changeset 55:2f4c427dec44

wrangled kml construction into template and method kml currently constructed live
author casties
date Wed, 29 Sep 2010 21:09:44 +0200
parents 54940a99f12d
children 8eca8a1fbf50 e0a79d926902
files RestDbGisApi.py RestDbInterface.py zpt/GIS_schema_table.zpt zpt/KML_schema_table.zpt
diffstat 4 files changed, 167 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/RestDbGisApi.py	Mon Sep 20 15:39:58 2010 +0200
+++ b/RestDbGisApi.py	Wed Sep 29 21:09:44 2010 +0200
@@ -24,6 +24,15 @@
                    "coord_lon": "numeric"
                    }
 
+def kmlEncode(s):
+    """returns string encoded for displaying in KML attribute"""
+    res = s.replace("'","__Apostroph__")
+    res = res.replace('"','__DoubleApostroph__')
+    res = res.replace(';','__$$__')
+    res = res.replace('&','&')
+    return res
+
+
 class RestDbGisApi(RestDbInterface):
     """Object for RESTful GIS database queries
     path schema: /db/{schema}/{table}/
@@ -35,13 +44,15 @@
 
     # data templates
     GIS_schema_table = PageTemplateFile('zpt/GIS_schema_table', globals())
+    KML_schema_table = PageTemplateFile('zpt/KML_schema_table', globals())
+    
     # and scripts
     def KML_URL_schema_table(self,schema,table):
         """KML_URL table function"""
         self.REQUEST.RESPONSE.setHeader("Content-Type", "text/plain")
         id = self.REQUEST.get('id',[])           
         doc = self.REQUEST.get('doc',None)
-        return self.getKmlUrl(schema=schema,table=table,id=id,doc=doc)
+        return self.getLiveKmlUrl(schema=schema,table=table,id=id,doc=doc)
 
 
     def checkTableMetaPermission(self,action,schema,table,user=None):
@@ -136,17 +147,6 @@
             return None
     
     
-
-    # Methods for GoogleMaps creation
-#    def showGoogleMap(self,schema='chgis',table='mpdl',id=[],doc=None):
-#        logging.debug("showGoogleMap")
-#        data = self.getDataForGoogleMap(schema,table,id,doc)
-#        kmlFileName=self.getKMLname(data=data,table=table)
-#        initializeStringForGoogleMaps="""onload=\"initialize(\'http://chinagis.mpiwg-berlin.mpg.de/chinagis/REST/daten/"""+kmlFileName+"""\')\""""#+str(data)
-#        initializeStringForGoogleMaps=initializeStringForGoogleMaps.replace("None","0")
-#        googleMap_page=self.htmlHead()+str(self.getGoogleMapString(kml=initializeStringForGoogleMaps))
-#        return googleMap_page
-
     def getKmlUrl(self,schema='chgis',table='mpdl',id=[],doc=None):
         logging.debug("getKmlUrl")
         data = self.getDataForGoogleMap(schema,table,id,doc)
@@ -154,11 +154,16 @@
         baseUrl = self.absolute_url()
         return "%s/daten/%s"%(baseUrl,kml)
 
-    def getDataForGoogleMap(self,schema='chgis',table='mpdl',id=[],doc=None):
+    def getLiveKmlUrl(self,schema='chgis',table='mpdl',id=None,doc=None):
+        logging.debug("getLiveKmlUrl")
+        baseUrl = self.absolute_url()
+        return "%s/db/%s/%s?format=KML"%(baseUrl,schema,table)
+
+    def getDataForGoogleMap(self,schema='chgis',table='mpdl',id=None,doc=None):
         logging.debug("getDataForGoogleMap")
         qstr="SELECT * FROM "+schema+"."+table
         try:
-            if id!=[]:
+            if id is not None:
                 qstr=qstr+" WHERE "
                 for id_item in id.split(","):
                     if table=='mpdl':
@@ -171,6 +176,113 @@
         except:
             return qstr
 
