source: cows_wps/trunk/cows_wps/renderer/xml_renderer.py @ 7531

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows_wps/trunk/cows_wps/renderer/xml_renderer.py@7531
Revision 7531, 6.5 KB checked in by astephen, 10 years ago (diff)

added authorised roles to check user can access this resource.

Line 
1"""
2xml_renderer.py
3===============
4
5Holds XMLRenderer class to render XML documents for responses.
6
7"""
8
9# Import standard library modules
10import os
11import sys
12#import StringIO
13import copy
14
15import logging
16log = logging.getLogger(__name__)
17
18# Import local modules
19
20from cows_wps import utils
21
22#import genshi template loader for xml templates for responses, such as GetCapabilities
23from genshi.template import TemplateLoader
24from genshi.builder import *
25from pkg_resources import resource_filename
26
27#test imports from cows
28from pylons import request, response, c
29from routes import url_for
30from cows import helpers
31from cows.builder import loadConfigFile
32
33#import config files
34from cows_wps.utils.parse_capabilities_config import caps_config_dict
35
36# Instantiate Genshi template loader
37templateLoader = TemplateLoader(
38    resource_filename('cows_wps', 'templates'),
39    auto_reload=True,
40    )
41
42
43# Define global variables
44
45class Operation(object):
46    def __init__(self, name, href):
47        self.name = name
48        self.href = href
49
50
51def addOperation(ops, name):
52    href=helpers.operation(url_for(qualified=True, action="index")+'?',[]).get.href
53    ops.append(Operation(name,href))
54
55
56
57def GetCapabilitiesResponse(version,service,request,format = "text/xml",updatesequence = "none"):
58    "returns service-level metadata"
59    #loading service metadata from a config file
60   
61    configFile = config.get('capabilities_config')
62    if configFile is None:
63        raise RuntimeError('No OWS configuration file')
64    c.capabilities = loadConfigFile(configFile)
65       
66    # check for version
67    if version == '0.4.0':
68        t= templateLoader.load("wps_getcapabilitiesresponse_template.xml")
69    else:
70        raise RuntimeError("Version %s not supported" % version)
71   
72    #generate capabilities XML
73    ops =[]
74    addOperation(ops, "GetCapabilities")
75    addOperation(ops,"DescribeProcess")
76    addOperation(ops, "Execute") 
77
78    ServiceCapabilitiesXML = t.generate(caps_config_dict=caps_config_dict, ops=ops, c=c).render()
79   
80    return (ServiceCapabilitiesXML, "xml")
81
82
83def DescribeProcessResponse(version, service, request, identifier):
84    "Returns XML for describe process"
85   
86
87    #new function definition using genshi xml template rendering
88    t= templateLoader.load("wps_describeprocess_response.xml")
89   
90    ids =[]
91    if identifier == "all":
92        ids = caps_config_dict["Identifiers"]
93    else:
94        ids.append(identifier)
95
96    describeProcessResponseXML = t.generate(caps_config_dict=caps_config_dict,ids=ids).render()
97   
98    return (describeProcessResponseXML, "xml")
99   
100def validateLength(def_len, out_len):
101
102    _len = def_len.split("_|,")
103    for i in _len:
104        try:
105            if out_len > i:
106                return False
107
108        except:
109            raise Exception ("%s not a integer" % i)
110    return True
111
112def validateType(def_type, param):
113    if def_type == "string":
114       def_type = 'str'
115
116    if checkType(param).__name__ == def_type:
117       return True
118
119    return False
120
121
122def checkType(param):
123
124    return type(param)
125
126
127
128def wrapExecuteResponse(context, identifier, version, input_dict, job_id, 
129                        authorisedRoles="0", is_cached=False):
130    """
131    Wraps full ExecuteResponse XML around specific response.
132    outputs is either a dictionary or an XML snippet.
133
134    authorisedRoles = "0" is the numeric code for no security restrictions.
135    """
136    # function definition using genshi xml template rendering
137    t= templateLoader.load("wps_execute_response.xml")
138   
139    job_details = context.outputs['job_details']
140    proc_out_defs = caps_config_dict[identifier]["ProcessOutputs"]
141    status_url = url_for(controller='/status', requestId=job_id, qualified=True)
142
143    if 'ProcessSpecificContent' in context.outputs:
144        replaceProcessSpecificContextLists(context.outputs['ProcessSpecificContent'])
145
146    for out_tag, out_def in proc_out_defs.items():
147        log.warn("out_def: %s" % str(out_def)) 
148        type = out_def["type"]
149       
150        if type == "xml_complex_value":
151            comp_t = templateLoader.load(out_def["template"])
152           
153            output_xml = Element("ComplexValue", format=out_def["mime_type"], schema=out_def["schema"])
154               
155            output_xml.append(comp_t.generate(context=context, authorisedRoles=authorisedRoles))
156           
157        else:
158
159            if job_details.has_key(out_tag):
160               out_val = job_details[out_tag]
161            else:
162               raise Exception("%s not found in job_details" % out_tag)
163            item_type = out_def["item_type"]
164            if item_type == "list":
165           
166               if checkType(out_val) == checkType([1,2]):
167                   
168                    if validateLength(out_def["allowed_length"], len(out_val)):
169                       value = " ".join(str(i) for i in out_val)
170                       output_xml = Element ("LiteralValue")(value)                           
171                    else:
172                       raise Exception ("%s exceedes allowed length %s" % (out_val, out_def['allowed_length']))     
173               else:
174                    raise Exception ("list type expected but found %s" % type(out_val))
175
176            elif item_type == "item":
177                if validateType(type, out_val):
178                    output_xml = Element ("LiteralValue")(out_val)
179                else:
180                    raise Exception("Expected %s type but value: %s is of type %s" % (type, out_val, checkType(out_val).__name__))
181               
182    log.debug("sending xml response")
183   
184    #!TODO: This is a hack to notify the client of a cached job
185    if is_cached:
186        statusTuple = (context.status, 'Cached Job', context.percentComplete)
187    else:   
188        statusTuple = (context.status, context.statusMessage, context.percentComplete)
189   
190    return t.generate(caps_config_dict=caps_config_dict, identifier=identifier, version=version, 
191                      status=statusTuple, lineage=job_details['lineage'],
192                      output_xml=output_xml, input_dict=input_dict, status_url=status_url).render()
193
194def replaceProcessSpecificContextLists(processSpecificDict):
195    """
196    Looks through the process specific context dictionary and replaces any lists
197    with a string of comma separated values.
198   
199    This is used to avoid the genshi default behaviour of just joinging the
200    list values without any separator.
201    """ 
202   
203    for key, value in processSpecificDict.items():
204
205        if type(value) == list:
206            newValue = ", ".join([ str(x) for x in value])
207            processSpecificDict[key] = newValue   
Note: See TracBrowser for help on using the repository browser.