Paste number 13249: Load addresses from AddressBook framework, publish on Google Maps

Index of paste annotations: 1

Paste number 13249: Load addresses from AddressBook framework, publish on Google Maps
Pasted by: Ralph Richard Cook
When:12 years, 1 month ago
Share:Tweet this! | http://paste.lisp.org/+A81
Channel:None
Paste contents:
Raw Source | XML | Display As
;;; Ralph Richard Cook
;;; Code to read addresses out of the Mac Address Book using the AddressBook framework,
;;; convert the addresses to latitute and longitude using the ontok REST to CSV geocoder,
;;; then use the co-ordinates to send a 'markers' XML data fragment to the Google Maps
;;; API to put up markers in a map.
;;; The process starts with a call to the async.html example from the Google Maps API, it will
;;; do an AJAX call back to data.xml, which is mapped in portable aserve to the build-marker function.
;;; Using AddressBook classes
;;; http://www.macdevcenter.com/pub/a/mac/2002/08/27/cocoa.html?page=1
;;; Using AddressBook classes in OpenMCL, the end of the thread
;;; http://clozure.com/pipermail/openmcl-devel/2005-November/003082.html
;;; The Google Maps API documentation
;;; http://www.google.com/apis/maps/documentation/
;;; The ontok geocoding REST API, 10 addresses at a time for free
;;; http://www.ontok.com/geocode/restapi



(defun build-query ()
  (ccl::with-autorelease-pool
    (let* ((book (ccl::send (ccl::find-class 'ns::ab-address-book) 'shared-address-book))
           (se (ccl::send (ccl::find-class 'ns::ab-person) :search-element-for-property #&kABAddressProperty 
                                                           :label #&kABAddressWorkLabel 
                                                           :key #&kABAddressStateKey 
                                                           :value #@"GA" 
                                                           :comparison #$kABEqual))
           (georgians (ccl::send book :records-matching-search-element se))
           ; Our geocoder maxes out on 10 reccords, and this is a demo
           (qu (loop for i from 0 to (1- (min 10 (ccl::send georgians 'count))) collect (cons '|q| (build-address (ccl::send georgians :object-at-index i))))))
      (push '(|key| . "") qu)
      (push '(|fmt| . "CSV") qu)
      qu)))

(defun build-address (person)
  (let* ((addr-mv (ccl::send person :value-for-property #&kABAddressProperty))
         (primary-id (ccl::send addr-mv 'primary-identifier))
         (idx (ccl::send addr-mv :index-for-identifier primary-id))
         (primary-addr (ccl::send addr-mv :value-at-index idx))
         (street (ccl::send primary-addr :object-for-key #&kABAddressStreetKey))
         (city (ccl::send primary-addr :object-for-key #&kABAddressCityKey))
         (state (ccl::send primary-addr :object-for-key #&kABAddressStateKey)))
    (format nil "~a ~a ~a" (ccl::lisp-string-from-nsstring street)
                           (ccl::lisp-string-from-nsstring city)
                           (ccl::lisp-string-from-nsstring state))))

(defun get-csvs ()
  (net.aserve.client:do-http-request "http://www.ontok.com/geocoder" :query (build-query)))

(defun build-marker (req ent)
  (net.aserve:with-http-response (req ent)
    (net.aserve:with-http-body (req ent)
      (let ((stream (net.aserve:request-reply-stream req)))
	(princ "<markers>" stream)
        (dolist (csv (cl-ppcre:split #\Newline (get-csvs)))
          (let ((values (cl-ppcre:split "," csv)))
            (format stream "<marker lat=\"~a\" lng=\"~a\"/>" (second values) (first values))))
        (princ "</markers>" stream)))))

(net.aserve:publish :path "/maptest/data.xml" :function #'build-marker)
(net.aserve:publish-file :path "/maptest/async.html" :file "/Users/rrc/lisp/maptest/async.html")


  
  

Annotations for this paste:

Annotation number 1: images
Pasted by: will
When:11 years, 11 months ago
Share:Tweet this! | http://paste.lisp.org/+A81/1
Paste contents:
Raw Source | Display As
fear helps you

Colorize as:
Show Line Numbers

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.