+    def getKmlData(self, schema, table, ids=None, gisIdField=None, latField=None, lonField=None):
+        """returns data structure for KML template"""
+        logging.debug("getKMLdata")
+        # Mapping a set of points from table-based SQL-query:
+        qstr='SELECT * FROM "%s"."%s"'%(schema,table)
+        idList = None
+        if ids is not None:
+            qstr += ' WHERE '
+            if table=='mpdl':
+                qstr += 'mpdl_xmlsource_id IN ('
+            else:
+                qstr += 'CAST(id AS text) IN ('
+                
+            idList = ids.split(",")
+            qstr += ','.join(['%s' for i in idList])
+            qstr += ')'
+
+        data = self.executeSQL(qstr,idList)
+        
+        fieldMap = self.getFieldNameMap(data['fields'])
+        
+        if (gisIdField is None) and (latField is None or lonField is None):
+            # no fields given - choose automagically
+            # gis id in metadata first
+            SQL='SELECT "attribute with gis_id" FROM public.metadata WHERE tablename = %s'
+            res = self.executeSQL(SQL, (table,))
+            if len(res['rows']) > 0:
+                gisIdField = res['rows'][0][0]
+            else:
+                logging.warning("no entry in metadata table for table %s"%table)
+                # try field names
+                if 'latitude' in fieldMap and 'longitude' in fieldMap:
+                    latField = 'latitude'
+                    lonField = 'longitude'
+                elif 'x_coord' in fieldMap and 'y_coord' in fieldMap:
+                    latField = 'x_coord'
+                    lonField = 'y_coord'
+                else:
+                    logging.error("getKMLdata unable to find position fields")
+                    return None
+        
+        # convert field names to row indexes
+        gisIdIdx = fieldMap.get(gisIdField,None)
+        latIdx = fieldMap.get(latField,None)
+        lonIdx = fieldMap.get(lonField,None)
+        logging.debug("gisidfield=%s idx=%s"%(gisIdField,gisIdIdx))
+        
+        # convert data
+        kmlData = []
+        for dataset in data['rows']:
+            if gisIdIdx is not None:
+                gisID = dataset[gisIdIdx]
+                coords=self.getPoint4GISid(gisID)
+                if coords!=None:
+                    xCoord=coords[0]
+                    yCoord=coords[1]
+                    
+            elif latIdx is not None:
+                xCoord = dataset[lonIdx]
+                yCoord = dataset[latIdx]
+                
+            else:
+                logging.error("getKMLdata unable to find position")
+                return None
+                    
+            if float(xCoord) == 0.0:
+                continue
+            
+            if float(yCoord) == 0.0:
+                continue
+
+            kmlPlace = {}
+            
+            # description
+            desc = ''
+            i = -1
+            for value in dataset:
+                i += 1
+                name = data['fields'][i][0]
+                logging.debug("value=%s"%value)
+                if value != None:
+                    if name.find('name')>-1:
+                        desc += "<name>%s</name>\n"%value
+                        continue
+                    elif name.find('place')>-1:
+                        desc += "<name>%s</name>\n"%value
+                        continue
+            
+                    val = "%s: %s"%(name, value)
+                    if val.find('http')>-1:
+                        val ='<a href="' + val + '" target="_blank">' + val + '</a>'
+                        
+                    desc += kmlEncode(val)
+                    desc += '<br/>\n'
+                      
+            kmlPlace['description'] = "<![CDATA[%s]]>"%desc
+            kmlPlace['icon'] = '#marker_icon'
+            kmlPlace['coord_x'] = str(xCoord)
+            kmlPlace['coord_y'] = str(yCoord)
+            kmlPlace['coord_z'] = '0'
+            kmlData.append(kmlPlace)
+    
+        #logging.debug("kmlData=%s"%(repr(kmlData)))
+        return kmlData
+        
+
+
     def getKMLname(self,data=[],table=""):
         logging.debug("getKMLname")
         #session=context.REQUEST.SESSION
@@ -209,6 +321,7 @@
                         kml4Marker=kml4Marker+"<Placemark>"
                         kml4Marker=kml4Marker+"<description> <![CDATA[<b>"
                         for values in dataset:
+                            #logging.debug("values=%s"%repr(values))
                             if values != (None, None):
                                 if str(values).find('name')>-1:
                                     kml4Marker=kml4Marker+"<name>"+str(values[1])+"</name>\n"
--- a/RestDbInterface.py	Mon Sep 20 15:39:58 2010 +0200
+++ b/RestDbInterface.py	Wed Sep 29 21:09:44 2010 +0200
@@ -151,6 +151,16 @@
             
         return cursor
     
+    def getFieldNameMap(self,fields):
+        """returns a dict mapping field names to row indexes"""
+        map = {}
+        i = 0
+        for f in fields:
+            map[f[0]] = i
+            i += 1
+            
+        return map
+    
     def executeSQL(self, query, args=None, hasResult=True, autocommit=True):
         """execute query with args on database and return all results.
         result format: {"fields":fields, "rows":data}"""
@@ -168,6 +178,8 @@
             # get all data in an array
             data = cur.fetchall()
             cur.close()
+            #logging.debug("fields: %s"%repr(fields))
+            logging.debug("rows: %s"%repr(data))
             return {"fields":fields, "rows":data}
         else:
             cur.close()
--- a/zpt/GIS_schema_table.zpt	Mon Sep 20 15:39:58 2010 +0200
+++ b/zpt/GIS_schema_table.zpt	Wed Sep 29 21:09:44 2010 +0200
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html tal:define="root here/getRestDbUrl; layout python:request.get('layout','pre'); element_id python:request.get('element_id',None);
         schema options/schema; table options/table; id python:request.get('id',[]); doc python:request.get('doc',None);
-        kmlUrl python:here.getKmlUrl(schema=schema,table=table,id=id,doc=doc);
+        kmlUrl python:here.getLiveKmlUrl(schema=schema,table=table,id=id,doc=doc);
 ">
  <head>
     <meta http-equiv="content-type" content="text/html; charset=utf-8">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/KML_schema_table.zpt	Wed Sep 29 21:09:44 2010 +0200
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:tal="http://xml.zope.org/namespaces/tal" 
+  tal:define="schema options/schema; table options/table; data python:here.getKmlData(schema=schema,table=table);">
+  <Document>
+    <Style id="marker_icon">
+      <IconStyle>
+        <scale>15</scale>
+        <Icon>
+          <href>http://chinagis.mpiwg-berlin.mpg.de/chinagis/images/dot_red.png</href>
+        </Icon>
+      </IconStyle>
+    </Style>
+    <Placemark tal:repeat="place data">
+      <description tal:content="place/description"><![CDATA[<b>ERD-0815: ERD-0815</a><br>
+Jingshi: Jingshi</a><br>
+nma_1898541: nma_1898541</a><br>
+Forbidden City: Forbidden City</a><br>
+1406: 1406</a><br>
+720000: 720000</a><br>
+]]></description>
+      <styleURL tal:content="place/icon">#marker_icon</styleURL>
+      <Point>
+        <coordinates tal:content="string:${place/coord_x},${place/coord_y},${place/coord_z}">116.38,39.92,0</coordinates>
+      </Point>
+    </Placemark>
+  </Document>
+</kml>