Advertisement
phr3ncj

vicinoa.py

May 30th, 2012
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.17 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. #  vicinoa.py
  5. #
  6. #  Copyright 2011 phra <phra@phra-EEEPC>
  7. #
  8. #  This program is free software; you can redistribute it and/or modify
  9. #  it under the terms of the GNU General Public License as published by
  10. #  the Free Software Foundation; either version 2 of the License, or
  11. #  (at your option) any later version.
  12. #
  13. #  This program is distributed in the hope that it will be useful,
  14. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. #  GNU General Public License for more details.
  17. #
  18. #  You should have received a copy of the GNU General Public License
  19. #  along with this program; if not, write to the Free Software
  20. #  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21. #  MA 02110-1301, USA.
  22. #
  23. import sys
  24. sys.path.append('/home/web/ltw1129/cgi-bin/descrittore/')
  25. from mod_python import apache as A, util
  26. from xml.dom.minidom import parse, parseString
  27. from encoding import smart_str
  28. from operator import itemgetter as IG
  29. import json, urllib2, math, csv, tempfile, codecs, rdflib, rdfextras, threading
  30.  
  31. lock = threading.Lock()
  32. listout = []
  33. RT = 6372795.477598
  34.  
  35. def toplain(listout):
  36.     s = '\n'.join('RESULT|||V') + '\n'
  37.     for tupla in listout:
  38.         s += 'ID: ' + smart_str(tupla[0]) + ', LAT: ' + smart_str(tupla[1]) + ', LONG: ' + smart_str(tupla[2]) + ', DISTANZA: ' + smart_str(tupla[11]) + '.\n'
  39.     return s
  40. def tojson(listout):
  41.     dictoutjson = {}
  42.     dictout = {}
  43.     meta = [('creator', 'Working Group LTW 2011/2012'), ('created', '20/12/2011'), ('version', '1.1'), ('source', 'http://vitali.web.cs.unibo.it/TechWeb12/Formati'),('valid', '31/12/2011')]
  44.     metadata = dict(meta)
  45.     for t in listout:
  46.         dictout[t[0]] = {'lat': t[1], 'long': t[2], 'category': smart_str(t[3]), 'name': t[4], 'opening': t[5], 'closing': t[6], 'address': t[7], 'tel': t[8], 'subcategory': t[9], 'note': t[10], 'distance': t[11]}
  47.     dictoutjson['metadata'] = metadata
  48.     dictoutjson['locations'] = dictout
  49.     return json.dumps(dictoutjson)
  50.  
  51. def toxml(listout):
  52.     s = '''<?xml version="1.0" encoding="UTF-8"?>
  53. <locations>
  54.     <metadata>
  55.         <creator>Working Group LTW 2011/2012</creator>
  56.         <created>12/20/2011</created>
  57.         <version>1.2</version>
  58.         <source>http://vitali.web.cs.unibo.it/TechWeb12/Formati</source>
  59.         <valid>02/21/2011</valid>
  60.         <note>Le date sono in formato americano: MM/GG/AAAA</note>
  61.     </metadata>
  62. '''
  63.     for t in listout:
  64.         s += '''<location id="%s" lat="%s" long="%s">
  65.         <category> %s </category>
  66.         <subcategory> %s </subcategory>
  67.         <name> %s </name>
  68.         <address> %s </address>
  69.         <tel> %s </tel>
  70.         <opening> %s </opening>
  71.         <closing> %s </closing>
  72.         </location>''' % (smart_str(t[0]),smart_str(t[1]),smart_str(t[2]),smart_str(t[3]),smart_str(t[9]),smart_str(t[4]),smart_str(t[7]),smart_str(t[8]),smart_str(t[5]),smart_str(t[6]))
  73.     s += '</locations>'
  74.     return s
  75.  
  76. def tocsv(listout):
  77.     s = '"id","category","name","address","lat","long","subcategory","note","opening","closing"'
  78.     for t in listout:
  79.         s += '"%s","%s","%s","%s","%s","%s","%s","%s","%s,"%s","%s","%s","%s","%s","%s","Working Group LTW 2011/2012","2011-12-20","2012-10-01","1.1","Unknown"\r\n' % (t[0],t[3],t[4],t[7],t[1],t[2],t[9],t[10],t[5],t[6])
  80.     return s
  81.  
  82. def tottl(listout):
  83.     s = '''@prefix : <http://www.essepuntato.it/resource/> .
  84. @prefix cs: <http://cs.unibo.it/ontology/> .
  85. @prefix dcterms: <http://purl.org/dc/terms/> .
  86. @prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
  87. @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
  88. @prefix this: <http://vitali.web.cs.unibo.it/twiki/pub/TechWeb12/DataSource2/posteBO2011.ttl> .
  89.  
  90. this:metadata
  91.      dcterms:creator "Working Group LTW 2011/2012"
  92.     ; dcterms:created "2011-12-20"^^xsd:date
  93.     ; dcterms:description "1.2"
  94.     ; dcterms:valid "2011-02-21"^^xsd:date
  95.     ; dcterms:source "http://www.aziendedibologna.it/poste_bologna_e_provincia.htm".
  96. '''
  97.     for id, value in dictout.items():
  98.         s += ''':%s cs:closing "%s";
  99.         cs:opening "%s";
  100.         vcard:category "%s";
  101.         vcard:extended-address "%s";
  102.         vcard:fax "%s";
  103.         vcard:fn "%s";
  104.         vcard:latitude "%s";
  105.         vcard:longitude "%s";
  106.         vcard:tel "%s" .
  107. ''' % (value['id'], value['closing'], value['opening'], value['category'], value['address'], value['fax'], value['name'], value['lat'], value['long'], value['tel'])
  108.     return s
  109.  
  110. def piglia(host,listout,radlatA,radlonA,req,MAX,DISTANZA,CATEGORY):
  111.     reqq = urllib2.Request(host)
  112.     reqq.add_header('Accept', 'text/plain application/json application/xml text/turtle text/csv text/comma-separated-values')
  113.     try:
  114.         r = urllib2.urlopen(reqq)
  115.     except urllib2.HTTPError, e:
  116.         req.status = A.HTTP_INTERNAL_SERVER_ERROR
  117.         req.write('500: INTERNAL SERVER ERROR\r\n')
  118.         req.write('%s non raggiungibile. (errore: %d)\r\n' % (host,e.code))
  119.         raise A.SERVER_RETURN, A.DONE
  120.     except urllib2.URLError, e:
  121.         req.status = A.HTTP_INTERNAL_SERVER_ERROR
  122.         req.write('500: INTERNAL SERVER ERROR\r\n')
  123.         req.write('%s non raggiungibile. (errore: %d)\r\n' % (host,e.args[0]))
  124.         raise A.SERVER_RETURN, A.DONE
  125.  
  126.     if 'application/json' in smart_str(r.info().getheader('Content-Type')):
  127.         data = smart_str(r.read())
  128.         dump = json.loads(data)
  129.         locations = dump['locations']
  130.         metadata = dump['metadata']
  131.         for id, value in locations.items():
  132.             latB = float(value['lat'])
  133.             lonB = float(value['long'])
  134.             category = smart_str(value['category']).lower()
  135.             radlatB = latB * (math.pi / 180.0)
  136.             radlonB = lonB * (math.pi / 180.0)
  137.             a = RT * math.acos(math.sin(radlatA) * math.sin(radlatB) + math.cos(radlatA) * math.cos(radlatB) * math.cos(radlonA - radlonB))
  138.             if (DISTANZA == 'none') or (a < float(DISTANZA)):
  139.                 if category == CATEGORY or CATEGORY == '*' or CATEGORY == 'none':
  140.                     lat = smart_str(value['lat'])
  141.                     long = smart_str(value['long'])
  142.                     category = smart_str(value['category'])
  143.                     name = smart_str(value['name'])
  144.                     opening = smart_str(value['opening'])
  145.                     closing = smart_str(value['closing'])
  146.                     tel = smart_str(value['tel'])
  147.                     address = smart_str(value['address'])
  148.                     lock.acquire()
  149.                     listout.append((id, lat, long, category, name, opening, closing, address, tel, '', '', a))
  150.                     lock.release()
  151.     elif 'application/xml' in smart_str(r.info().getheader('Content-Type')):
  152.         data = r.read()
  153.         dom = parseString(smart_str(data))
  154.         root = dom.getElementsByTagName('locations')[0]
  155.         metadata = root.getElementsByTagName('metadata')[0]
  156.         locations = dom.getElementsByTagName('location')
  157.         for location in locations:
  158.             category = smart_str(location.getElementsByTagName('category')[0]).lower()
  159.             id = smart_str(location.getAttribute('id')).lower()
  160.             latB = float(location.getAttribute('lat'))
  161.             lonB = float(location.getAttribute('long'))
  162.             radlatB = latB * (math.pi / 180.0)
  163.             radlonB = lonB * (math.pi / 180.0)
  164.             a = RT * math.acos(math.sin(radlatA) * math.sin(radlatB) + math.cos(radlatA) * math.cos(radlatB) * math.cos(radlonA - radlonB))
  165.             #req.write("la distanza di %s e' di: %f \r\n" % (id,a))
  166.             if DISTANZA == 'none' or a < float(DISTANZA):
  167.                 if category == CATEGORY or CATEGORY == '*' or CATEGORY == 'none':
  168.                     lat = smart_str(location.getAttribute('lat'))
  169.                     long = smart_str(location.getAttribute('long'))
  170.                     category = smart_str(location.getElementsByTagName('category')[0].childNodes[0].data)
  171.                     name = smart_str(location.getElementsByTagName('name')[0].childNodes[0].data)
  172.                     address = smart_str(location.getElementsByTagName('address')[0].childNodes[0].data)
  173.                     closing = smart_str(location.getElementsByTagName('closing')[0].childNodes[0].data)
  174.                     category = smart_str(location.getElementsByTagName('category')[0].childNodes[0].data)
  175.                     subcategory = smart_str(location.getElementsByTagName('subcategory')[0].childNodes[0].data)
  176.                     tel = smart_str(location.getElementsByTagName('tel')[0].childNodes[0].data)
  177.                     opening = ''
  178.                     for open in location.getElementsByTagName('opening')[0].childNodes:
  179.                         opening += open.data + ' '
  180.                     lock.acquire()
  181.                     listout.append((id, lat, long, category, name, opening, closing, address, tel, subcategory, '', a))
  182.                     lock.release()
  183.  
  184.  
  185.     elif 'text/csv' in smart_str(r.info().getheader('Content-Type')):
  186.         data = r.read()
  187.         temp = tempfile.TemporaryFile()
  188.         temp.write(smart_str(data))
  189.         enc = 'utf-8'
  190.         temp.seek(0)
  191.         temp.readline()
  192.         attrs = ["id","category","name","address","lat","long","subcategory","note","opening","closing","creator","created","valid","version","source"]
  193.         dump = csv.DictReader(temp, attrs, lineterminator='\n')
  194.         for line in dump:
  195.             id = smart_str(line['id']).lower()
  196.             latB = float(line['lat'])
  197.             lonB = float(line['long'])
  198.             radlatB = latB * (math.pi / 180.0)
  199.             radlonB = lonB * (math.pi / 180.0)
  200.             a = RT * math.acos(math.sin(radlatA) * math.sin(radlatB) + math.cos(radlatA) * math.cos(radlatB) * math.cos(radlonA - radlonB))
  201.             if (DISTANZA == 'none') or (a < float(DISTANZA)):
  202.                 if smart_str(line['category']).lower() == CATEGORY or CATEGORY == '*' or CATEGORY == 'none':
  203.                     lat = smart_str(line['lat'])
  204.                     long = smart_str(line['long'])
  205.                     category = smart_str(line['category'])
  206.                     name = smart_str(line['name'])
  207.                     opening = smart_str(line['opening'])
  208.                     closing = smart_str(line['closing'])
  209.                     tel = ''
  210.                     address = smart_str(line['address'])
  211.                     lock.acquire()
  212.                     listout.append((id, lat, long, category, name, opening, closing, address, tel, '', '', a))
  213.                     lock.release()
  214.         temp.close()
  215.     elif 'text/turtle' in smart_str(r.info().getheader('Content-Type')):
  216.         graph = rdflib.Graph()
  217.         dump = graph.parse(r, format='n3')
  218.         rdflib.plugin.register('sparql', rdflib.query.Processor, 'rdfextras.sparql.processor', 'Processor')
  219.         rdflib.plugin.register('sparql', rdflib.query.Result, 'rdfextras.sparql.query', 'SPARQLQueryResult')
  220.         foo = dump.query("""
  221.                      PREFIX vcard: <http://www.w3.org/2006/vcard/ns#>
  222.                      PREFIX cs: <http://cs.unibo.it/ontology/>
  223.                      PREFIX : <http://www.essepuntato.it/resource/>
  224.                          SELECT ?x ?fn ?latitude ?longitude ?tel ?category ?fax ?opening ?closing ?address
  225.                      WHERE {
  226.                         ?x vcard:fn ?fn ;
  227.                         vcard:latitude ?latitude ;
  228.                         vcard:longitude ?longitude ;
  229.                         vcard:category ?category ;
  230.                         vcard:tel ?tel ;
  231.                         vcard:fax ?fax ;
  232.                         vcard:extended-address ?address ;
  233.                         cs:opening ?opening ;
  234.                         cs:closing ?closing .
  235.                      }
  236.             """)
  237.         for each in foo.topUnion:
  238.             id = smart_str(each['x']).split('/')[4]
  239.             radlatB = float(smart_str(each['latitude'])) * (math.pi / 180.0)
  240.             radlonB = float(smart_str(each['longitude'])) * (math.pi / 180.0)
  241.             a = RT * math.acos(math.sin(radlatA) * math.sin(radlatB) + math.cos(radlatA) * math.cos(radlatB) * math.cos(radlonA - radlonB))
  242.             if (DISTANZA == 'none') or (a < float(DISTANZA)):
  243.                 if smart_str(each['category']).lower() == CATEGORY or CATEGORY == '*' or CATEGORY == 'none':
  244.                     temp = {}
  245.                     id = smart_str(each['x']).split('/')[4]
  246.                     lat = smart_str(each['latitude'])
  247.                     long = smart_str(each['longitude'])
  248.                     tel = smart_str(each['tel'])
  249.                     name = smart_str(each['fn'])
  250.                     address = smart_str(each['address'])
  251.                     category = smart_str(each['category'])
  252.                     fax = smart_str(each['fax'])
  253.                     opening = smart_str(each['opening'])
  254.                     closing = smart_str(each['closing'])
  255.                     lock.acquire()
  256.                     listout.append((id, lat, long, category, name, opening, closing, address, tel, '', '', a))
  257.                     lock.release()
  258.     else:
  259.         req.write('501: Internal Server Error\n')
  260.         req.write("l'aggregatore %s vuole fornire dati in %s, non compatibile con il protocollo." % (host, smart_str(r.info().getheader('Content-Type'))))
  261.         req.status = A.HTTP_INTERNAL_SERVER_ERROR
  262.         raise A.SERVER_RETURN, A.DONE
  263.  
  264. def index(req):
  265.  
  266.     if not (('application/json' in req.headers_in['Accept']) or ('application/xml' in req.headers_in['Accept']) or ('text/csv' in req.headers_in['Accept']) or ('text/turtle' in req.headers_in['Accept']) or ('text/x-python' in req.headers_in['Accept'])):
  267.         req.content_type = 'text/plain; charset="UTF-8"'
  268.         req.headers_out.add("Access-Control-Allow-Origin","*")
  269.         req.status = A.HTTP_NOT_ACCEPTABLE
  270.         req.write('406: NOT ACCEPTABLE\r\n')
  271.         req.write('intersezione tra content-type vuota.\r\n')
  272.         raise A.SERVER_RETURN, A.DONE
  273.  
  274.     content_type = req.headers_in['Accept']
  275.     req.content_type = 'text/plain; charset="UTF-8"'
  276.     req.headers_out.add("Access-Control-Allow-Origin","*")
  277.     if req.method != 'GET':
  278.         req.status = A.HTTP_METHOD_NOT_ALLOWED
  279.         req.write('405: METHOD NOT ALLOWED\r\n')
  280.         req.write('metodo %s non permesso.\r\n' % req.method)
  281.         raise A.SERVER_RETURN, A.DONE
  282.  
  283.     try:
  284.         parms = util.FieldStorage(req)
  285.         AGGRs = smart_str(parms.getfirst('aggr')).split('/')
  286.         latA = float(parms.getfirst('lat'))
  287.         lonA = float(parms.getfirst('long'))
  288.         MAX = smart_str(parms.getfirst('max')).lower()
  289.         DISTANZA = smart_str(parms.getfirst('distance')).lower()
  290.         CATEGORY = smart_str(parms.getfirst('category')).lower()
  291.     except:
  292.         req.status = A.HTTP_NOT_ACCEPTABLE
  293.         req.write('406: NOT ACCEPTABLE\r\n')
  294.         req.write('parametri errati.')
  295.         req.write('i parametri sono: lat: %s, long: %s[, max: %s, distance: %s]\r\nex: http://ltw1129.web.cs.unibo.it/vicinoa/ltw1129-farmacie/params/44.500456/11.277643/10/5000\r\n' % (smart_str(parms.getfirst('lat')), smart_str(parms.getfirst('long')), smart_str(parms.getfirst('max')), smart_str(parms.getfirst('distance'))))
  296.         raise A.SERVER_RETURN, A.DONE
  297.     hosts = []
  298.     host = 'http://vitali.web.cs.unibo.it/twiki/pub/TechWeb12/MetaCatalogo1112/metaCatalogo.xml'
  299.     reqq = urllib2.Request(host)
  300.     reqq.add_header('Accept', 'application/xml')
  301.     try:
  302.         r = urllib2.urlopen(reqq)
  303.     except urllib2.HTTPError, e:
  304.         req.status = A.HTTP_INTERNAL_SERVER_ERROR
  305.         req.write('500: INTERNAL SERVER ERROR\r\n')
  306.         req.write('%s non raggiungibile. (errore: %d)\r\n' % (host,e.code))
  307.         raise A.SERVER_RETURN, A.DONE
  308.     except urllib2.URLError, e:
  309.         req.status = A.HTTP_INTERNAL_SERVER_ERROR
  310.         req.write('500: INTERNAL SERVER ERROR\r\n')
  311.         req.write('%s non raggiungibile. (errore: %d)\r\n' % (host,e.args[0]))
  312.         raise A.SERVER_RETURN, A.DONE
  313.     data = r.read()
  314.     dom = parseString(smart_str(data))
  315.     root = dom.getElementsByTagName('metaCatalogo')[0]
  316.     catas = root.getElementsByTagName('catalogo')
  317.     for AGGR in AGGRs:
  318.         for cata in catas:
  319.             if smart_str(cata.getAttribute('id')).lower() in smart_str(AGGR).lower():
  320.                 host = smart_str(cata.getAttribute('url'))
  321.                 reqq = urllib2.Request(host)
  322.                 reqq.add_header('Accept', 'application/xml')
  323.                 try:
  324.                     r = urllib2.urlopen(reqq)
  325.                 except urllib2.HTTPError, e:
  326.                     req.status = A.HTTP_INTERNAL_SERVER_ERROR
  327.                     req.write('500: INTERNAL SERVER ERROR\r\n')
  328.                     req.write('%s non raggiungibile. (errore: %d)\r\n' % (host,e.code))
  329.                     raise A.SERVER_RETURN, A.DONE
  330.                 except urllib2.URLError, e:
  331.                     req.status = A.HTTP_INTERNAL_SERVER_ERROR
  332.                     req.write('500: INTERNAL SERVER ERROR\r\n')
  333.                     req.write('%s non raggiungibile. (errore: %d)\r\n' % (host,e.args[0]))
  334.                     raise A.SERVER_RETURN, A.DONE
  335.                 catalogo = r.read()
  336.                 dom = parseString(smart_str(catalogo))
  337.                 root = dom.getElementsByTagName('catalogo')[0]
  338.                 foo = root.getElementsByTagName('aggregatori')[0]
  339.                 aggrs = foo.getElementsByTagName('aggregatore')
  340.                 for aggr in aggrs:
  341.                     if smart_str(aggr.getAttribute('id')).lower() == smart_str(AGGR).lower():
  342.                         url = smart_str(aggr.getAttribute('url'))
  343.                         hosts.append(url)
  344.  
  345.     radlatA = latA * (math.pi / 180.0)
  346.     radlonA = lonA * (math.pi / 180.0)
  347.     threads = []
  348.     for host in hosts:
  349.         t = threading.Thread(target=piglia,args=(host,listout,radlatA,radlonA,req,MAX,DISTANZA,CATEGORY))
  350.         t.start()
  351.         threads.append(t)
  352.     for t in threads:
  353.         threading.Thread.join(t)
  354.     if MAX != 'none':
  355.         listout.sort(key=IG(11))
  356.         del(listout[int(MAX):])
  357.  
  358.     if 'application/json' in content_type:
  359.         req.content_type = 'application/json; charset=utf-8'
  360.         req.write(tojson(listout))
  361.     elif 'application/xml' in content_type:
  362.         req.content_type = 'application/xml; charset=utf-8'
  363.         req.write(toxml(listout))
  364.     elif 'text/csv' in content_type:
  365.         req.content_type = 'text/cvs; charset=utf-8'
  366.         req.write(tocsv(listout))
  367.     elif 'text/turtle' in content_type:
  368.         req.content_type = 'text/turtle; charset=utf-8'
  369.         req.write(tottl(listout))
  370.     else:
  371.         req.content_type = 'text/plain; charset=utf-8'
  372.         req.write(toplain(listout))
  373.  
  374.     req.status = A.OK
  375.     raise A.SERVER_RETURN, A.DONE
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement