def _encode_process_brief(process, elem): """ Insert a brief process description into an XML element passed as the second argument. The brief process description is shared by both the Capabilities and ProcessDescriptions XML encoders. """ identifier = getattr(process, 'identifier', type(process).__name__) title = getattr(process, 'title', identifier) abstract = getattr(process, 'description', process.__doc__) version = getattr(process, "version", "1.0.0") metadata = getattr(process, "metadata", {}) profiles = getattr(process, "profiles", []) wsdl = getattr(process, "wsdl", None) elem.append(OWS("Identifier", identifier)) elem.append(OWS("Title", title)) elem.attrib[ns_wps("processVersion")] = version if abstract: elem.append(OWS("Abstract", abstract)) elem.extend(_encode_metadata(k, metadata[k]) for k in metadata) elem.extend(WPS("Profile", profile) for profile in profiles) if wsdl: elem.append(WPS("WSDL", **{ns_xlink("href"): wsdl})) return elem
def encode_capabilities(processes): """ Encode Capabilities XML document. """ conf = CapabilitiesConfigReader(get_eoxserver_config()) # Avoid duplicate process offerings ... process_set = set() process_offerings = [] for process in processes: process_identifier = (getattr(process, 'identifier', None) or type(process).__name__) if process_identifier not in process_set: process_offerings.append(encode_process_brief(process)) process_set.add(process_identifier) return WPS( "Capabilities", OWS( "ServiceIdentification", OWS("Title", conf.title), OWS("Abstract", conf.abstract), OWS("Keywords", *(OWS("Keyword", kw) for kw in conf.keywords)), OWS("ServiceType", "WPS"), OWS("ServiceTypeVersion", "1.0.0"), OWS("Fees", conf.fees), OWS("AccessConstraints", conf.access_constraints), ), OWS( "ServiceProvider", OWS("ProviderName", conf.provider_name), OWS("ProviderSite", **{ns_xlink("href"): conf.provider_site}), OWS( "ServiceContact", OWS("IndividualName", conf.individual_name), OWS("PositionName", conf.position_name), OWS( "ContactInfo", OWS("Phone", OWS("Voice", conf.phone_voice), OWS("Facsimile", conf.phone_facsimile)), OWS( "Address", OWS("DeliveryPoint", conf.delivery_point), OWS("City", conf.city), OWS("AdministrativeArea", conf.administrative_area), OWS("PostalCode", conf.postal_code), OWS("Country", conf.country), OWS("ElectronicMailAddress", conf.electronic_mail_address))))), _encode_operations_metadata(conf), WPS("ProcessOfferings", *process_offerings), WPS("Languages", WPS("Default", OWS("Language", "en-US")), WPS("Supported", OWS("Language", "en-US"))), # TODO: WPS("WSDL") **{ "service": "WPS", "version": "1.0.0", ns_xml("lang"): "en-US", "updateSequence": conf.update_sequence, })
def encode_response(self, results): """Encode ProcessSucceeded execute response including the output data.""" elem = self._encode_common( WPS("ProcessSucceeded", "The processes execution completed successfully.")) outputs = [] for result, prm, req in itervalues(results): outputs.append(_encode_output(result, prm, req)) elem.append(WPS("ProcessOutputs", *outputs)) return elem
def _encode_output(data, prm, req): """ Encode one ProcessOutputs sub-element. """ elem = encode_output_exec( Parameter(prm.identifier, req.title or prm.title, req.abstract or prm.abstract)) if isinstance(data, Reference): elem.append(_encode_output_reference(data, prm)) elif isinstance(prm, LiteralData): elem.append(WPS("Data", _encode_literal(data, prm, req))) elif isinstance(prm, BoundingBoxData): elem.append(WPS("Data", _encode_bbox(data, prm))) elif isinstance(prm, ComplexData): elem.append(WPS("Data", _encode_complex(data, prm))) return elem
def encode_paused(self, progress=0): """ Encode ProcessPaused execute response.""" return self._encode_common( WPS("ProcessPaused", "The processes execution is paused.", percentCompleted=("%d" % min(99, max(0, int(float(progress)))))))
def _encode_raw_input_literal(input_raw, prm): """ Encode Data/LiteralData element from a raw (unparsed) input .""" attrib = {'dataType': prm.dtype.name} uom = input_raw.uom or prm.default_uom if prm.uoms: attrib['uom'] = uom return WPS("LiteralData", input_raw.data, **attrib)
def _encode_common_response(process, status_elem, inputs, raw_inputs, resp_doc): """Encode common execute response part shared by all specific responses.""" inputs = inputs or {} conf = CapabilitiesConfigReader(get_eoxserver_config()) url = conf.http_service_url if url[-1] == "?": url = url[:-1] elem = WPS( "ExecuteResponse", encode_process_brief(process), WPS("Status", status_elem, creationTime=isoformat(now())), { "service": "WPS", "version": "1.0.0", ns_xml("lang"): "en-US", "serviceInstance": ("%s?service=WPS&version=1.0.0&request=GetCapabilities" % url) }, ) if resp_doc.lineage: inputs_data = [] for id_, prm in process.inputs: if isinstance(prm, RequestParameter): continue prm = fix_parameter(id_, prm) data = inputs.get(id_) rawinp = raw_inputs.get(prm.identifier) if rawinp is not None: inputs_data.append(_encode_input(data, prm, rawinp)) elem.append(WPS("DataInputs", *inputs_data)) outputs_def = [] for id_, prm in process.outputs: prm = fix_parameter(id_, prm) outdef = resp_doc.get(prm.identifier) if outdef is not None: outputs_def.append(encode_output_def(outdef)) elem.append(WPS("OutputDefinitions", *outputs_def)) return elem
def encode_process_descriptions(processes): """ Encode the ProcessDescriptions XML document. """ _proc = [encode_process_full(p) for p in processes] _attr = { "service": "WPS", "version": "1.0.0", ns_xml("lang"): "en-US", } return WPS("ProcessDescriptions", *_proc, **_attr)
def encode_failed(self, exception): """ Encode ProcessFailed execute response.""" # NOTE: Some exceptions such as the urllib2.HTTPError have also # the 'code' attribute and the duck typing does not work very well. # Therefore we need match the exception base type. if isinstance(exception, OWS10Exception): code = exception.code locator = exception.locator else: code = "NoApplicableCode" locator = type(exception).__name__ message = str(exception) exc_attr = {"exceptionCode": str(code)} if locator: exc_attr["locator"] = str(locator) exc_elem = OWS("Exception", OWS("ExceptionText", message), **exc_attr) status = WPS("ProcessFailed", WPS("ExceptionReport", exc_elem)) return self._encode_common(status)
def encode_started(self, progress=0, message=None): """ Encode ProcessStarted execute response.""" if not message: message = "The processes execution is in progress." return self._encode_common( WPS("ProcessStarted", message, percentCompleted=("%d" % min(99, max(0, int(float(progress)))))))
def _encode_input(data, prm, raw): """ Encode one DataInputs sub-element. """ elem = encode_input_exec(raw) if isinstance(raw, InputReference): elem.append(_encode_input_reference(raw)) elif isinstance(prm, LiteralData): elem.append(WPS("Data", _encode_raw_input_literal(raw, prm))) elif isinstance(prm, BoundingBoxData): if data is None: data = prm.parse(raw.data) elem.append(WPS("Data", _encode_bbox(data, prm))) elif isinstance(prm, ComplexData): if data is None: data = prm.parse(data=raw.data, mime_type=raw.mime_type, encoding=raw.encoding, schema=raw.schema) elem.append(WPS("Data", _encode_complex(data, prm))) return elem
def _encode_literal(data, prm, req): """ Encode Data/LiteralData element. """ attrib = {'dataType': prm.dtype.name} uom = req.uom or prm.default_uom if prm.uoms: attrib['uom'] = uom try: encoded_data = prm.encode(data, uom) except (ValueError, TypeError) as exc: raise InvalidOutputValueError(prm.identifier, exc) return WPS("LiteralData", encoded_data, **attrib)
def _encode_complex(data, prm): """ Encode Data/ComplexData element. """ try: payload = prm.encode_xml(data) except (ValueError, TypeError) as exc: raise InvalidOutputValueError(prm.identifier, exc) elem = WPS("ComplexData", **_encode_format_attr(data, prm)) if isinstance(payload, etree._Element): elem.append(payload) else: elem.text = etree.CDATA(payload) return elem
def _encode_bbox(data, prm): """ Encode Data/BoundingBoxData element. """ try: lower, upper, crs = prm.encode_xml(data) except (ValueError, TypeError) as exc: raise InvalidOutputValueError(prm.identifier, exc) return WPS( "BoundingBoxData", OWS("LowerCorner", lower), OWS("UpperCorner", upper), crs=crs, #dimension="%d"%prm.dimension, )
def encode_output_def(outdef): """ Encode execute response Output (definition) element. """ attrib = {} if outdef.uom is not None: attrib['uom'] = outdef.uom if outdef.crs is not None: attrib['crs'] = outdef.crs if outdef.mime_type is not None: attrib['mimeType'] = outdef.mime_type if outdef.encoding is not None: attrib['encoding'] = outdef.encoding if outdef.schema is not None: attrib['schema'] = outdef.schema if outdef.as_reference is not None: attrib['asReference'] = 'true' if outdef.as_reference else 'false' return WPS("Output", *_encode_param_common(outdef, False), **attrib)
def _encode_allowed_value(avobj): """ Encode process description LiteralData allowed values definition. Based on the type of the allowed value definition either AnyValue, ValuesReference, or AllowedValues element is returned. """ enum, ranges, elist = None, [], [] if isinstance(avobj, AllowedAny): return OWS("AnyValue") elif isinstance(avobj, AllowedByReference): return WPS( "ValuesReference", **{ ns_ows("reference"): avobj.url, "valuesForm": avobj.url, }) elif isinstance(avobj, AllowedEnum): enum = avobj elif isinstance(avobj, AllowedRange): ranges = [avobj] elif isinstance(avobj, AllowedRangeCollection): enum, ranges = avobj.enum, avobj.ranges else: raise TypeError("Invalid allowed value object! OBJ=%r" % avobj) dtype = avobj.dtype ddtype = dtype.get_diff_dtype() if enum is not None: elist.extend(OWS("Value", dtype.encode(v)) for v in enum.values) for range_ in ranges: attr, elms = {}, [] if range_.closure != 'closed': attr = {ns_ows("rangeClosure"): range_.closure} if range_.minval is not None: elms.append(OWS("MinimumValue", dtype.encode(range_.minval))) if range_.maxval is not None: elms.append(OWS("MaximumValue", dtype.encode(range_.maxval))) if range_.spacing is not None: elms.append(OWS("Spacing", ddtype.encode(range_.spacing))) elist.append(OWS("Range", *elms, **attr)) return OWS("AllowedValues", *elist)
def _encode_output_reference(ref, prm): """ Encode ProcessOutputs/Reference element. """ #TODO proper output reference encoding mime_type = getattr(ref, 'mime_type', None) encoding = getattr(ref, 'encoding', None) schema = getattr(ref, 'schema', None) if mime_type is None and hasattr(prm, 'default_format'): default_format = prm.default_format mime_type = default_format.mime_type encoding = default_format.encoding schema = default_format.schema attr = { #ns_xlink("href"): ref.href, 'href': ref.href, } if mime_type: attr['mimeType'] = mime_type if encoding is not None: attr['encoding'] = encoding if schema is not None: attr['schema'] = schema return WPS("Reference", **attr)
def encode_output_exec(prm): """ Encode common part of the execute response Output (data) element. """ return WPS("Output", *_encode_param_common(prm))
def encode_input_exec(prm): """ Encode common part of the execute response Input (data) element. """ return WPS("Input", *_encode_param_common(prm, False))
def encode_process_brief(process): """ Encode a brief process description (Process element) of the Capabilities XML document. """ return _encode_process_brief(process, WPS("Process"))
def _encode_input_reference(ref): """ Encode DataInputs/Reference element. """ #TODO proper input reference encoding return WPS("Reference", **{ns_xlink("href"): ref.href})
def encode_accepted(self): """ Encode ProcessAccepted execute response.""" return self._encode_common( WPS("ProcessAccepted", "The processes was accepted for execution."))