Changeset 2529


Ignore:
Timestamp:
30/05/07 17:00:30 (12 years ago)
Author:
spascoe
Message:

CSML_API service shows an example of a browsable dataset with subsetting.
The WMS will create a capabilities document with valid <Contents> taken from
the CSML doc.

Location:
TI05-delivery/ows_framework/trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • TI05-delivery/ows_framework/trunk/ows_common/ows_common/contents.py

    r2502 r2529  
    1515class Contents(object): 
    1616    """ 
    17     @ivar datasetSummary 
    18     @type datasetSummary: Iterable of DatasetSummary objects 
    19     @ivar otherSource: A URL 
    20     @type otherSource: None or str 
     17    @ivar datasetSummaries 
     18    @type datasetSummaries: Iterable of DatasetSummary objects 
     19    @ivar otherSources: URLs 
     20    @type otherSource: iterable of str 
    2121 
    2222    """ 
    23     def __init__(self, datasetSummary=[], otherSource=None): 
    24         self.datasetSummary = datasetSummary 
    25         self.otherSource = otherSource 
     23    def __init__(self, datasetSummaries=[], otherSources=[]): 
     24        self.datasetSummaries = datasetSummaries 
     25        self.otherSources = otherSources 
    2626 
    2727class DatasetSummary(Description): 
     
    3333    @ivar boundingBoxes 
    3434    @type boundingBoxes: iterable of BoundingBox objects 
    35     @ivar wsg84BoundingBoxes 
    36     @type wsg84BoundingBoxes: iterable of WSG84BoundingBox objects 
     35    @ivar wgs84BoundingBoxes 
     36    @type wgs84BoundingBoxes: iterable of WSG84BoundingBox objects 
    3737    """ 
    3838 
    39     def __init__(self, title=None, abstract=None, keywords=Keywords(), 
     39    def __init__(self, titles=[], abstracts=[], keywords=Keywords(), 
    4040                 identifier=None, metadata=[], boundingBoxes=[], 
    41                  wsg84BoundingBoxes=[]): 
    42         super(DatasetSummary, self).__init__(title, abstract, keywords) 
     41                 wgs84BoundingBoxes=[]): 
     42        super(DatasetSummary, self).__init__(titles, abstracts, keywords) 
    4343 
    4444        self.identifier = identifier 
    4545        self.metadata = metadata 
    4646        self.boundingBoxes = boundingBoxes 
    47         self.wsg84BoundingBoxes = wsg84BoundingBoxes 
    48  
    49          
    50          
    51                   
     47        self.wgs84BoundingBoxes = wgs84BoundingBoxes 
  • TI05-delivery/ows_framework/trunk/ows_common/ows_common/data_identification.py

    r2519 r2529  
    1414class Description(object): 
    1515    """ 
    16     @ivar title 
    17     @type title: iterable of str or LanguageString 
    18     @ivar abstract 
    19     @type abstract: iterable of str or LanguageString 
     16    @ivar titles 
     17    @type titles: iterable of str or LanguageString 
     18    @ivar abstracts 
     19    @type abstracts: iterable of str or LanguageString 
    2020    @ivar keywords 
    2121    @type keywords: iterable or Keywords 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/config/routing.py

    r2494 r2529  
    2222 
    2323    map.connect(':file/wms', controller='csml_wms') 
    24     map.connect(':file/:action', controller='csml_api') 
     24    map.connect(':file.:format', controller='csml_api', action='index', format='html') 
     25    map.connect(':file/:(feature).:format', action='getFeature', 
     26                controller='csml_api', format='html') 
     27    map.connect(':file/:feature/:action', controller='csml_api') 
    2528 
    2629    return map 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/csml_api.py

    r2507 r2529  
    1111from ows_server.lib.base import * 
    1212import os 
    13 from ows_server.lib.csml_util import get_csml_doc 
     13from ows_server.lib.csml_util import get_csml_doc, CsmlBundle 
     14from elementtree import ElementTree as ET 
    1415 
    15  
     16import tempfile, shutil 
    1617 
    1718class CsmlApiController(BaseController): 
    18     def index(self, file): 
     19    def index(self, file, format): 
     20        c.dataset = get_csml_doc(file) 
     21         
     22        if format == 'html': 
     23            return render_response('csml_describe') 
     24        else: 
     25            return Response(ET.tostring(c.dataset.toXML()), mimetype="text/xml") 
     26     
     27    def getFeature(self, file, feature, format): 
    1928        d = get_csml_doc(file) 
    20         return Response('Dataset: %s\nFeatures: %s' % (file, 
    21                         ' '.join(d.getFeatureList()))) 
     29        f = d.getFeature(feature) 
     30        if format == 'html': 
     31            c.feature_obj = f 
     32            return render_response('csml_describe_feature') 
     33        else: 
     34            r = ET.Element("CSML_API"); f.toXML(r) 
     35            return Response(ET.tostring(r), mimetype=format) 
    2236 
     37    def subsetToGridSeries(self, file, feature): 
     38        d = get_csml_doc(file) 
     39        f = d.getFeature(feature) 
     40 
     41        # Get selector parameters from request 
     42        domain = f.getDomain() 
     43        sel = {} 
     44        for ord in domain: 
     45            if ord in request.params: 
     46                sel[ord] = request.params[ord].split(',') 
     47            else: 
     48                sel[ord] = () 
     49 
     50        # Create the bundle in a temporary directory 
     51        tmpdir = tempfile.mkdtemp() 
     52        b = CsmlBundle(tmpdir) 
     53        b.add(f.subsetToGridSeries(ncpath=b.join('data.nc'), **sel)) 
     54        bundleFile = b.makeBundle(b.join('bundle.zip')) 
     55 
     56        # Write bundle to a response object 
     57        r = Response(open(bundleFile), mimetype='application/octetstream') 
     58        r.headers['Content-disposition'] = 'attachment; filename=bundle.zip' 
     59 
     60        # remove tmpdir 
     61        shutil.rmtree(tmpdir) 
     62 
     63        return r 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/csml_wms.py

    r2524 r2529  
    1111from ows_server.controllers.csml_api import get_csml_doc 
    1212from elementtree import ElementTree as ET 
     13 
    1314from ows_common import exceptions as OWS_E 
    1415from ows_common.decorators import * 
     16from ows_common.contents import * 
     17 
    1518from ows_server.lib.csml_util import get_csml_doc 
     19 
    1620 
    1721class CsmlWmsController(OwsController): 
     
    2226        } 
    2327 
     28    _ows_versions = ['1.1.0'] 
     29 
    2430    #_ows_constraints = { 
    2531        # MaximumLayerLevels 
     
    2733        # MaximumWidth 
    2834    #    } 
     35 
     36 
     37    def _load_capabilities(self): 
     38        """ 
     39        Overriding subclass to add layer capabilities 
     40 
     41        """ 
     42        # Get default capabilities from superclass 
     43        sm = super(CsmlWmsController, self)._load_capabilities() 
     44 
     45        # Add a DatasetSummary for each feature 
     46        contents = Contents() 
     47        for f_n in c.dataset.getFeatureList(): 
     48            f = c.dataset.getFeature(f_n) 
     49            contents.datasetSummaries.append(DatasetSummary(identifier=f.id, 
     50                                                            titles=[f.description.CONTENT])) 
     51 
     52        sm.contents = contents 
     53        return sm 
     54 
    2955     
    3056    @operation 
    3157    @parameter('Format', possibleValues=['text/xml']) 
     58    @parameter('Service', possibleValues=['WMS']) 
    3259    def GetCapabilities(self, file, service=None, version=None): 
    3360        """ 
     
    3764        """ 
    3865 
     66        #!TODO: This error checking could be done automatically based on the method 
     67        #       decorators. 
    3968        if service is None: 
    4069            raise OWS_E.MissingParameterValue('SERVICE parameter not specified', 
     
    4372            raise OWS_E.InvalidParameterValue('SERVICE parameter must be "WMS"', 
    4473                                              'SERVICE') 
     74 
     75        #!TODO: Version negotiation could be done automatically 
     76        if version not in self._ows_versions: 
     77            raise OWS_E.InvalidParameterValue('VERSION parameter must be one of %s' 
     78                                              % ','.join(self._ows_versions), 
     79                                              'VERSION') 
    4580         
    46         #c.dataset = get_csml_doc(file) 
    47         c.service_metadata = self._load_capabilities( 
    48             h.url_for(controller='csml_wms', file=file) 
    49             ) 
    50         c.version = '1.1.0' 
    51          
    52         return render_response('ows/get_capabilities', format='xml') 
     81        c.dataset = get_csml_doc(file) 
     82        c.service_metadata = self._load_capabilities() 
     83 
     84        r = render_response('ows/get_capabilities', format='xml') 
     85        r.headers['content-type'] = 'text/xml' 
     86        return r 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/base.py

    r2524 r2529  
    6767        return kargs 
    6868 
    69  
    70     def _load_capabilities(self, ows_endpoint): 
     69    def _load_capabilities(self): 
    7170        """ 
    7271        creates an ows_common.get_capabilities.ServiceMetadata object 
    7372        by consulting the paste configuration and annotations in the 
    74         controller definition.  The endpoint must be supplied to allow 
    75         a controller to serve multiple ows endpoints. 
    76  
    77         @param ows_endpoint: The URI of the OWS endpoint being served 
    78             by this controller. 
     73        controller definition. 
    7974 
    8075        """ 
     76 
     77        # Deduce ows_endpoint from routes 
     78        ows_endpoint = h.url_for(controller=request.environ['pylons.routes_dict']['controller']) 
    8179 
    8280        # Get the server-level configuration data from an XML file 
     
    8886        parameters = getattr(self, '_ows_parameters', {}) 
    8987        constraints = getattr(self, '_ows_constraints', {}) 
     88        versions = getattr(self, '_ows_versions', []) 
    9089 
    9190        # Extract operation-level parameters and constraints 
     
    102101         
    103102        sm.operationsMetadata = OperationsMetadata(od, constraints, parameters) 
     103        sm.serviceIdentification.serviceTypeVersions = versions 
    104104         
    105105        return sm 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/csml_util.py

    r2507 r2529  
    1212import csml 
    1313import os 
     14import zipfile 
    1415 
    1516def get_csml_doc(file): 
     
    3536         
    3637    return d 
     38         
     39class CsmlBundle(csml.API.csmlContainer.Container): 
     40    """ 
     41    A quick stab at bundling CSML. 
     42 
     43    """ 
     44    def __init__(self, context, **kwargs): 
     45        """ 
     46        @param context: A directory path to store the CSML and NetCDF 
     47        """ 
     48        self.context = context 
     49        kwargs['csmlpath'] = os.path.join(context, 'container.xml') 
     50        super(CsmlBundle, self).__init__(**kwargs) 
     51 
     52    def add(self, fpd): 
     53        """ 
     54        Overrides the file storage descriptor so that the CSML points relative to the 
     55        bundle context 
     56 
     57        @warning: THIS IS A HACK! 
     58 
     59        """ 
     60        (feature, path, desc) = fpd 
     61        if os.path.dirname(path) != self.context: 
     62            raise ValueError, "Extract not in bundle context" 
     63        desc.fileName.CONTENT = os.path.basename(path) 
     64 
     65        return super(CsmlBundle, self).add(fpd) 
     66 
     67    def join(self, *p): 
     68        return os.path.join(self.context, *p) 
     69 
     70    def makeBundle(self, file, bundleName=None): 
     71        """ 
     72        Writes the bundle to a zipfile. 
     73 
     74        @param file: path or file-like object (see zipfile docs) 
     75 
     76        """ 
     77        if bundleName is None: 
     78            bundleName = os.path.splitext(os.path.basename(file))[0] 
     79         
     80        zf = zipfile.ZipFile(file, 'w') 
     81        self.getContents() 
     82        for f in self.containerContents: 
     83            zf.write(f, os.path.join(bundleName, os.path.basename(f))) 
     84        zf.close() 
     85 
     86        return file 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/templates/ows/get_capabilities.kid

    r2524 r2529  
    118118      ${a} 
    119119    </Abstract> 
     120    ${keywords(si.keywords)} 
    120121    <ServiceTypeVersion py:for="v in si.serviceTypeVersions">${v}</ServiceTypeVersion> 
    121122    <Profile py:for="p in si.profiles">${p}</Profile> 
     
    181182    </Operation> 
    182183  </OperationsMetadata> 
     184  <Contents> 
     185    <?python cn = c.service_metadata.contents ?> 
     186    <OtherSource py:for="s in cn.otherSources" py:content="s"/> 
     187    <DatasetDescriptionSummary py:for="dsd in cn.datasetSummaries"> 
     188      <Identifier py:if="dsd.identifier is not None" 
     189                  py:attrs="code_attrs(dsd.identifier)" 
     190                  py:content="dsd.identifier"/> 
     191      <Title py:for="t in dsd.titles" py:attrs="langstr_attrs(t)" 
     192             py:content="t"/> 
     193      <Abstract py:for="a in dsd.abstracts" py:attrs="langstr_attrs(a)" 
     194                py:content="a"/> 
     195      ${keywords(dsd.keywords)} 
     196      <Metadata py:for="m in dsd.metadata" 
     197                xlink:href="${m.link}" about="${m.about}">${m.content}</Metadata> 
     198      <BoundingBox py:for="bb in dsd.boundingBoxes"> 
     199        <LowerCorner py:content="' '.join(bb.lowerCorner)"/> 
     200        <UpperCorner py:content="' '.join(bb.upperCorner)"/> 
     201        <CRS py:content="bb.crs"/> 
     202        <Dimensions py:content="bb.dimensions"/> 
     203      </BoundingBox> 
     204      <WGS84BoundingBox py:for="bb in dsd.wgs84BoundingBoxes"> 
     205        <LowerCorner py:content="' '.join(bb.lowerCorner)"/> 
     206        <UpperCorner py:content="' '.join(bb.upperCorner)"/> 
     207        <CRS py:content="bb.crs"/> 
     208        <Dimensions py:content="bb.dimensions"/> 
     209      </WGS84BoundingBox> 
     210    </DatasetDescriptionSummary> 
     211  </Contents> 
    183212</Capabilities> 
Note: See TracChangeset for help on using the changeset viewer.