spatial-d4science/ckanext/spatial/plugin.py

124 lines
4.3 KiB
Python

import os
from logging import getLogger
from pylons.i18n import _
from genshi.input import HTML
from genshi.filters import Transformer
import ckan.lib.helpers as h
from ckan.lib.helpers import json
from ckan.plugins import implements, SingletonPlugin
from ckan.plugins import IRoutes, IConfigurer
from ckan.plugins import IGenshiStreamFilter
from ckan.plugins import IPackageController
from ckan.logic import ValidationError
from ckan.logic.action.update import package_error_summary
import html
from ckanext.spatial.lib import save_package_extent
log = getLogger(__name__)
class SpatialQuery(SingletonPlugin):
implements(IRoutes, inherit=True)
implements(IPackageController, inherit=True)
def before_map(self, map):
map.connect('api_spatial_query', '/api/2/search/{register:dataset|package}/geo',
controller='ckanext.spatial.controllers.api:ApiController',
action='spatial_query')
return map
def create(self, package):
self.check_spatial_extra(package)
def edit(self, package):
self.check_spatial_extra(package)
def check_spatial_extra(self,package):
if not package.id:
log.warning('Couldn\'t store spatial extent because no id was provided for the package')
return
# TODO: deleted extra
for extra in package.extras_list:
if extra.key == 'spatial':
if extra.state == 'active':
try:
log.debug('Received: %r' % extra.value)
geometry = json.loads(extra.value)
except ValueError,e:
error_dict = {'spatial':[u'Error decoding JSON object: %s' % str(e)]}
raise ValidationError(error_dict, error_summary=package_error_summary(error_dict))
except TypeError,e:
error_dict = {'spatial':[u'Error decoding JSON object: %s' % str(e)]}
raise ValidationError(error_dict, error_summary=package_error_summary(error_dict))
try:
save_package_extent(package.id,geometry)
except ValueError,e:
error_dict = {'spatial':[u'Error creating geometry: %s' % str(e)]}
raise ValidationError(error_dict, error_summary=package_error_summary(error_dict))
except Exception, e:
error_dict = {'spatial':[u'Error: %s' % str(e)]}
raise ValidationError(error_dict, error_summary=package_error_summary(error_dict))
elif extra.state == 'deleted':
# Delete extent from table
save_package_extent(package.id,None)
break
def delete(self, package):
save_package_extent(package.id,None)
class DatasetExtentMap(SingletonPlugin):
implements(IGenshiStreamFilter)
implements(IConfigurer, inherit=True)
def filter(self, stream):
from pylons import request, tmpl_context as c
routes = request.environ.get('pylons.routes_dict')
if routes.get('controller') == 'package' and \
routes.get('action') == 'read' and c.pkg.id:
extent = c.pkg.extras.get('spatial',None)
if extent:
data = {'extent': extent,
'title': _('Geographic extent')}
stream = stream | Transformer('body//div[@class="dataset"]')\
.append(HTML(html.PACKAGE_MAP % data))
stream = stream | Transformer('head')\
.append(HTML(html.PACKAGE_MAP_EXTRA_HEADER % data))
stream = stream | Transformer('body')\
.append(HTML(html.PACKAGE_MAP_EXTRA_FOOTER % data))
return stream
def update_config(self, config):
here = os.path.dirname(__file__)
template_dir = os.path.join(here, 'templates')
public_dir = os.path.join(here, 'public')
if config.get('extra_template_paths'):
config['extra_template_paths'] += ','+template_dir
else:
config['extra_template_paths'] = template_dir
if config.get('extra_public_paths'):
config['extra_public_paths'] += ','+public_dir
else:
config['extra_public_paths'] = public_dir