Adept Software Development
Adept: (A)pplication (D)evelopment (E)nterprise to (P)ersonal (T)ransition. It is a system I am developing to leverage Enterprise developer skills to produce stand-alone software for other market segments. This is a general software development blog discussing issues about project, architecture, design and development. The emphasis will be in Java, but many of the issues will be more general. Almost all will be technical.
Saturday, November 21, 2009
If you feel the need to add a new feed to your site and know python, then this is a simple solution.
http://appengine-cookbook.appspot.com/recipe/simple-atom-feed-in-appengine/
Monday, November 16, 2009
appengine service for google maps/earth (kml)
This example is called TripKML. It reads pre-recorded GeoPt records and generates KML for Google Maps/Earth. The basic webapp is as normal:
class TripKML(webapp.RequestHandler):
def get(self):
try:
...
except DeadlineExceededError:
self.response.clear()
self.response.set_status(500)
self.message("This operation could not be completed in time...")
application = webapp.WSGIApplication([('/service/tripKML', TripKML)], debug = True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
First we parse the command line:
self.traveller = User.fromId(int(self.request.get('traveller')))
trip = self.request.get('trip')
As the code creates KML, tell the browser what do do with it:
self.response.headers['Content-Type'] = 'application/vnd.google-earth.kml+xml'
I have attached my lightweight class for generating XML. You give it the root XML tag name and attributes. Wrap everything in a folder for clarity in the tree. The last line is XML to be inserted (saved as )
rootElement = self.kml = xml('kml', xmlns = 'http://www.opengis.net/kml/2.2')
self.kml = rootElement.Folder
self.kml.name(trip)
self.kml.Style.IconStyle(id = 'noteStyle').Icon.href(iconUrl)
My style is to read the records and have factory code to call methods based on the record type. Because most records will be of one or two types, I have cached the parser method:
parsers = dict() query = Record.gql( 'WHERE userId=:1 AND trip=:2 ORDER BY time', self.traveller.id, trip) for self.record in query: try: parser = parsers[self.record.type] except KeyError: method = self.record.type + "RecordProcessor"; parser = getattr(self, method, self.defaultRecordProcessor) parsers[self.record.type] = parser parser()
A record type called "notes" generates a note indicated by an icon on the map:
def notesRecordProcessor(self):
self.kml.Placemark.name(self.record.title).styleUrl('noteStyle').\
description(self.record.notes).Point.coordinates(
"%f,%f" % (self.record.location.lon, self.record.location.lat))()
The “here” record processor does more work as it collects coordinates to make a line.
Back to the TripKml class, I also overlay kml generated by Picasa to display images:
albums = Album.forTrip(self.traveller.id, trip)
for album in albums:
try:
self.kml.NetworkLink.name(trip).Link.refreshMode('onInterval').\
refreshInterval(3600).hreflang(\
album.feedUri + '&alt=kml&kind=photo')
except Exception, e:
logging.warning('Can\'t access Picasa album for trip %s: %s' % (trip.name, e.message))
The last thing we need to do is generate the KML and send it to the browser:
self.response.out.write(str(self.kml))
I have attached TripKML.py as it is in use and xml.py for generating the XML.








