def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) #************************** if method == "GET": raise sosException.SOSException( "NoApplicableCode", None, "registerSensor request support only POST method!") if method == "POST": #---assignedSensorId asid = requestObject.getElementsByTagName('AssignedSensorId') if len(asid) == 1: self.assignedSensorId = getElemTxt(asid[0]) else: raise sosException.SOSException( "MissingParameterValue", "AssignedSensorId", "AssignedSensorId parameter is mandatory with multiplicity 1" ) #---SensorDescription sd = requestObject.getElementsByTagName('SensorDescription') if len(sd) == 1: self.xmlSensorDescription = sd[0] else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "SensorDescription parameter is mandatory with multiplicity 1" )
def CQLvalueFilter2PostgisSql(fildName, CQLfilter): """parse a CQL filter and returen an SQL filter""" CQLsupportedOperators = ("<", "<=", ">", ">=", "=") if CQLfilter.__class__.__name__ in ["str", "StringField"]: if CQLfilter[0] in ["<", ">", "="]: if CQLfilter[1] in ["="]: if not CQLfilter[2:].isdigit(): raise sosException.SOSException( "NoApplicableCode", None, "CQLvalueFilter2PostgisSql: only numeric comparison supported" ) else: if not CQLfilter[1:].isdigit(): raise sosException.SOSException( "NoApplicableCode", None, "CQLvalueFilter2PostgisSql: only numeric comparison supported" ) else: raise sosException.SOSException( "NoApplicableCode", None, "CQLvalueFilter2PostgisSql: only filter by comparing values is supported" ) else: raise sosException.SOSException( "NoApplicableCode", None, "CQLvalueFilter2PostgisSql: input must be a string") return "%s %s" % (fildName, CQLfilter)
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) if method == "GET": self.sections = None if "section" in requestObject: self.sections = requestObject["section"].lower().split(",") if "sections" in requestObject: self.sections = requestObject["sections"].lower().split(",") if self.sections: for s in self.sections: if self.version == '2.0.0': if s not in sosConfig.parameters["GC_Section_2_0_0"]: err_txt = "Allowed parameter \"section\" values are: " + ",".join( sosConfig.parameters["GC_Section"]) raise sosException.SOSException( "InvalidParameterValue", "section", err_txt) else: if s not in sosConfig.parameters["GC_Section"]: err_txt = "Allowed parameter \"section\" values are: " + ",".join( sosConfig.parameters["GC_Section"]) raise sosException.SOSException( "InvalidParameterValue", "section", err_txt) else: self.sections = ["all"] if method == "POST": if requestObject.nodeType == requestObject.ELEMENT_NODE: #-------SECTIONS------------- self.sections = [] sects = requestObject.getElementsByTagName('section') if len(sects) > 0: for sect in sects: for val in sect.childNodes: if val.nodeType == val.TEXT_NODE and str( val.data).lower( ) in sosConfig.parameters["GC_Section"]: self.sections.append(str(val.data).lower()) else: err_txt = "Allowed parameter \"section\" values are: " + ",".join( sosConfig.parameters["GC_Section"]) raise sosException.SOSException( "InvalidParameterValue", "sections", err_txt) else: self.sections = ["all"]
def checkAuthorization(self): if self.service and self.user and not self.user.isAdmin(): if self.service == 'default': raise sosException.SOSException( "ResourceNotFound", "Authorization", "Access to admin request are not allowed.") elif not self.user.allowedService(self.service): raise sosException.SOSException( "ResourceNotFound", "Authorization", "You don't have the permissions to access the '%s' instance." % self.service)
def __init__(self,filter,pgdb): #check assigned sensor id sql = "SELECT id_prc, name_prc FROM %s.procedures WHERE assignedid_prc='%s'" %(filter.sosConfig.schema,get_name_from_urn(filter.assignedSensorId,"sensor",filter.sosConfig)) try: prc = pgdb.select(sql)[0] except: raise sosException.SOSException("InvalidParameterValue","assignedSensorId","assignedSensorId: '%s' is not valid!" %(filter.assignedSensorId)) #---------------------------------------- # create SensorML for inserted procedure #---------------------------------------- f = open(filter.sosConfig.sensorMLpath + filter.procedure + ".xml", 'w') xml_pre = """<SensorML xmlns:sml="http://www.opengis.net/sensorML/1.0.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:swe="http://www.opengis.net/swe/1.0.1" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sensorML/1.0.1 http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd" version="1.0.1"> <member xlink:arcrole="urn:ogc:def:process:OGC:detector">""" xml_ascii = filter.xmlSensorDescription.toxml().encode('ascii','ignore') xml_post = " </member>\n</SensorML>" f.write(xml_pre + xml_ascii + xml_post) f.close() self.procedure = prc["name_prc"]
def get_name_from_urn(stringa, urnName, sosConfig): a = stringa.split(":") name = a[-1] urn = sosConfig.urn[urnName].split(":") if len(a) > 1: for index in range(len(urn) - 1): if urn[index] == a[index]: pass else: raise sosException.SOSException( 1, "Urn \"%s\" is not valid: %s." % (a, urn)) return name
def sosFactoryRender(response, sosConfig): res_type = str(response.__class__.__name__) if res_type == "GetCapabilitiesResponse": from istsoslib.renderers import GCresponseRender if response.version == '2.0.0': return GCresponseRender.render_2_0_0(response, sosConfig) else: return GCresponseRender.render(response, sosConfig) elif res_type == "DescribeSensorResponse": from istsoslib.renderers import DSresponseRender if response.version == '2.0.0': return DSresponseRender.render_2_0_0(response, sosConfig) else: return DSresponseRender.render(response, sosConfig) elif res_type in [ "GetObservationResponse", "GetObservationResponse_2_0_0" ]: from istsoslib.renderers import GOresponseRender return GOresponseRender.render(response, sosConfig) elif res_type == "foi": from istsoslib.renderers import GFresponseRender return GFresponseRender.render(response, sosConfig) elif res_type == "InsertObservationResponse": from istsoslib.renderers import IOresponseRender return IOresponseRender.render(response, sosConfig) elif res_type == "RegisterSensorResponse": from istsoslib.renderers import RSresponseRender return RSresponseRender.render(response, sosConfig) elif res_type == "UpdateSensorDescriptionResponse": from istsoslib.renderers import USDresponseRender return USDresponseRender.render(response, sosConfig) else: raise sosException.SOSException( "InvalidRequest", "request", "\"request\": %s not supported" % (str(response.__class__.__name__)))
def __init__(self,sosRequest,method,requestObject,sosConfig): f.sosFilter.__init__(self,sosRequest,method,requestObject,sosConfig) #************************** if method == "GET": #---FeatureOfInterest if not requestObject.has_key("featureofinterestid"): raise sosException.SOSException("MissingParameterValue","FeatureOfInterestId","Parameter \"FeatureOfInterestId\" is required with multiplicity 1") else: self.featureOfInterest = get_name_from_urn(requestObject["featureofinterestid"],"feature",sosConfig) #one-many ID #---srsName if requestObject.has_key("srsname"): self.srsName = get_name_from_urn(requestObject["srsname"],"refsystem",sosConfig) if not self.srsName in sosConfig.parameters["GO_srs"]: raise sosException.SOSException("OptionNotSupported","srsName","Supported \"srsName\" valueas are: " + ",".join(sosConfig.parameters["GO_srs"])) else: self.srsName = sosConfig.parameters["GO_srs"][0] if method == "POST": #---FeatureOfInterest fets = requestObject.getElementsByTagName('FeatureOfInterestId') if len(fets)==1: try: self.featureOfInterest = get_name_from_urn(getElemAtt(fets[0],"xlink:href"),"feature",sosConfig) except: try: self.featureOfInterest = get_name_from_urn(getElemTxt(fets[0]),"feature",sosConfig) except: err_txt = "XML parsing error (get value: FeatureOfInterestId)" raise sosException.SOSException("NoApplicableCode",None,err_txt) else: err_txt = "parameter \"FeatureOfInterestId\" is mandatory with multiplicity 1" if len(fets)==0: raise sosException.SOSException("MissingParameterValue","FeatureOfInterestId",err_txt) else: raise sosException.SOSException("NoApplicableCode",None,err_txt) #---srsName srss = requestObject.getElementsByTagName('srsName') if len(srss) ==1: self.srsName = get_name_from_urn(getElemTxt(srss[0]),"refsystem",sosConfig) if not self.srsName in sosConfig.parameters["GO_srs"]: raise sosException.SOSException("OptionNotSupported","srsName","Supported \"srsName\" valueas are: " + ",".join(sosConfig.parameters["GO_srs"])) elif len(srss) == 0: self.srsName = sosConfig.parameters["GO_srs"][0] else: err_txt = "parameter \"srsName\" is optional with multiplicity 1" raise sosException.SOSException("NoApplicableCode",None,err_txt)
def sosFactoryResponse(sosFilter, pgdb): if sosFilter.request == "getcapabilities": from istsoslib.responders import GCresponse return GCresponse.GetCapabilitiesResponse(sosFilter, pgdb) elif sosFilter.request == "describesensor": from istsoslib.responders import DSresponse return DSresponse.DescribeSensorResponse(sosFilter, pgdb) elif sosFilter.request == "getobservation": from istsoslib.responders import GOresponse if sosFilter.version == '2.0.0': return GOresponse.GetObservationResponse_2_0_0(sosFilter, pgdb) else: return GOresponse.GetObservationResponse(sosFilter, pgdb) elif sosFilter.request == "getfeatureofinterest": from istsoslib.responders import GFresponse return GFresponse.foi(sosFilter, pgdb) elif sosFilter.request == "insertobservation": from istsoslib.responders import IOresponse return IOresponse.InsertObservationResponse(sosFilter, pgdb) elif sosFilter.request == "registersensor": from istsoslib.responders import RSresponse return RSresponse.RegisterSensorResponse(sosFilter, pgdb) elif sosFilter.request == "updatesensordescription": from istsoslib.responders import USDresponse return USDresponse.UpdateSensorDescription(sosFilter, pgdb) else: raise sosException.SOSException( "InvalidRequest", "request", "\"request\": %s not supported" % (sosFilter.request))
def ogcCompCons2PostgisSql(ogcComparisonOperator): """parse an ogc property operator element and convert it to a PostGIS SQL WHERE clause""" ogcSupportedCompOperators = { 'ogc:PropertyIsEqualTo': '=', 'ogc:PropertyIsNotEqualTo': '!=', 'ogc:PropertyIsLessThan': '<', 'ogc:PropertyIsGreaterThan': '>', 'ogc:PropertyIsLessThanOrEqualTo': '<=', 'ogc:PropertyIsGreaterThanOrEqualTo': '>=', } """ 'ogc:PropertyIsBetween':'BETWEEN' 'ogc:PropertyIsLike':'LIKE', 'ogc:PropertyIsNull':'= NULL' """ if ogcComparisonOperator.__class__.__name__ in ["str", "StringField"]: xmlString = """<?xml version="1.0" encoding="UTF-8"?><sos:result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" xmlns:sos="http://www.opengis.net/sos/1.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:om="http://www.opengis.net/om/1.0" service="SOS" version='1.0.0'> """ xmlString += ogcComparisonOperator + "</sos:result>" xmlObject = minidom.parseString(xmlString) res = xmlObject.getElementsByTagName("sos:result")[0] ogcComparisonOperator = childElementNodes(res)[0] try: ogcOperator = ogcComparisonOperator.nodeName.encode() except: raise sosException.SOSException( "NoApplicableCode", None, "ogcCompCons2PostgisSql: argunment must be an ''XML object'' or a valid ''XML string''" ) prop = '' sql = '' #--------------------------- # PARSE OPTIONS #--------------------------- if ogcOperator in ogcSupportedCompOperators.keys(): childs = childElementNodes(ogcComparisonOperator) propertyNameObj = ogcComparisonOperator.getElementsByTagName( "ogc:PropertyName") literalObj = ogcComparisonOperator.getElementsByTagName("ogc:Literal") matchCase = True if len(propertyNameObj) == 1 and len(literalObj) == 1: #raise sosException.SOSException(1,"XML %s" %(propertyNameObj[0].data)) propertyName = propertyNameObj[0].firstChild.data.encode().strip() """ -- unsupported because only digits are valid -- if propertyNameObj[0].value.upper()=="FALSE": matchCase = False """ literal = literalObj[0].firstChild.data.encode().strip() if not literal.isdigit() and not literal == None: raise sosException.SOSException( "NoApplicableCode", None, "Sorry istsos support only numeric constraints, provided: \'%s\'" % (literal)) else: raise sosException.SOSException( "NoApplicableCode", None, "ogcCompCons2PostgisSql: ogc:comparisonOps allow only two expression" ) return ("%s" % (propertyName), "%s %s" % (ogcSupportedCompOperators[ogcOperator], literal)) else: raise sosException.SOSException( "NoApplicableCode", None, "ogcCompCons2PostgisSql: ogc:comparisonOps not jet supported")
def sosFactoryFilter(environ, sosConfig): """Instantiate the correct filter type depending on requests Args: environ (obj): the mod_wsgi environment object sosCOnfig (obj): the service configuration Returns: filter (obj): the filter subclass which meet the request Raises: Exception if missing or invalid parameters are used in the request """ content_type = environ.get('CONTENT_TYPE', '') # set method, requestObject and sosRequest method = str(environ['REQUEST_METHOD']).upper() if method == "GET": # Returns a dictionary containing lists as values. # > keep_blank_values used in version 2.0.0 to check # > null parameter exceptions rect = parse_qs(environ['QUERY_STRING'], keep_blank_values=True) requestObject = {} for key in rect.keys(): requestObject[key.lower()] = rect[key][0] if "request" in requestObject: sosRequest = requestObject["request"].lower() else: raise sosException.SOSException( "MissingParameterValue", "request", "Parameter \"request\" is mandatory") elif method == "POST": # the environment variable CONTENT_LENGTH may be empty or missing try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except (ValueError): request_body_size = 0 # get the request from xml.dom import minidom content = environ['wsgi.input'].read(request_body_size) if content_type.startswith("application/x-www-form-urlencoded"): form = cgi.parse_qs(content) if "request" in form: xmldoc = minidom.parseString(form["request"][0]) else: raise sosException.SOSException( "MissingParameterValue", "request", "Parameter \"request\" is mandatory") else: try: xmldoc = minidom.parseString(content) except: raise sosException.SOSException( "MissingParameterValue", None, "Unable to parse the request body: validation issue") requestObject = xmldoc.firstChild sosRequest = requestObject.localName.lower() else: raise sosException.SOSException( "InvalidRequest", None, "Allowed \"http request\" are GET and " "POST: %s" % (method == "GET")) # if request is allowed instantiate the rigth filter if sosRequest in sosConfig.parameters["requests"]: if sosRequest == "getcapabilities": from istsoslib.filters import GC_filter return GC_filter.sosGCfilter(sosRequest, method, requestObject, sosConfig) elif sosRequest == "describesensor": from istsoslib.filters import DS_filter return DS_filter.sosDSfilter(sosRequest, method, requestObject, sosConfig) elif sosRequest == "getobservation": from istsoslib.filters import GO_filter return GO_filter.sosGOfilter(sosRequest, method, requestObject, sosConfig) elif sosRequest == "getfeatureofinterest": from istsoslib.filters import GF_filter return GF_filter.sosGFfilter(sosRequest, method, requestObject, sosConfig) elif sosRequest == "insertobservation": from istsoslib.filters import IO_filter return IO_filter.sosIOfilter(sosRequest, method, content, sosConfig) elif sosRequest == "registersensor": from istsoslib.filters import RS_filter return RS_filter.sosRSfilter(sosRequest, method, content, sosConfig) elif sosRequest == "updateSensorDescription": from istsoslib.filters import USD_filter return USD_filter.sosUSDfilter(sosRequest, method, requestObject, sosConfig) else: raise sosException.SOSException( "InvalidParameterValue", "request", "\"request\": %s not supported" % (sosRequest))
def __init__(self, filter, pgdb): #sys.stderr.write("*****************************************************************") self.name = filter.featureOfInterest self.type = "" self.desc = "" self.procedures = [] self.idPrc = [] self.obsType = [] self.samplingTime = [] self.properties = [] self.geom = "" #select foi sql = "SELECT id_foi, name_foi, desc_foi, ST_AsGml(ST_Transform(geom_foi,%s)) as geom, name_fty" #%(filter.srsName) sql += " FROM %s.foi, %s.feature_type" % (filter.sosConfig.schema, filter.sosConfig.schema) sql += " WHERE id_fty_fk=id_fty AND name_foi=%s" #%(filter.featureOfInterest) params = (filter.srsName, str(filter.featureOfInterest)) try: foi = pgdb.select(sql, params)[0] except: raise sosException.SOSException( "InvalidParameterValue", "FeatureOfInterestId", "FeatureOfInterestId: Feature of Interest '%s' not found." % (filter.featureOfInterest)) self.name = foi["name_foi"] self.desc = foi["desc_foi"] self.type = foi["name_fty"] self.geom = foi["geom"] #select procedures sql = "SELECT id_prc, name_prc, name_oty " sql += "FROM %s.procedures, %s.foi, %s.obs_type " % ( filter.sosConfig.schema, filter.sosConfig.schema, filter.sosConfig.schema) sql += "WHERE id_foi_fk=id_foi AND id_oty=id_oty_fk AND name_foi=%s " #%(filter.featureOfInterest) sql += "ORDER BY name_prc " params = (str(filter.featureOfInterest), ) try: prc = pgdb.select(sql, params) except: raise Exception("GFresponse, SQL: %s" % (pgdb.mogrify(sql, params))) for p in prc: self.procedures.append(p["name_prc"]) self.obsType.append(p["name_oty"]) self.idPrc.append(p["id_prc"]) # select obesrved properties of aa given procedure sql = "SELECT name_opr " sql += " FROM %s.procedures, %s.proc_obs, %s.observed_properties" % ( filter.sosConfig.schema, filter.sosConfig.schema, filter.sosConfig.schema) sql += " WHERE id_prc=id_prc_fk AND id_opr=id_opr_fk AND name_prc=%s" #%(p["name_prc"]) sql += " ORDER BY name_opr" params = (p["name_prc"], ) try: obs = pgdb.select(sql, params) except: raise Exception("GFresponse, SQL: %s" % (pgdb.mogrify(sql, params))) obsArr = [] for o in obs: obsArr.append(o['name_opr']) self.properties.append(obsArr) sql = "SELECT MIN(time_eti) as firstet, MAX(time_eti) as lastet FROM %s.event_time " % ( filter.sosConfig.schema) sql += "WHERE id_prc_fk = %s GROUP BY id_prc_fk" #% (p["id_prc"]) params = (p["id_prc"], ) try: samplTime = pgdb.select(sql, params) except: raise Exception("GFresponse, SQL: %s" % (pgdb.mogrify(sql, params))) samplTimeArr = [] for st in samplTime: samplTimeArr.append([st['firstet'], st['lastet']]) self.samplingTime.append(samplTimeArr)
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) if method == "GET": raise sosException.SOSException( "NoApplicableCode", None, "registerSensor request support only POST method!") if method == "POST": from StringIO import StringIO tree, ns = parse_and_get_ns(StringIO(requestObject)) SensorDescription = tree.find("{%s}SensorDescription" % ns['sos']) if SensorDescription is None: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", ("sos:SensorDescription parameter is " "mandatory with multiplicity 1")) name = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}name" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) self.procedure = name.text description = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}description" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) if not description is None: self.proc_desc = description.text else: self.proc_desc = 'NULL' #---Capabilities capabilities = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/" "{%s}capabilities/{%s}DataRecord/{%s}field" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['swe'], ns['swe'])) self.time_sam_val = "0" self.time_acq_val = "0" for cap in capabilities: if ('name' in cap.attrib and cap.attrib['name'] == 'Sampling time resolution'): tmpSam = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if 'code' in uom.attrib: uomSam = uom.attrib['code'] self.time_sam_val = convertToSec[uomSam](tmpSam) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", ("sml:capabilities, missing uom for " "Sampling time resolution")) elif ('name' in cap.attrib and cap.attrib['name'] == 'Acquisition time resolution'): tmpAcq = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if 'code' in uom.attrib: uomAcq = uom.attrib['code'] self.time_acq_val = convertToSec[uomAcq](tmpAcq) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", ("sml:capabilities, missing uom " "for Sampling time resolution")) self.systemType = None classifiers = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/" "{%s}classification/{%s}ClassifierList/{%s}classifier" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['sml'], ns['sml'])) for classifier in classifiers: if ('name' in classifier.attrib and classifier.attrib['name'] == 'System Type'): val = classifier.find("{%s}Term/{%s}value" % (ns['sml'], ns['sml'])) if val is not None: self.systemType = val.text member = tree.find("{%s}SensorDescription/{%s}member" % (ns['sos'], ns['sml'])) root = et.Element("{%s}SensorML" % ns['sml']) root.attrib["{%s}schemaLocation" % ns['xsi']] = ( "http://www.opengis.net/sensorML/1.0.1 " "http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd") root.attrib["version"] = "1.0.1" root.append(member) self.xmlSensorDescription = root """ from xml.dom.minidom import parseString txt = et.tostring(root, encoding="UTF-8") self.xmlSensorDescription = parseString(txt).toprettyxml() """ ObservationTemplate = tree.find("{%s}ObservationTemplate" % ns['sos']) if ObservationTemplate is None: raise sosException.SOSException( "MissingParameterValue", "ObservationTemplate", ("ObservationTemplate parameter is " "mandatory with multiplicity 1")) Observation = ObservationTemplate.find("{%s}Observation" % ns['om']) if Observation is None: raise sosException.SOSException( "NoApplicableCode", None, "om:Observation tag is mandatory with multiplicity 1") procedure = Observation.find("{%s}procedure" % ns['om']) self.procedure = procedure.attrib["{%s}href" % ns['xlink']].split(":")[-1] if procedure is None: raise sosException.SOSException( "NoApplicableCode", None, "om:procedure tag is mandatory with multiplicity 1") self.oprDef = [] self.oprDesc = [] self.oprName = [] self.beginPosition = 'NULL' try: name = Observation.find( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}name" % (ns['om'], ns['swe'], ns['gml'])) except: raise sosException.SOSException( "NoApplicableCode", None, "swe:CompositePhenomenon mandatory name element is missing" ) components = Observation.findall( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}component" % (ns['om'], ns['swe'], ns['swe'])) if not components == []: for comp in components: try: self.oprDef.append(comp.attrib["{%s}href" % ns['xlink']]) except: raise sosException.SOSException( "NoApplicableCode", None, ("om:observedProperty/component attribute " "missing: 'xlink:href' required")) featureOfInterest = Observation.find("{%s}featureOfInterest" % ns['om']) if featureOfInterest is None: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest tag is mandatory with multiplicity 1" ) try: self.foiName = featureOfInterest.attrib["{%s}href" % ns['xlink']] except: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest: attribute 'xlink:href' is required") description = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/{%s}description" % (ns['om'], ns['gml'], ns['gml'])) if not description is None: self.foiDesc = description.text else: self.foiDesc = "NULL" self.foiType = None for geomtype in sosConfig.foiGeometryType: geomtype = geomtype.split(":")[1] GMLfeature = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/" "{%s}location/{%s}%s" % (ns['om'], ns['gml'], ns['gml'], ns['gml'], geomtype)) if not GMLfeature is None: self.foiType = geomtype self.foiSRS = GMLfeature.attrib["srsName"].split(":")[-1] self.foiGML = et.tostring( GMLfeature, encoding="UTF-8").replace( "<?xml version='1.0' encoding='UTF-8'?>", "") if self.foiType is None: raise sosException.SOSException( "NoApplicableCode", None, "not found valid GML feature, supported: %s " % (";".join(sosConfig.foiGeometryType))) result = Observation.find("{%s}result" % ns['om']) self.parameters = [] self.uoms = [] self.names = [] self.descs = [] self.constr = [] self.partime = [] if not result is None: sdr = Observation.find("{%s}result/{%s}SimpleDataRecord" % (ns['om'], ns['swe'])) da = Observation.find("{%s}result/{%s}DataArray" % (ns['om'], ns['swe'])) if sdr is not None and da is None: fields = sdr.findall("{%s}field" % ns['swe']) elif da is not None and sdr is None: fields = da.findall( "{%s}elementType/{%s}DataRecord/{%s}field" % (ns['swe'], ns['swe'], ns['swe'])) else: err_txt = ( "in <swe:result>: <swe:DataRecord> or " "<swe:DataArray> are mandatory in multiplicity 1") raise sosException.SOSException("NoApplicableCode", None, err_txt) timetag = False for field in fields: defin = None uom = None self.names.append(field.attrib['name']) tf = field.find("{%s}Time" % ns['swe']) qf = field.find("{%s}Quantity" % ns['swe']) if not tf is None and qf is None: self.partime.append(1) timetag = True self.parameters.append(tf.attrib["definition"]) uom = tf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = tf.find("{%s}description" % ns['swe']) if not desc is None: self.descs.append(desc.text) else: self.descs.append("NULL") elif not qf is None and tf is None: self.partime.append(0) self.parameters.append(qf.attrib["definition"]) uom = qf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = qf.find("{%s}description" % ns['swe']) if not desc is None: self.descs.append(desc.text) else: self.descs.append("NULL") cc = {} constraints = qf.findall("{%s}constraint" % (ns['swe'])) if len(constraints) == 0: self.constr.append(None) else: for constraint in constraints: if (constraint and "{%s}role" % ns["xlink"] in constraint.attrib): if constraint.attrib["{%s}role" % ns[ "xlink"]] == "urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable": crole = constraint.attrib["{%s}role" % ns["xlink"]] allow = constraint.find( "{%s}AllowedValues" % (ns['swe'])) if allow is None: err_txt = "in <swe:constraint>: <swe:AllowedValues> is mandatory in multiplicity 1" raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: cvals = None if len(allow) == 1: ct = allow[0].tag if not ct in [ "{%s}min" % ns["swe"], "{%s}max" % ns["swe"], "{%s}interval" % ns["swe"], "{%s}valueList" % ns["swe"] ]: err_txt = "in <swe:constraint>: support only min, max, interval, valueList tag" raise sosException.SOSException( "NoApplicableCode", None, err_txt) xvals = allow[0].text.strip( ).split(" ") if ct == "{%s}min" % ns["swe"]: ct = "min" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float(xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}max" % ns[ "swe"]: ct = "max" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float(xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}interval" % ns[ "swe"]: ct = "interval" if not len(xvals) == 2: err_txt = "'%s' constraint support/need two values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float(xvals[0]), float(xvals[1]) ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}valueList" % ns[ "swe"]: ct = "valueList" if not len(xvals) > 0: err_txt = "'%s' constraint support/need at least one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float(a) for a in xvals ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) cc["role"] = crole cc["%s" % ct] = cvals if not cc == {}: self.constr.append(json.dumps(cc)) else: self.constr.append(None) else: err_txt = ("swe:Time or swe:Quantity is mandatory " "in multiplicity 1:N") raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: err_txt = "om:result is mandatory in multiplicity 1:N" raise sosException.SOSException("NoApplicableCode", None, err_txt)
def __init__(self, sosRequest, method, requestObject, sosConfig): """Init sosFilter class""" self.request = sosRequest if self.request == '': raise sosException.SOSException("MissingParameterValue", "request", "Missing 'request' parameter") self.sosConfig = sosConfig if method == "GET": # OGC 12-006/REQ 5: # http://www.opengis.net/spec/SOS/2.0/req/core/gc-version if self.request == "getcapabilities": if "acceptversions" in requestObject: AcceptVersions = requestObject["acceptversions"].split(",") AcceptVersions.sort() self.version = None for version in AcceptVersions: if version in sosConfig.parameters["version"]: self.version = version break if not self.version: raise sosException.SOSException( "VersionNegotiationFailed", None, "Any of the accepted versions are supported" " by this server") else: self.version = sosConfig.parameters["default_version"] else: # OGC 12-006/REQ 2: # http://www.opengis.net/spec/SOS/2.0/req/core/request-version if "version" in requestObject: self.version = requestObject["version"] if self.version == '': raise sosException.SOSException( "MissingParameterValue", "version", "Missing 'version' parameter") if self.version not in sosConfig.parameters["version"]: raise sosException.SOSException( "InvalidParameterValue", "version", "\"version\": %s not supported" % (self.version)) else: raise sosException.SOSException( "MissingParameterValue", "version", "\"version\" parameter is mandatory") # OGC 12-006/REQ 1: # http://www.opengis.net/spec/SOS/2.0/req/core/request-service if "service" in requestObject: self.service = requestObject["service"] if self.service == '': raise sosException.SOSException( "MissingParameterValue", "service", "Missing 'service' parameter") if self.service not in sosConfig.parameters["service"]: raise sosException.SOSException( "InvalidParameterValue", "service", "\"service\": %s not supported" % (self.service)) else: raise sosException.SOSException( "MissingParameterValue", "service", "\"service\" parameter is mandatory") if method == "POST": if not isinstance(requestObject, basestring): # OGC 12-006/REQ 1: # http://www.opengis.net/spec/SOS/2.0/req/core/request-service if "service" in requestObject.attributes.keys(): self.service = str(requestObject.getAttribute("service")) if self.service not in sosConfig.parameters["service"]: raise sosException.SOSException( "InvalidParameterValue", "service", "\"service\": %s not supported" % (self.service)) else: raise sosException.SOSException( "MissingParameterValue", "service", "\"service\" parameter is mandatory") # OGC 12-006/REQ 5: # http://www.opengis.net/spec/SOS/2.0/req/core/gc-version if self.request == "getcapabilities": AcceptVersions = requestObject.getElementsByTagName( 'AcceptVersions') if len(AcceptVersions) > 1: raise sosException.SOSException( "InvalidParameterValue", "AcceptVersions", "AcceptVersions multiplicity is 1" % (self.version)) elif len(AcceptVersions) == 1: VersionsObj = requestObject.getElementsByTagName( 'Version') versions = [ str(val.firstChild.data) for val in VersionsObj ] versions.sort() self.version = None for version in versions: if version in sosConfig.parameters["version"]: self.version = version break if not self.version: raise sosException.SOSException( "VersionNegotiationFailed", None, "Any of the accepted versions are " "supported by this server") else: self.version = sosConfig.parameters["version"][0] else: # OGC 12-006/REQ 2: # http://www.opengis.net/spec/SOS/2.0/req/ # core/request-version if "version" in requestObject.attributes.keys(): self.version = str( requestObject.getAttribute("version")) if self.version not in sosConfig.parameters["version"]: raise sosException.SOSException( "InvalidParameterValue", "version", "\"version\": %s not supported" % (self.version)) else: self.version = sosConfig.parameters["default_version"]
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) if method == "GET": self.outputFormat = None self.procedure = None if self.version == '2.0.0': # OUTPUTFORMAT if requestObject.has_key("procedure"): if requestObject["procedure"] == '': raise sosException.SOSException( "MissingParameterValue", "procedure", "Missing 'procedure' parameter") if requestObject.has_key("proceduredescriptionformat"): if requestObject["proceduredescriptionformat"] == '': raise sosException.SOSException( "MissingParameterValue", "proceduredescriptionformat", "Missing 'proceduredescriptionformat' parameter") if requestObject[ "proceduredescriptionformat"] in sosConfig.parameters[ "DS_outputFormats_2_0_0"]: self.outputFormat = requestObject[ "proceduredescriptionformat"] else: raise sosException.SOSException( "InvalidParameterValue", "procedureDescriptionFormat", "Supported \"procedureDescriptionFormat\" values are: " + ",".join(sosConfig. parameters["DS_outputFormats_2_0_0"])) else: raise sosException.SOSException( "MissingParameterValue", "procedureDescriptionFormat", "Parameter \"procedureDescriptionFormat\" is mandatory" ) else: # OUTPUTFORMAT if requestObject.has_key("outputformat"): if requestObject["outputformat"] in sosConfig.parameters[ "DS_outputFormats"]: self.outputFormat = requestObject["outputformat"] else: err_txt = "Supported \"outputFormat\" values are: " + ",".join( sosConfig.parameters["DS_outputFormats"]) raise sosException.SOSException( "InvalidParameterValue", "outputFormat", err_txt) else: raise sosException.SOSException( "MissingParameterValue", "outputFormat", "Parameter \"outputFormat\" is mandatory") # PROCEDURES if requestObject.has_key("procedure"): if requestObject["procedure"] == '': raise sosException.SOSException( "MissingParameterValue", "procedure", "Missing 'procedure' parameter") prc = requestObject["procedure"].split(":") self.procedure = prc[-1] if len(prc) > 1: prc[-1] = "" if ":".join(prc) == sosConfig.urn["procedure"]: pass else: err_txt = "Supported \"procedure\" urn is: " + sosConfig.urn[ "procedure"] err_txt += "\n passed: " + ":".join(prc) raise sosException.SOSException( "InvalidParameterValue", "procedure", err_txt) else: raise sosException.SOSException( "MissingParameterValue", "procedure", "Parameter \"procedure\" is mandatory with multiplicity 1") if method == "POST": self.outputFormat = None self.procedure = None # OUTPUTFORMAT if "outputFormat" in requestObject.attributes.keys(): self.outputFormat = str( requestObject.getAttribute("outputFormat")) if self.outputFormat not in sosConfig.parameters[ "DS_outputFormats"]: err_txt = "Allowed \"outputFormat\" values are: " + ",".join( sosConfig.parameters["DS_outputFormats"]) raise sosException.SOSException("InvalidParameterValue", "outputFormat", err_txt) else: err_txt = "Parameter \"outputFormat\" is mandatory" raise sosException.SOSException( "MissingParameterValue", "outputFormat", "Parameter \"outputFormat\" is mandatory") # PROCEDURES procs = requestObject.getElementsByTagName('procedure') if len(procs) > 0: if len(procs) < 2: val = procs[0].firstChild if val.nodeType == val.TEXT_NODE: """ self.procedure = str(val.data) """ prc = str(val.data).split(":") if len(prc) > 1: if prc[0:-1] == filter( None, sosConfig.urn["procedure"].split(":")): pass else: err_txt = "Supported \"procedure\" urn is: " + sosConfig.urn[ "procedure"] raise sosException.SOSException( "InvalidParameterValue", "procedure", err_txt) self.procedure = prc[-1] else: err_txt = "XML parsing error (get value: procedure)" raise sosException.SOSException( "MissingParameterValue", "procedure", "Parameter \"procedure\" is mandatory with multiplicity 1", err_txt) else: err_txt = "Allowed only ONE parameter \"procedure\"" raise sosException.SOSException("IvalidParameterValue", "procedure", err_txt) else: err_txt = "Parameter \"procedure\" is mandatory" raise sosException.SOSException( "MissingParameterValue", "procedure", "Parameter \"procedure\" is mandatory with multiplicity 1")
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) if method == "GET": raise sosException.SOSException( "NoApplicableCode", None, "insertObservation request support " "only POST method!") if method == "POST": from StringIO import StringIO tree, ns = parse_and_get_ns(StringIO(requestObject)) # Workaround for rare xml parsing bug in etree ns = { 'gml': 'http://www.opengis.net/gml', 'swe': 'http://www.opengis.net/swe', 'om': 'http://www.opengis.net/om/1.0', 'sos': 'http://www.opengis.net/sos/1.0', 'xlink': 'http://www.w3.org/1999/xlink', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance' } if not 'swe' in ns: ns['swe'] = 'http://www.opengis.net/swe/1.0.1' # assignedSensorId AssignedSensorId = tree.find("{%s}AssignedSensorId" % ns['sos']) if AssignedSensorId is None: raise sosException.SOSException( "MissingParameterValue", "AssignedSensorId", "sos:AssignedSensorId parameter is mandatory " "with multiplicity 1") else: self.assignedSensorId = AssignedSensorId.text.split(":")[-1] # forceInsert ForceInsert = tree.find("{%s}ForceInsert" % ns['sos']) if not ForceInsert is None: if ForceInsert.text == 'true' or ForceInsert.text == "": self.forceInsert = True elif ForceInsert.text == 'false': self.forceInsert = False else: err_txt = ("parameter \"ForceInsert\" can only be: " "'true' or 'false'") raise sosException.SOSException("InvalidParameterValue", "ForceInsert", err_txt) else: self.forceInsert = False # om:observation Observation = tree.find("{%s}Observation" % ns['om']) if Observation is None: raise sosException.SOSException( "MissingParameterValue", "Observation", "om:Observation tag is mandatory with multiplicity 1") # procedure procedure = Observation.find("{%s}procedure" % ns['om']) if procedure is None: raise sosException.SOSException( "NoApplicableCode", None, "om:procedure tag is mandatory with multiplicity 1") self.procedure = procedure.attrib["{%s}href" % ns['xlink']].split(":")[-1] # ObservedProperties self.oprName = [] observedProperty = Observation.find("{%s}observedProperty" % ns['om']) if observedProperty is None: raise sosException.SOSException( "NoApplicableCode", None, "om:observedProperty tag is mandatory with multiplicity 1") CompositPhenomenon = observedProperty.find( "{%s}CompositePhenomenon" % ns['swe']) if not CompositPhenomenon is None: components = CompositPhenomenon.findall("{%s}component" % ns['swe']) for co in components: try: self.oprName.append(co.attrib["{%s}href" % ns['xlink']]) except: try: name = co.find("{%s}name" % ns['gml']) self.oprName.append(name.text) except: raise sosException.SOSException( "NoApplicableCode", None, "om:observedProperty Name is missing: " "'xlink:href' or 'gml:name' required") else: try: self.oprName.append(observedProperty.attrib["{%s}href" % ns['xlink']]) except: try: name = co.find("{%s}name" % ns['gml']) self.oprName.append(name.text) except: print >> sys.stderr, "XML: %s" % requestObject raise sosException.SOSException( "NoApplicableCode", None, "om:observedProperty Name is missing: " "'xlink:href' or 'gml:name' required") # samplingTime samplingTime = Observation.find("{%s}samplingTime" % ns['om']) if samplingTime is None: raise sosException.SOSException( "NoApplicableCode", None, "om:samplingTime is mandatory in multiplicity 1") TimePeriod = samplingTime.find("{%s}TimePeriod" % ns['gml']) if not TimePeriod is None: bp = TimePeriod.find("{%s}beginPosition" % ns['gml']) ep = TimePeriod.find("{%s}endPosition" % ns['gml']) if bp is None or ep is None: raise sosException.SOSException( "NoApplicableCode", None, "gml:TimePeriod is mandatory in multiplicity 1") self.samplingTime = bp.text + "/" + ep.text else: TimeInstant = samplingTime.find("{%s}TimeInstant" % ns['gml']) if not TimeInstant is None: tpos = TimeInstant.find("{%s}timePosition" % ns['gml']) self.samplingTime = tpos.text else: raise sosException.SOSException( "NoApplicableCode", None, "one of gml:TimePeriod or gml:TimeInstant " "is mandatory in multiplicity 1") # featureOfInterest featureOfInterest = Observation.find("{%s}featureOfInterest" % ns['om']) if featureOfInterest is None: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest tag is mandatory with " "multiplicity 1") try: self.foiName = featureOfInterest.attrib[ "{%s}href" % ns['xlink']].split(":")[-1] except: try: gml_name = featureOfInterest.find("{%s}name" % ns['gml']).split(":")[-1] self.foiName = gml_name.text except: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest name is missing: 'xlink:href' " "or 'gml:name' is required") # result if Observation.find("{%s}result" % ns['om']) is None: raise sosException.SOSException("NoApplicableCode", None, "om:result tag is required") SimpleDataRecord = Observation.find( "{%s}result/{%s}SimpleDataRecord" % (ns['om'], ns['swe'])) DataArray = Observation.find("{%s}result/{%s}DataArray" % (ns['om'], ns['swe'])) ################################################################### # RESULT # return self.data where self.data is a dictionary of "definition" # containing dictionary of "uom" and "vals" #""" e.g.: #self.data = { # "urn:ist:parameter:time:iso8601": # { # "uom":"sec", # "vals":[ # "2009-07-31T12:00:00+02:00", # "2009-07-31T12:10:00+02:00", # "2009-07-31T12:20:00+02:00"] # }, # "urn:ist:def:phenomenon:rainfall": # { # "uom":"mm", # "vals":[0.1,0.2,0.3,0.4] # } # } # ################################################################### self.parameters = [] self.uoms = [] self.data = {} #case SimpleDataRecord if not SimpleDataRecord is None and DataArray is None: fields = SimpleDataRecord.findall("{%s}field" % ns['swe']) for field in fields: defin = None uom = None vals = [] fieldName = field.attrib["name"] if not field.find("{%s}Time" % ns['swe']) is None: tf = field.find("{%s}Time" % ns['swe']) defin = tf.attrib["definition"] vals.append(tf.find("{%s}value" % ns['swe']).text) elif not field.find("{%s}Quantity" % ns['swe']) is None: qf = field.find("{%s}Quantity" % ns['swe']) defin = qf.attrib["definition"] uom = qf.find("{%s}uom" % ns['swe']).attrib["code"] vals.append(qf.find("{%s}value" % ns['swe']).text) else: raise sosException.SOSException( "NoApplicableCode", None, "swe:Time or swe:Quantity is mandatory in " "multiplicity 1") self.data[defin] = {"uom": uom, "vals": vals} # Case DataArray elif SimpleDataRecord is None and not DataArray is None: DataRecord = DataArray.find("{%s}elementType/{%s}DataRecord" % (ns['swe'], ns['swe'])) fields = DataRecord.findall("{%s}field" % ns['swe']) urnlist = [] for id, field in enumerate(fields): defin = None uom = None vals = [] #fieldName = field.attrib["name"] if not field.find("{%s}Time" % ns['swe']) is None: swet = field.find("{%s}Time" % ns['swe']) defin = swet.attrib["definition"] urnlist.append(swet.attrib["definition"]) elif not field.find("{%s}Quantity" % ns['swe']) is None: sweq = field.find("{%s}Quantity" % ns['swe']) defin = sweq.attrib["definition"] urnlist.append(sweq.attrib["definition"]) if not sweq.find("{%s}uom" % ns['swe']) is None: uom = sweq.find("{%s}uom" % ns['swe']).attrib["code"] else: raise sosException.SOSException( "NoApplicableCode", None, "swe:Time or swe:Quantity is mandatory in " "multiplicity 1") self.data[defin] = {"uom": uom, "vals": vals} # encoding encodingTxtBlock = Observation.find( "{%s}result/{%s}DataArray/{%s}encoding/{%s}TextBlock" % (ns['om'], ns['swe'], ns['swe'], ns['swe'])) if encodingTxtBlock is None: raise sosException.SOSException( "NoApplicableCode", None, "swe:encoding is mandatory in multiplicity 1") tokenSeparator = encodingTxtBlock.attrib["tokenSeparator"] blockSeparator = encodingTxtBlock.attrib["blockSeparator"] values = Observation.find( "{%s}result/{%s}DataArray/{%s}values" % (ns['om'], ns['swe'], ns['swe'])) if values is None: raise sosException.SOSException( "NoApplicableCode", None, "swe:values is mandatory in multiplicity 1") self.dataArray = [] if values.text: valsplit = [ i.split(tokenSeparator) for i in values.text.split(blockSeparator) ] self.dataArray = valsplit for index, c in enumerate(urnlist): col = [] for l in valsplit: col.append(l[index]) self.data[c]["vals"] = col # case simple om:result elif SimpleDataRecord is None and DataArray is None: self.data[sosConfig.urn["time"]] = { "uom": None, "vals": [self.samplingTime] } result = Observation.find("{%s}result" % (ns['om'])) uom = result.attrib["uom"] vals = result.text self.data[sosConfig.urn["phenomena"] + self.oprName] = { "uom": uom, "vals": vals } self.dataArray = [[self.samplingTime, vals]] # error else: raise sosException.SOSException( "NoApplicableCode", None, "om:SimpleDataRecord in multiplicity N or om:DataArray " "in multiplicity 1 is mandatory")
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__( self, sosRequest, method, requestObject, sosConfig ) if method == "GET": self.eventTime = None self.featureOfInterest = None self.featureOfInterestSpatial = None self.result = None # zero-one optional self.observedProperty = [':'] # OBSERVED PROPERTY # get_name_from_urn limit the ability to ask for an observedProperty with LIKE: # eg: ask "water" to get all the water related data, "water:discharge", "water:temperature" ... if "observedproperty" in requestObject: self.observedProperty = [] oprs = requestObject["observedproperty"].split(",") for opr in oprs: if opr == '': raise sosException.SOSException( "MissingParameterValue", "observedProperty", "Missing 'observedProperty' parameter" ) oprName = opr self.observedProperty.append(oprName) # one-many ID # PROCEDURES FILTER if "procedure" in requestObject: self.procedure = [] prcs = requestObject["procedure"].split(",") for prc in prcs: if prc == '': raise sosException.SOSException( "MissingParameterValue", "procedure", "Missing 'procedure' parameter" ) try: prcName = get_name_from_urn( prc, "procedure", sosConfig ) except Exception as e: raise sosException.SOSException( "InvalidParameterValue", "procedure", str(e) ) self.procedure.append(prcName) else: self.procedure = None if self.version == '2.0.0': # THE OFFERING # > in istSOS offerings are equals to procedures # > so offerings are inserted into the procedure array filter if "offering" in requestObject: prcs = requestObject["offering"].split(",") if self.procedure is None: self.procedure = [] for prc in prcs: if prc == '': raise sosException.SOSException( "MissingParameterValue", "offering", "Missing 'offering' parameter" ) try: prcName = get_name_from_urn( prc, "offering", sosConfig ) except Exception as e: raise sosException.SOSException( "InvalidParameterValue", "offering", str(e) ) # Check for name redundancy if prcName not in self.procedure: self.procedure.append(prcName) # RESPONSE FORMAT self.responseFormat = 'text/xml;subtype="om/2.0"' if "responseformat" in requestObject: if requestObject["responseformat"] == '': raise sosException.SOSException( "MissingParameterValue", "responseformat", "Missing 'responseformat' parameter" ) if not requestObject["responseformat"] in sosConfig.parameters["GO_responseFormat_2_0_0"]: raise sosException.SOSException( "InvalidParameterValue", "responseFormat", "Parameter \"responseFormat\" sent with invalid value : use one of %s" % "; ".join(sosConfig.parameters["GO_responseFormat_2_0_0"]) ) elif requestObject["responseformat"] == sosConfig.parameters["GO_responseFormat_2_0_0"][0]: self.responseFormat = 'text/xml;subtype="om/2.0"' else: self.responseFormat = requestObject["responseformat"] # OPTIONAL SRS FILTER if "crs" in requestObject: try: self.srsName = requestObject["crs"].split(':')[-1] except Exception as e: raise sosException.SOSException("InvalidParameterValue", "crs", "%s" % e) if self.srsName not in sosConfig.parameters["GO_srs"]: raise sosException.SOSException( "InvalidParameterValue", "crs", "crs \"%s\" not supported, use one of: %s" %(self.srsName, ",".join(sosConfig.parameters["GO_srs"])) ) else: self.srsName = sosConfig.parameters["GO_srs"][0] # TIME FILTER # istSOS supports # kvp examples: # - during: temporalFilter=om:phenomenonTime,2012-11-19T14:00:00+01:00/2012-11-19T14:15:00+01:00 # - equals: temporalFilter=om:phenomenonTime,2012-11-19T14:00:00.000+01:00 # - combination: temporalFilter=om:phenomenonTime,2012-11-19T14:00:00+01:00/2012-11-19T14:15:00+01:00,2012-11-19T14:00:00.000+01:00 if 'temporalfilter' in requestObject: self.eventTime = [] temporalfilter = requestObject["temporalfilter"].replace( " ", "+").split(",") # > in istSOS om:phenomenonTime is equals to om:resultTime if temporalfilter.pop(0) not in ['om:phenomenonTime','phenomenonTime','om:resultTime','resultTime']: raise sosException.SOSException("InvalidParameterValue", "temporalfilter", "Parameter \"temporalFilter\" bad formatted") for i in temporalfilter: if '/' in i: interval = i.split("/") if len(interval) != 2: raise sosException.SOSException( "InvalidParameterValue", "temporalfilter", "Parameter \"temporalfilter\" bad formatted" ) try: iso.parse_date(interval[0]) iso.parse_date(interval[1]) except iso.ISO8601Error as isoerr: raise sosException.SOSException( "InvalidParameterValue", "temporalfilter", "Parameter \"temporalfilter\" bad formatted, %s" % isoerr ) self.eventTime.append(interval) else: try: iso.parse_date(i) except iso.ISO8601Error as isoerr: raise sosException.SOSException( "InvalidParameterValue", "temporalfilter", "Parameter \"temporalfilter\" bad formatted, %s" % isoerr ) self.eventTime.append([i]) # FEATURES OF INTEREST FILTER if "featureofinterest" in requestObject: if requestObject["featureofinterest"] == '': raise sosException.SOSException("MissingParameterValue", "featureOfInterest", "Missing 'featureOfInterest' parameter") if sosConfig.urn["feature"] in requestObject["featureofinterest"]: self.featureOfInterest = get_name_from_urn(requestObject["featureofinterest"], "feature", sosConfig) else: self.featureOfInterest = requestObject["featureofinterest"] # SPATIAL FILTER # example1: spatialFilter=om:featureOfInterest/*/sams:shape,0.0,0.0,60.0,60.0,http://www.opengis.net/def/crs/EPSG/0/4326 # example2: spatialFilter=om:featureOfInterest/*/sams:shape,0.0,0.0,60.0,60.0,urn:ogc:def:crs:EPSG::4326 if "spatialfilter" in requestObject: sfs = requestObject["spatialfilter"].split(",") if len(sfs) != 6: raise sosException.SOSException( "InvalidParameterValue", "spatialfilter", "Invalid spatial filter '%s'" % requestObject["spatialfilter"] ) if sfs[0] != 'om:featureOfInterest/*/sams:shape': raise sosException.SOSException("InvalidParameterValue", "spatialfilter", "Invalid spatial filter '%s'" % requestObject["spatialfilter"]) srsName = None if sfs[5].index(':')>-1: srsName = sfs[5].split(':')[-1] if sfs[5].index('/')>-1: srsName = sfs[5].split('/')[-1] ogcfilter = ( "<ogc:BBOX>" + "<ogc:PropertyName>the_geom</ogc:PropertyName>"+ ("<gml:Box srsName='EPSG:%s'>" % (srsName) )+ ("<gml:coordinates>%s,%s %s,%s</gml:coordinates>" % (sfs[1], sfs[2], sfs[3], sfs[4])) + "</gml:Box>"+ "</ogc:BBOX>") self.featureOfInterestSpatial = sosUtils.ogcSpatCons2PostgisSql( ogcfilter, 'geom_foi', sosConfig.istsosepsg ) else: # THE OFFERING if "offering" in requestObject: try: self.offering = get_name_from_urn(requestObject["offering"], "offering", sosConfig) except Exception as e: raise sosException.SOSException("InvalidParameterValue","offering",str(e)) # RESPONSE FORMAT if "responseformat" in requestObject: if requestObject["responseformat"] == '': raise sosException.SOSException("MissingParameterValue", "responseFormat", "Missing 'responseFormat' parameter") if not requestObject["responseformat"] in sosConfig.parameters["GO_responseFormat"]: raise sosException.SOSException("InvalidParameterValue", "responseFormat", "Parameter \"responseFormat\" sent with invalid value : use one of %s" % "; ".join(sosConfig.parameters["GO_responseFormat"])) else: self.responseFormat = requestObject["responseformat"] if "offering" not in requestObject: raise sosException.SOSException("MissingParameterValue", "offering", "Parameter \"offering\" is mandatory with multiplicity 1") if "observedproperty" not in requestObject: raise sosException.SOSException("MissingParameterValue", "observedProperty", "Parameter \"observedProperty\" is mandatory with multiplicity N") if "responseformat" not in requestObject: raise sosException.SOSException("MissingParameterValue", "responseFormat", "Parameter \"responseFormat\" is mandatory with multiplicity 1") #one # OPTIONAL SRS FILTER if "srsname" in requestObject: try: self.srsName = get_name_from_urn(requestObject["srsname"], "refsystem", sosConfig) except Exception as e: raise sosException.SOSException("InvalidParameterValue", "srsname", "%s" % e) if not self.srsName in sosConfig.parameters["GO_srs"]: raise sosException.SOSException("InvalidParameterValue", "srsName", "srsName \"%s\" not supported, use one of: %s" %(self.srsName, ",".join(sosConfig.parameters["GO_srs"]))) else: self.srsName = sosConfig.parameters["GO_srs"][0] # TIME FILTER if 'eventtime' in requestObject: self.eventTime = [] for i in requestObject["eventtime"].replace(" ","+").split(","): if len(i.split("/")) < 3: self.eventTime.append(i.split("/")) else: raise sosException.SOSException("InvalidParameterValue", "eventTime", "Parameter \"eventTime\" bad formatted") # FEATURES OF INTEREST FILTER if "featureofinterest" in requestObject: foi = requestObject["featureofinterest"] if foi.find("<ogc:") >= 0 and foi.find("<gml:")>=0: self.featureOfInterestSpatial = sosUtils.ogcSpatCons2PostgisSql(foi, 'geom_foi', sosConfig.istsosepsg) else: try: self.featureOfInterest = get_name_from_urn(foi, "feature", sosConfig) except Exception as e: raise sosException.SOSException("InvalidParameterValue", "featureofinterest", str(e)) # FILTERS FOR QUERY NOT SUPPORTED YET if "result" in requestObject: self.result = sosUtils.ogcCompCons2PostgisSql(requestObject["result"]) # RESULT MODEL if "resultmodel" in requestObject: if requestObject["resultmodel"] in sosConfig.parameters["GO_resultModel"]: self.resultModel = requestObject["resultmodel"] else: raise sosException.SOSException("InvalidParameterValue", "resultModel", "Parameter \"resultModel\" sent with invalid value: supported values are: %s" %",".join(sosConfig.parameters["GO_resultModel"])) else: self.resultModel = sosConfig.parameters["GO_resultModel"][0] # RESPONSE MODE if "responsemode" in requestObject: if requestObject["responsemode"] in sosConfig.parameters["GO_responseMode"]: self.responseMode = requestObject["responsemode"] else: raise sosException.SOSException("InvalidParameterValue", "responseMode", "Parameter \"responseMode\" sent with invalid value, supported values are: %s" %(",".join(sosConfig.parameters["GO_responseMode"]))) else: self.responseMode = sosConfig.parameters["GO_responseMode"][0] # Checking if some event limitation is reached if self.eventTime != None: tp=[] for t in self.eventTime: if len(t) == 2: tp.append(iso.parse_datetime(t[0])) tp.append(iso.parse_datetime(t[1])) if len(t)==1: tp.append(iso.parse_datetime(t[0])) if int(sosConfig.maxGoPeriod) > 0: maxhours = timedelta(hours=int(sosConfig.maxGoPeriod)) userPeriod = max(tp)-min(tp) if maxhours < userPeriod: if self.version == '2.0.0': # REQ39 - http://www.opengis.net/spec/SOS/2.0/req/core/go-too-many-obs-exception # The service determined that the requested result set exceeds the response # size limit of the service and thus cannot be delivered. raise sosException.SOSException("ResponseExceedsSizeLimit", "", "You are requesting data for a period of [%s hours], but you are not permitted to ask for a period longer than: %s hours" % (userPeriod, maxhours)) else: raise sosException.SOSException("InvalidParameterValue", "eventTime", "You are requesting data for a period of [%s hours], but you are not permitted to ask for a period longer than: %s hours" % (userPeriod, maxhours)) elif ( sosConfig.strictogc in ['True','true',1] and self.version == '2.0.0' and self.eventTime == None and self.featureOfInterest == None and self.featureOfInterestSpatial == None and self.procedure == None ): # ResponseExceedsSizeLimit fake exception raise sosException.SOSException("ResponseExceedsSizeLimit", "", "Sorry but, You are requesting too many data") ##################################### # NON STANDARD PARAMETERS by istSOS # ##################################### # AGGREGATE INTERVAL # In ISO 8601 duration format if "aggregateinterval" in requestObject: # Check on the eventTime parameter: it must be only one interval: 2010-01-01T00:00:00+00/2011-01-01T00:00:01+00 exeMsg = "Using aggregate functions, the event time must exist with an interval composed by a begin and an end date (ISO8601)" if self.eventTime == None or len(self.eventTime)!=1 or len(self.eventTime[0])!=2: raise sosException.SOSException("InvalidParameterValue", "aggregateInterval", exeMsg) self.aggregate_interval = requestObject["aggregateinterval"] try: iso.parse_duration(self.aggregate_interval) except Exception as ex: raise sosException.SOSException("InvalidParameterValue", "aggregateInterval", "Parameter \"aggregate_interval\" sent with invalid format (check ISO8601 duration spec): %s" % ex) else: self.aggregate_interval = None # AGGREGATE FUNCTION # sum,avg,max,min if "aggregatefunction" in requestObject: if self.aggregate_interval==None: raise sosException.SOSException("InvalidParameterValue", "aggregateFunction", "Using aggregate functions parameters \"aggregateInterval\" and \"aggregateFunction\" are both mandatory") self.aggregate_function = requestObject["aggregatefunction"] if not (self.aggregate_function.upper() in ["AVG", "COUNT", "MAX", "MIN", "SUM"]): raise sosException.SOSException("InvalidParameterValue", "aggregateFunction", "Available aggregation functions: avg, count, max, min, sum.") else: self.aggregate_function = None # AGGREGATE NODATA if "aggregatenodata" in requestObject: if self.aggregate_interval==None or self.aggregate_function==None: raise sosException.SOSException("InvalidParameterValue", "aggregateNodata", "Using aggregateNodata parameter requires both \"aggregateInterval\" and \"aggregateFunction\"") self.aggregate_nodata = requestObject["aggregatenodata"] else: self.aggregate_nodata = sosConfig.aggregate_nodata # AGGREGATE NODATA QUALITY INDEX if "aggregatenodataqi" in requestObject: if self.aggregate_interval==None or self.aggregate_function==None: raise sosException.SOSException("InvalidParameterValue", "aggregateNodataQi", "Using aggregateNodataQi parameter requires both \"aggregateInterval\" and \"aggregateFunction\"") self.aggregate_nodata_qi = requestObject["aggregatenodataqi"] else: self.aggregate_nodata_qi = sosConfig.aggregate_nodata_qi # QUALITY INDEX self.qualityIndex=False if "qualityindex" in requestObject: if requestObject["qualityindex"].upper() == "TRUE": self.qualityIndex = True elif requestObject["qualityindex"].upper() == "FALSE": self.qualityIndex = False else: raise sosException.SOSException("InvalidParameterValue", "qualityIndex", "qualityIndex can only be True or False!") # QUALITY INDEX FILTERING self.qualityFilter=False if "qualityfilter" in requestObject: if len(requestObject["qualityfilter"])>=2: try: if requestObject["qualityfilter"][0:2]=='<=' or requestObject["qualityfilter"][0:2]=='>=': self.qualityFilter = (requestObject["qualityfilter"][0:2], float(requestObject["qualityfilter"][2:])) elif (requestObject["qualityfilter"][0]=='>' or requestObject["qualityfilter"][0]=='=' or requestObject["qualityfilter"][0]=='<'): self.qualityFilter = (requestObject["qualityfilter"][0], float(requestObject["qualityfilter"][1:])) # If qualityFilter is defined qualityIndex are automatically returned self.qualityIndex=True except ValueError as ve: raise sosException.SOSException("InvalidParameterValue", "qualityFilter", "invalid quality index value in qualityFilter") else: raise sosException.SOSException("InvalidParameterValue", "qualityFilter", "qualityFilter operator can only be in ['<','>','<=','>=','=']") if method == "POST": from xml.dom import minidom # THE OFFERING offs = requestObject.getElementsByTagName('offering') if len(offs) == 1: val = offs[0].firstChild if val.nodeType == val.TEXT_NODE: try: self.offering = get_name_from_urn(str(val.data), "offering", sosConfig) except Exception as e: raise sosException.SOSException("InvalidParameterValue", "offering", str(e)) else: err_txt = "XML parsing error (get value: offering)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: err_txt = "Parameter \"offering\" is mandatory with multiplicity 1" raise sosException.SOSException("MissingParameterValue", "offering", err_txt) # THE OBSERVED PROPERTY obsProps = requestObject.getElementsByTagName('observedProperty') self.observedProperty = [] if len(obsProps) > 0: for obsProp in obsProps: val = obsProp.firstChild if val.nodeType == val.TEXT_NODE: # get_name_from_urn limit the ability to ask for an observedProperty with LIKE: # eg: ask "water" to get all the water related data, "water:discharge", "water:temperature" ... #self.observedProperty.append(get_name_from_urn(str(val.data),"property")) self.observedProperty.append(str(val.data)) else: err_txt = "XML parsing error (get value: observedProperty)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: err_txt = "Parameter \"observedProperty\" is mandatory with multiplicity N" raise sosException.SOSException("MissingParameterValue", "observedProperty", err_txt) # RESPONSE FORMAT respF = requestObject.getElementsByTagName('responseFormat') if len(respF) == 1: val = respF[0].firstChild if val.nodeType == val.TEXT_NODE: self.responseFormat = str(val.data) if self.responseFormat not in sosConfig.parameters["GO_responseFormat"]: raise sosException.SOSException("InvalidParameterValue", "responseFormat", "Parameter \"responseFormat\" sent with invalid value: use one of %s" % "; ".join(sosConfig.parameters["GO_responseFormat"])) else: err_txt = "XML parsing error (get value: responseFormat)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: err_txt = "Parameter \"responseFormat\" is mandatory with multiplicity 1" raise sosException.SOSException("MissingParameterValue", "responseFormat", err_txt) # OPTIONAL request parameters # SRS OF RETURNED GML FEATURES srs = requestObject.getAttributeNode('srsName') if srs: self.srsName = srs.nodeValue if not self.srsName in sosConfig.parameters["GO_srs"]: raise sosException.SOSException("InvalidParameterValue", "srsName", "srsName \"%s\" not supported, use one of: %s" %(self.srsName, ",".join(sosConfig.parameters["GO_srs"]))) else: self.srsName = sosConfig.parameters["GO_srs"][0] # TIME FILTER evtms = requestObject.getElementsByTagName('eventTime') self.eventTime = [] if len(evtms) > 0: for evtm in evtms: tps = evtm.getElementsByTagName('gml:TimePeriod') for tp in tps: begin = tp.getElementsByTagName('gml:beginPosition') end = tp.getElementsByTagName('gml:endPosition') if len(begin)==1 and len(end)==1: Bval = begin[0].firstChild Eval = end[0].firstChild if Bval.nodeType == Bval.TEXT_NODE and Eval.nodeType == Eval.TEXT_NODE: self.eventTime.append([str(Bval.data).replace(" ","+"), str(Eval.data).replace(" ","+")]) else: err_txt = "XML parsing error (get value: TimePeriod)" raise sosException.SOSException("NoApplicableCode",None,err_txt) tis = evtm.getElementsByTagName('gml:TimeInstant') for ti in tis: instant = ti.getElementsByTagName('gml:timePosition') if len(instant)>0 and len(instant)<2: Ival = instant[0].firstChild if Ival.nodeType == Ival.TEXT_NODE: self.eventTime.append([str(Ival.data).replace(" ","+")]) else: err_txt = "XML parsing error (get value: Timeinstant)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: self.eventTime = None # PROCEDURES FILTER procs = requestObject.getElementsByTagName('procedure') if len(procs) > 0: self.procedure=[] for proc in procs: if "xlink:href" in list(proc.attributes.keys()): self.procedure.append(str(proc.getAttribute("xlink:href"))) elif proc.hasChildNodes(): val = proc.firstChild if val.nodeType == val.TEXT_NODE: try: self.procedure.append(get_name_from_urn(str(val.data), "procedure", sosConfig)) except Exception as e: raise sosException.SOSException("InvalidParameterValue", "procedure", str(e)) else: err_txt = "XML parsing error (get value: procedure)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: self.procedure = None # FEATURES OF INTEREST FILTER fets = requestObject.getElementsByTagName('featureOfInterest') self.featureOfInterest = None self.featureOfInterestSpatial = None # get sub-elements of FOI if fets: elements = [e for e in fets[0].childNodes if e.nodeType == e.ELEMENT_NODE] if len(elements)==0: err_txt = "ObjectID or ogc:spatialOps elements in parameter \"featureOfInterest\" are mandatory" raise sosException.SOSException("NoApplicableCode",None,err_txt) # only one sub element elif len(elements)==1 and elements[0].tagName!="ObjectID" : self.featureOfInterestSpatial = sosUtils.ogcSpatCons2PostgisSql(elements[0], 'geom_foi', sosConfig.istsosepsg) else: tempfois=[] for e in elements: if not e.tagName=="ObjectID": err_txt = "Allowed only ObjectID or ogc:spatialOps elements in parameter \"featureOfInterest\"" raise sosException.SOSException("NoApplicableCode", None, err_txt) try: val = e.firstChild if val.nodeType == val.TEXT_NODE: try: tempfois.append( get_name_from_urn(str(val.data), "feature", sosConfig)) except Exception as e: raise sosException.SOSException("InvalidParameterValue", "featureOfInterest", str(e)) except Exception as e: raise e self.featureOfInterest = ",".join(tempfois) # FILTERS FOR QUERY NOT SUPPORTED YET ress = requestObject.getElementsByTagName('result') if len(ress)>0: raise sosException.SOSException("NoApplicableCode", None, "Parameter \"result\" not yet supported") else: self.result = None #zero-one optional # RESULT MODEL mods = requestObject.getElementsByTagName('resultModel') if len(mods)>0: if len(mods)<2: val = mods[0].firstChild if val.nodeType == val.TEXT_NODE: self.resultModel = str(val.data) if self.resultModel not in sosConfig.parameters["GO_resultModel"]: raise sosException.SOSException("InvalidParameterValue", "resultModel", "Parameter \"resultModel\" sent with invalid value") else: err_txt = "XML parsing error (get value: resultModel)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: err_txt = "Allowed only ONE parameter \"resultModel\"" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: self.resultModel = None # RESPONSE MODE rsmods = requestObject.getElementsByTagName('responseMode') if len(rsmods)>0: if len(rsmods)<2: val = rsmods[0].firstChild if val.nodeType == val.TEXT_NODE: self.responseMode = str(val.data) if self.responseMode not in sosConfig.parameters["GO_responseMode"]: raise sosException.SOSException("InvalidParameterValue", "responseMode", "Parameter \"responseMode\" sent with invalid value") else: err_txt = "XML parsing error (get value: responseMode)" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: err_txt = "Allowed only ONE parameter \"responseMode\"" raise sosException.SOSException("NoApplicableCode", None, err_txt) else: self.responseMode = sosConfig.parameters["GO_responseMode"][0] # AGGREGATE INTERVAL & FUNCTION self.aggregate_interval = None self.aggregate_function = None self.aggregate_nodata = None self.aggregate_nodata_qi = None aggint = requestObject.getElementsByTagName('aggregateInterval') aggfun = requestObject.getElementsByTagName('aggregateFunction') aggnodata = requestObject.getElementsByTagName('aggregateNodata') if len(aggint)==1 and len(aggfun)==1: # aggregate_interval # Check on the eventTime parameter: it must be only one interval: 2010-01-01T00:00:00+00/2011-01-01T00:00:01+00 exeMsg = "Using aggregate functions, the event time must exist with an interval composed by a begin and an end date (ISO8601)" if self.eventTime == None or len(self.eventTime)!=1 or len(self.eventTime[0])!=2: raise sosException.SOSException("NoApplicableCode", None, exeMsg) val = aggint[0].firstChild if val.nodeType == val.TEXT_NODE: self.aggregate_interval = str(val.data) try: iso.parse_duration(self.aggregate_interval) except Exception as ex: raise sosException.SOSException("InvalidParameterValue", "aggregateInterval", "Parameter \"aggregate_interval\" sent with invalid format (check ISO8601 duration spec): %s" % ex) else: err_txt = "cannot get ISO8601 duration value in \"aggregateInterval\"" raise sosException.SOSException("InvalidParameterValue", "aggregateInterval", err_txt) # aggregate_function val = aggfun[0].firstChild if val.nodeType == val.TEXT_NODE: self.aggregate_function = str(val.data) if not (self.aggregate_function.upper() in ["AVG", "COUNT", "MAX", "MIN", "SUM"]): raise sosException.SOSException("InvalidParameterValue", "aggregateFunction", "Available aggregation functions: avg, count, max, min, sum.") # aggregate_no_data default value if len(aggnodata)==1: val = aggnodata[0].firstChild self.aggregate_nodata = str(val.data) else: self.aggregate_nodata = sosConfig.aggregate_nodata #================================ # MISSING AGGREGATE QUALITY INDEX #================================ elif len(aggint)==0 and len(aggfun)==0: pass else: err_txt = "\"aggregateInterval\" and \"aggregate_function\" are both required with multiplicity 1" raise sosException.SOSException("NoApplicableCode", None, err_txt) # QUALITY INDEX self.qualityIndex=False qidx = requestObject.getElementsByTagName('qualityIndex') if len(qidx)>0: if len(qidx)<2: val = qidx[0].firstChild if val.nodeType == val.TEXT_NODE: self.qualityIndex = str(val.data) if self.qualityIndex.upper() == "TRUE": self.qualityIndex=True elif self.qualityIndex.upper() == "FALSE": pass else: raise sosException.SOSException("InvalidParameterValue", "qualityIndex", "qualityIndex can only be \'True\' or \'False\'") elif len(qidx)==0: pass else: err_txt = "\"qualityIndex\" is allowed with multiplicity 1 only" raise sosException.SOSException("NoApplicableCode", None, err_txt) self.qualityFilter=False
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) # @TODO Declare attribute first! # self.offering = None # etc.. #************************** if method == "GET": #---------- THE OFFERING if requestObject.has_key("offering"): self.offering = get_name_from_urn(requestObject["offering"], "offering", sosConfig) else: raise sosException.SOSException( 1, "Parameter \"offering\" is mandatory with multiplicity 1") #---------- THE OBSERVED PROPERTY if requestObject.has_key("observedProperty"): self.observedProperty = [] oprs = requestObject["observedProperty"].split(",") for opr in oprs: # get_name_from_urn limit the ability to ask for an observedProperty with LIKE: # eg: ask "water" to get all the water related data, "water:discharge", "water:temperature" ... #oprName = get_name_from_urn(opr,"property") oprName = opr self.observedProperty.append(oprName) # one-many ID else: raise sosException.SOSException( 1, "Parameter \"observedProperty\" is mandatory with multiplicity N" ) #---------- RESPONSE FORMAT if requestObject.has_key("responseFormat"): if not requestObject["responseFormat"] in sosConfig.parameters[ "GO_responseFormat"]: raise sosException.SOSException( 2, "Parameter \"responseFormat\" sent with invalid value : use one of %s" % "; ".join(sosConfig.parameters["GO_responseFormat"])) else: self.responseFormat = requestObject["responseFormat"] else: raise sosException.SOSException( 1, "Parameter \"responseFormat\" is mandatory with multiplicity 1" ) #one #OPTIONAL request parameters #---------- SRS FILTER if requestObject.has_key("srsName"): self.srsName = get_name_from_urn(requestObject["srsName"], "refsystem", sosConfig) if not self.srsName in sosConfig.parameters["GO_srs"]: raise sosException.SOSException( 2, "srsName \"%s\" not supported, use one of: %s" % (self.srsName, ",".join( sosConfig.parameters["GO_srs"]))) else: self.srsName = sosConfig.parameters["GO_srs"][0] #---------- TIME FILTER if requestObject.has_key('eventTime'): self.eventTime = [] for i in requestObject["eventTime"].replace(" ", "+").split(","): if len(i.split("/")) < 3: self.eventTime.append(i.split("/")) else: raise sosException.SOSException( 2, "Parameter \"eventTime\" bad formatted") tp = [] for t in self.eventTime: if len(t) == 2: tp.append(iso.parse_datetime(t[0])) tp.append(iso.parse_datetime(t[1])) if len(t) == 1: tp.append(iso.parse_datetime(t[0])) # Checking if some event limitation is reached #if sosConfig["maxGoPeriod"]: if int(sosConfig.maxGoPeriod) > 0: from datetime import timedelta d = timedelta(hours=int(sosConfig.maxGoPeriod)) userPeriod = max(tp) - min(tp) if d < userPeriod: raise sosException.SOSException( 2, "You are requesting data for a period of [%s hours], but you are not permitted to ask for a period longer than: %s hours" % (userPeriod, d)) else: self.eventTime = None #---------- PROCEDURES FILTER if requestObject.has_key("procedure"): self.procedure = [] prcs = requestObject["procedure"].split(",") for prc in prcs: prcName = get_name_from_urn(prc, "procedure", sosConfig) self.procedure.append(prcName) else: self.procedure = None #---------- FEATURES OF INTEREST FILTER self.featureOfInterest = None self.featureOfInterestSpatial = None if requestObject.has_key("featureOfInterest"): foi = requestObject["featureOfInterest"] if foi.find("<ogc:") >= 0 and foi.find("<gml:") >= 0: #raise sosException.SOSException(3,"FOI SPATIAL: %s" %(foi)) self.featureOfInterestSpatial = sosUtils.ogcSpatCons2PostgisSql( foi, 'geom_foi', sosConfig.istsosepsg) else: self.featureOfInterest = get_name_from_urn( foi, "feature", sosConfig) #fois = requestObject["featureOfInterest"].split(",") #for foi in fois: # foiName = get_name_from_urn(foi,"feature") # self.featureOfInterest.append(foiName) #---------- FILTERS FOR QUERY NOT SUPPORTED YET if requestObject.has_key("result"): #raise sosException.SOSException(3,"Parameter \"result\" not yet supported") self.result = sosUtils.ogcCompCons2PostgisSql( requestObject["result"]) else: self.result = None #zero-one optional #---------- RESULT MODEL if requestObject.has_key("resultModel"): if requestObject["resultModel"] in sosConfig.parameters[ "GO_resultModel"]: self.resultModel = requestObject["resultModel"] else: raise sosException.SOSException( 2, "Parameter \"resultModel\" sent with invalid value: supported values are: %s" % ",".join(sosConfig.parameters["GO_resultModel"])) else: self.resultModel = sosConfig.parameters["GO_resultModel"][0] #---------- RESPONSE MODE if requestObject.has_key("responseMode"): if requestObject["responseMode"] in sosConfig.parameters[ "GO_responseMode"]: self.responseMode = requestObject["responseMode"] else: raise sosException.SOSException( 2, "Parameter \"responseMode\" sent with invalid value, supported values are: %s" % (",".join(sosConfig.parameters["GO_responseMode"]))) else: self.responseMode = sosConfig.parameters["GO_responseMode"][0] ########################### # NON STANDARD PARAMETERS # ########################### #---------- AGGREGATE INTERVAL # In ISO 8601 duration format if requestObject.has_key("aggregateInterval"): # Check on the eventTime parameter: it must be only one interval: 2010-01-01T00:00:00+00/2011-01-01T00:00:01+00 exeMsg = "Using aggregate functions, the event time must exist with an interval composed by a begin and an end date (ISO8601)" if self.eventTime == None or len(self.eventTime) != 1 or len( self.eventTime[0]) != 2: raise sosException.SOSException(2, exeMsg) self.aggregate_interval = requestObject["aggregateInterval"] try: iso.parse_duration(self.aggregate_interval) except Exception as ex: raise sosException.SOSException( 2, "Parameter \"aggregate_interval\" sent with invalid format (check ISO8601 duration spec): %s" % ex) else: self.aggregate_interval = None #---------- AGGREGATE FUNCTION # sum,avg,max,min if requestObject.has_key("aggregateFunction"): if self.aggregate_interval == None: raise sosException.SOSException( 2, "Using aggregate functions parameters \"aggregateInterval\" and \"aggregateFunction\" are both mandatory" ) self.aggregate_function = requestObject["aggregateFunction"] if not (self.aggregate_function.upper() in ["AVG", "COUNT", "MAX", "MIN", "SUM"]): raise sosException.SOSException( 2, "Available aggregation functions: avg, count, max, min, sum." ) else: self.aggregate_function = None #---------- AGGREGATE NODATA if requestObject.has_key("aggregateNodata"): if self.aggregate_interval == None or self.aggregate_function == None: raise sosException.SOSException( 2, "Using aggregateNodata parameter requires both \"aggregateInterval\" and \"aggregateFunction\"" ) self.aggregate_nodata = requestObject["aggregateNodata"] else: self.aggregate_nodata = sosConfig.aggregate_nodata #---------- AGGREGATE NODATA QUALITY INDEX if requestObject.has_key("aggregateNodataQi"): if self.aggregate_interval == None or self.aggregate_function == None: raise sosException.SOSException( 2, "Using aggregateNodataQi parameter requires both \"aggregateInterval\" and \"aggregateFunction\"" ) self.aggregate_nodata_qi = requestObject["aggregateNodataQi"] else: self.aggregate_nodata_qi = sosConfig.aggregate_nodata_qi #------------ QUALITY INDEX self.qualityIndex = False if requestObject.has_key("qualityIndex"): if requestObject["qualityIndex"].upper() == "TRUE": self.qualityIndex = True elif requestObject["qualityIndex"].upper() == "FALSE": self.qualityIndex = False else: raise sosException.SOSException( 2, "qualityIndex can only be True or False!") # self.qualityIndex = sosUtils.CQLvalueFilter2PostgisSql("id_qi_fk",requestObject["qualityIndex"]) #********************** if method == "POST": from xml.dom import minidom #---------- THE OFFERING offs = requestObject.getElementsByTagName('offering') if len(offs) == 1: val = offs[0].firstChild if val.nodeType == val.TEXT_NODE: self.offering = get_name_from_urn(str(val.data), "offering", sosConfig) else: err_txt = "XML parsing error (get value: offering)" raise sosException.SOSException(1, err_txt) else: err_txt = "Parameter \"offering\" is mandatory with multiplicity 1" raise sosException.SOSException(1, err_txt) #---------- THE OBSERVED PROPERTY obsProps = requestObject.getElementsByTagName('observedProperty') self.observedProperty = [] if len(obsProps) > 0: for obsProp in obsProps: val = obsProp.firstChild if val.nodeType == val.TEXT_NODE: # get_name_from_urn limit the ability to ask for an observedProperty with LIKE: # eg: ask "water" to get all the water related data, "water:discharge", "water:temperature" ... #self.observedProperty.append(get_name_from_urn(str(val.data),"property")) self.observedProperty.append(str(val.data)) else: err_txt = "XML parsing error (get value: observedProperty)" raise sosException.SOSException(1, err_txt) else: err_txt = "Parameter \"observedProperty\" is mandatory with multiplicity N" raise sosException.SOSException(1, err_txt) #---------- RESPONSE FORMAT respF = requestObject.getElementsByTagName('responseFormat') if len(respF) == 1: val = respF[0].firstChild if val.nodeType == val.TEXT_NODE: self.responseFormat = str(val.data) if self.responseFormat not in sosConfig.parameters[ "GO_responseFormat"]: raise sosException.SOSException( 2, "Parameter \"responseFormat\" sent with invalid value: use one of %s" % "; ".join( sosConfig.parameters["GO_responseFormat"])) else: err_txt = "XML parsing error (get value: responseFormat)" raise sosException.SOSException(1, err_txt) else: err_txt = "Parameter \"responseFormat\" is mandatory with multiplicity 1" raise sosException.SOSException(1, err_txt) #OPTIONAL request parameters #---------- SRS OF RETURNED GML FEATURES srss = requestObject.getElementsByTagName('srsName') if len(srss) > 0: if len(srss) < 2: val = srss[0].firstChild if val.nodeType == val.TEXT_NODE: self.srsName = get_name_from_urn( str(val.data), "refsystem", sosConfig) else: err_txt = "XML parsing error (get value: srsName)" raise sosException.SOSException(1, err_txt) else: err_txt = "Allowed only ONE parameter \"srsName\"" raise sosException.SOSException(1, err_txt) else: self.srsName = sosConfig.parameters["GO_srs"][0] #---------- TIME FILTER evtms = requestObject.getElementsByTagName('eventTime') self.eventTime = [] if len(evtms) > 0: for evtm in evtms: tps = evtm.getElementsByTagName('gml:TimePeriod') for tp in tps: begin = tp.getElementsByTagName('gml:beginPosition') end = tp.getElementsByTagName('gml:endPosition') if len(begin) == 1 and len(end) == 1: Bval = begin[0].firstChild Eval = end[0].firstChild #raise sosException.SOSException(1,end[0].toprettyxml()) if Bval.nodeType == Bval.TEXT_NODE and Eval.nodeType == Eval.TEXT_NODE: self.eventTime.append([ str(Bval.data).replace(" ", "+"), str(Eval.data).replace(" ", "+") ]) #raise sosException.SOSException(1,str(self.eventTime)) else: err_txt = "XML parsing error (get value: TimePeriod)" raise sosException.SOSException(1, err_txt) tis = evtm.getElementsByTagName('gml:TimeInstant') for ti in tis: instant = ti.getElementsByTagName('gml:timePosition') if len(instant) > 0 and len(instant) < 2: Ival = instant[0].firstChild if Ival.nodeType == Ival.TEXT_NODE: self.eventTime.append( [str(Ival.data).replace(" ", "+")]) else: err_txt = "XML parsing error (get value: Timeinstant)" raise sosException.SOSException(1, err_txt) else: self.eventTime = None #---------- PROCEDURES FILTER procs = requestObject.getElementsByTagName('procedure') if len(procs) > 0: self.procedure = [] for proc in procs: if "xlink:href" in proc.attributes.keys(): self.procedure.append( str(proc.getAttribute("xlink:href"))) elif proc.hasChildNodes(): val = proc.firstChild if val.nodeType == val.TEXT_NODE: self.procedure.append( get_name_from_urn(str(val.data), "procedure", sosConfig)) else: err_txt = "XML parsing error (get value: procedure)" raise sosException.SOSException(1, err_txt) else: self.procedure = None #---------- FEATURES OF INTEREST FILTER fets = requestObject.getElementsByTagName('featureOfInterest') self.featureOfInterest = None self.featureOfInterestSpatial = None if len(fets) > 0: if len(fets) < 2: elements = [ e for e in fets[0].childNodes if e.nodeType == e.ELEMENT_NODE ] if len(elements) == 1: self.featureOfInterestSpatial = sosUtils.ogcSpatCons2PostgisSql( elements[0], 'geom_foi', sosConfig.istsosepsg) else: if "xlink:href" in fets[0].attributes.keys(): self.featureOfInterest = str( fets[0].getAttribute("xlink:href")) elif fets[0].hasChildNodes(): val = fets[0].firstChild if val.nodeType == val.TEXT_NODE: self.featureOfInterest = get_name_from_urn( str(val.data), "feature", sosConfig) else: err_txt = "XML parsing error (get value: featureOfInterest)" raise sosException.SOSException(1, err_txt) else: err_txt = "Allowed only ONE parameter \"featureOfInterest\"" raise sosException.SOSException(1, err_txt) #---------- FILTERS FOR QUERY NOT SUPPORTED YET ress = requestObject.getElementsByTagName('result') if len(ress) > 0: raise sosException.SOSException( 3, "Parameter \"result\" not yet supported") else: self.result = None #zero-one optional #---------- RESULT MODEL mods = requestObject.getElementsByTagName('resultModel') if len(mods) > 0: if len(mods) < 2: val = mods[0].firstChild if val.nodeType == val.TEXT_NODE: self.resultModel = str(val.data) if self.resultModel not in sosConfig.parameters[ "GO_resultModel"]: raise sosException.SOSException( 2, "Parameter \"resultModel\" sent with invalid value" ) else: err_txt = "XML parsing error (get value: resultModel)" raise sosException.SOSException(1, err_txt) else: err_txt = "Allowed only ONE parameter \"resultModel\"" raise sosException.SOSException(1, err_txt) else: self.resultModel = None #---------- RESPONSE MODE rsmods = requestObject.getElementsByTagName('responseMode') if len(rsmods) > 0: if len(rsmods) < 2: val = rsmods[0].firstChild if val.nodeType == val.TEXT_NODE: self.responseMode = str(val.data) if self.responseMode not in sosConfig.parameters[ "GO_responseMode"]: raise sosException.SOSException( 2, "Parameter \"responseMode\" sent with invalid value" ) else: err_txt = "XML parsing error (get value: responseMode)" raise sosException.SOSException(1, err_txt) else: err_txt = "Allowed only ONE parameter \"responseMode\"" raise sosException.SOSException(1, err_txt) else: self.responseMode = sosConfig.parameters["GO_responseMode"][0] #-------------- AGGREGATE INTERVAL & FUNCTION self.aggregate_interval = None self.aggregate_function = None aggint = requestObject.getElementsByTagName('aggregateInterval') aggfun = requestObject.getElementsByTagName('aggregateFunction') aggnodata = requestObject.getElementsByTagName('aggregateNodata') if len(aggint) == 1 and len(aggfun) == 1: #----------------------- # -- aggregate_interval #----------------------- # Check on the eventTime parameter: it must be only one interval: 2010-01-01T00:00:00+00/2011-01-01T00:00:01+00 exeMsg = "Using aggregate functions, the event time must exist with an interval composed by a begin and an end date (ISO8601)" if self.eventTime == None or len(self.eventTime) != 1 or len( self.eventTime[0]) != 2: raise sosException.SOSException(2, exeMsg) val = aggint[0].firstChild if val.nodeType == val.TEXT_NODE: self.aggregate_interval = str(val.data) try: iso.parse_duration(self.aggregate_interval) except Exception as ex: raise sosException.SOSException( 2, "Parameter \"aggregate_interval\" sent with invalid format (check ISO8601 duration spec): %s" % ex) else: err_txt = "cannot get ISO8601 duration value in \"aggregateInterval\"" raise sosException.SOSException(1, err_txt) #----------------------- # -- aggregate_function #----------------------- val = aggfun[0].firstChild if val.nodeType == val.TEXT_NODE: self.aggregate_function = str(val.data) if not (self.aggregate_function.upper() in ["AVG", "COUNT", "MAX", "MIN", "SUM"]): raise sosException.SOSException( 2, "Available aggregation functions: avg, count, max, min, sum." ) #----------------------------------- # -- aggregate_no_data default value #----------------------------------- if len(aggnodata) == 1: val = aggnodata[0].firstChild self.aggregate_nodata = str(val.data) else: self.aggregate_nodata = sosConfig.aggregate_nodata #================================ #MISSING AGGREGATE QUALITY INDEX #================================ elif len(aggint) == 0 and len(aggfun) == 0: pass else: err_txt = "\"aggregateInterval\" and \"aggregate_function\" are both required with multiplicity 1" raise sosException.SOSException(1, err_txt) #------------ QUALITY INDEX self.qualityIndex = False qidx = requestObject.getElementsByTagName('qualityIndex') if len(qidx) > 0: if len(qidx) < 2: val = qidx[0].firstChild if val.nodeType == val.TEXT_NODE: self.qualityIndex = str(val.data) if self.qualityIndex.upper() == "TRUE": self.qualityIndex = True elif self.qualityIndex.upper() == "FALSE": pass else: raise sosException.SOSException( 2, "qualityIndex can only be \'True\' or \'False\'" ) elif len(qidx) == 0: pass else: err_txt = "\"qualityIndex\" is allowed with multiplicity 1 only" raise sosException.SOSException(1, err_txt)
def executeSos(environ, start_response): try: from istsoslib import sosDatabase from istsoslib import sosException try: sosConfig = waconf2sos.istsosConfig(environ) except sosException.SOSException as ise: raise ise except Exception as ex: raise sosException.SOSException("NoApplicableCode", "", str(ex)) if not sosConfig.istsos_librarypath == "" or ( sosConfig.istsos_librarypath is None): sys.path.insert(0, sosConfig.istsos_librarypath) pgdb = sosDatabase.PgDB(sosConfig.connection["user"], sosConfig.connection["password"], sosConfig.connection["dbname"], sosConfig.connection["host"], sosConfig.connection["port"]) req_filter = FF.sosFactoryFilter(environ, sosConfig) # Checking authorizations if not sosConfig.user.allowedService(sosConfig.schema): raise sosException.SOSException( "NoApplicableCode", "", "You are not authorized to access the " "'%s' instance" % sosConfig.schema) elif req_filter.request in ['insertobservation', 'registersensor']: # If hybrid mode enable check authorizations if config.hybrid and (not 'HTTP_AUTHORIZATION' in environ): raise sosException.SOSException( "NoApplicableCode", "", "In hybrid mode, you are not authorized to " "execute %s requests on this server" % req_filter.request) # Only Admin, Network Managers and Data Manager con execute # insertobservation or registersensor elif not sosConfig.user.isAdmin() and ( not sosConfig.user.isNetworkManager()) and ( not sosConfig.user.isDataManager()): raise sosException.SOSException( "NoApplicableCode", "", "You are not authorized to execute %s " "requests on this server" % req_filter.request) response = FR.sosFactoryResponse(req_filter, pgdb) render = FRe.sosFactoryRender(response, sosConfig) try: content_type = req_filter.responseFormat except: content_type = 'application/xml; charset=utf-8' status = '200 OK' response_headers = [('Content-Type', content_type), ('Content-Length', str(len(render.encode('utf-8'))))] if str(environ['REQUEST_METHOD']).upper() == 'GET': rect = parse_qs(environ['QUERY_STRING']) requestObject = {} for key in rect.keys(): requestObject[key.lower()] = rect[key][0] if "attachment" in requestObject: response_headers.append( ("Content-Disposition", "attachment; filename=%s" % requestObject["attachment"])) start_response(status, response_headers) return [render.encode('utf-8')] except sosException.SOSException, e: #print >> sys.stderr, traceback.print_exc() response_body = e.ToXML() status = '200 OK' response_headers = [('Content-Type', 'application/xml; charset=utf-8'), ('Content-Length', str(len(response_body.encode('utf-8'))))] start_response(status, response_headers) return [response_body.encode('utf-8')]
except sosException.SOSException, e: #print >> sys.stderr, traceback.print_exc() response_body = e.ToXML() status = '200 OK' response_headers = [('Content-Type', 'application/xml; charset=utf-8'), ('Content-Length', str(len(response_body.encode('utf-8'))))] start_response(status, response_headers) return [response_body.encode('utf-8')] except Exception, e: print >> sys.stderr, traceback.print_exc() othertext = traceback.format_exception(*sys.exc_info()) if sosConfig.debug: response_body = "%s" % (sosException.SOSException( "NoApplicableCode", None, e.__class__.__name__, [e, othertext]), ) else: response_body = "%s" % (sosException.SOSException( "NoApplicableCode", None, "istSOS internal error", ["Please activate debug level for more details"])) status = '200 OK' response_headers = [('Content-Type', 'application/xml; charset=utf-8'), ('Content-Length', str(len(response_body.encode('utf-8'))))] start_response(status, response_headers) return [response_body.encode('utf-8')] return []
def __init__(self, filter, pgdb): # get procedure information sql = """ SELECT id_prc, name_prc, name_oty, name_foi, stime_prc, etime_prc FROM %s.procedures, %s.obs_type, %s.foi""" % (filter.sosConfig.schema, filter.sosConfig.schema, filter.sosConfig.schema) sql += """ WHERE id_oty=id_oty_fk AND id_foi=id_foi_fk AND assignedid_prc=%s""" params = (filter.assignedSensorId, ) try: prc = pgdb.select(sql, params)[0] except: raise sosException.SOSException( "InvalidParameterValue", "assignedSensorId", "assignedSensorId '%s' is not valid!" % (filter.assignedSensorId)) # check requested procedure name exists if not prc["name_prc"] == filter.procedure: raise sosException.SOSException( "NoApplicableCode", None, "procedure '%s' not associated with provided " "assignedSensorId!" % (filter.procedure)) # check requested foi name exists if not filter.foiName == prc["name_foi"]: raise sosException.SOSException( "NoApplicableCode", None, "featureOfInterest '%s' not associated with " "provided assignedSensorId" % (filter.foiName)) # check provided samplingTime and upadate # begin/end time procedure if necessary # (samplingTime=period or istant of provided # observations defined by samplingTime filter) #============================================= if filter.samplingTime: stime = filter.samplingTime.split("/") # if len(stime) == 2: # is a TimePeriod start = iso.parse_datetime(stime[0]) end = iso.parse_datetime(stime[1]) elif len(stime) == 1: # is a TimeInstant start = end = iso.parse_datetime(stime[0]) else: raise Exception("filter samplingTime error! given '%s'" % (filter.samplingTime)) if start > end: raise Exception( "endPosition (%s) must be after beginPosition (%s)" % (end, start)) # check samplingTime # > verify procedure begin/end exist if not (prc["stime_prc"].__class__.__name__ == "NoneType" and (prc["etime_prc"].__class__.__name__ == "NoneType")): # check eventTime interval and update begin/end position when # force flas is active if filter.forceInsert: # update begin time of procedure if start < prc["stime_prc"]: sql = """ UPDATE %s.procedures""" % (filter.sosConfig.schema) sql += """ SET stime_prc=%s::TIMESTAMPTZ WHERE id_prc=%s""" params = (stime[0], prc["id_prc"]) try: a = pgdb.executeInTransaction(sql, params) com = True except: raise Exception("SQL: %s" % (pgdb.mogrify(sql, params))) # update end time of procedure if end > prc["etime_prc"]: sql = """ UPDATE %s.procedures""" % (filter.sosConfig.schema) sql += """ SET etime_prc=%s::TIMESTAMPTZ WHERE id_prc=%s""" params = (stime[1], prc["id_prc"]) try: b = pgdb.executeInTransaction(sql, params) com = True except Exception as err: raise Exception( "SQL: %s - %s" % (pgdb.mogrify(sql, params), err.pgerror)) # check eventTime interval and update begin/end position when # force flag is off else: if filter.sosConfig.sequential: sql = """ SELECT max(time_eti) as max_time_eti FROM %s.event_time""" % (filter.sosConfig.schema) sql += """ WHERE id_prc_fk = %s GROUP BY id_prc_fk""" params = (prc["id_prc"], ) try: lastMsr = pgdb.select(sql, params)[0]["max_time_eti"] except: lastMsr = None if lastMsr is not None: # verify begin observation is minor/equal then end # time procedure and later then last observation if not (end >= prc["etime_prc"] and (start <= prc["etime_prc"]) and (start >= lastMsr)): raise Exception( "begin observation (%s) must be between last " "observation (%s) and end procedure (%s); end" " observation (%s) must be after end " "procedure (%s)" % (start, lastMsr, prc["etime_prc"], end, prc["etime_prc"])) else: # verify begin observation is minor/equal then end # time procedure and later then first observation if not (end >= prc["etime_prc"] and (start <= prc["etime_prc"]) and (start >= prc["stime_prc"])): raise Exception( "begin observation (%s) must be between start " "procedure (%s) and end procedure (%s); end " "observation (%s) must be after end procedure " "(%s)" % (start, prc["stime_prc"], prc["etime_prc"], end, prc["etime_prc"])) #-- update end time of procedure sql = """ UPDATE %s.procedures""" % (filter.sosConfig.schema) sql += """ SET etime_prc=%s::TIMESTAMPTZ WHERE id_prc=%s""" params = (str(stime[1]), int(prc["id_prc"])) try: b = pgdb.executeInTransaction(sql, params) com = True except Exception as err: raise Exception( "SQL: %s - %s" % (pgdb.mogrify(sql, params), err.pgerror)) else: sql = """ UPDATE %s.procedures""" % (filter.sosConfig.schema) sql += """ SET stime_prc=%s::TIMESTAMPTZ, etime_prc=%s::TIMESTAMPTZ WHERE id_prc=%s""" params = (str(stime[0]), str(stime[1]), int(prc["id_prc"])) try: b = pgdb.executeInTransaction(sql, params) com = True except: raise Exception("SQL: %s" % (pgdb.mogrify(sql, params))) # check data definition and uom (compare registered # observed properties with provided observations) #================================================== # get values for provided data: UOM, NAME, URN, ID #-------------------------------------------------- sql = """ SELECT id_pro, id_opr, def_opr, name_uom, constr_opr, constr_pro FROM %s.observed_properties, %s.proc_obs, %s.uoms""" % (filter.sosConfig.schema, filter.sosConfig.schema, filter.sosConfig.schema) sql += """ WHERE id_uom_fk = id_uom AND id_opr_fk = id_opr AND id_prc_fk = %s""" params = (prc["id_prc"], ) try: opr = pgdb.select(sql, params) except Exception as err: raise Exception("SQL2: %s -%s" % (pgdb.mogrify(sql, params), err.pgerror)) # get list of available ObservedProperty, unit of measure, property # id for this procedure oprNames = [] oprUoms = [] oprIds = [] # to be removed ???? proIds = [] obsPropConstr = [] procConstr = [] ''' Building a matrix: oprNames = ["urn:ogc:def:parameter:x-istsos:1.0:" + "meteo:air:temperature" , ...] oprUoms = ["mm" , ...] oprIds = [id_opr , ...] proIds = [id_pro , ...] obsPropConstr = [{ "interval": ["-40", "50"], "role": "urn:ogc:def:classifiers:x-istsos:1.0:" + "qualityIndex:check:acceptable"} , ...] procConstr = [{ "max": "100", "role": "urn:ogc:def:classifiers:x-istsos:1.0:" + "qualityIndex:check:reasonable"} , ...] ''' for row in opr: oprNames.append(row["def_opr"]) oprUoms.append(row["name_uom"]) oprIds.append(row["id_opr"]) proIds.append(row["id_pro"]) if not row["constr_opr"] in [None, '']: obsPropConstr.append(json.loads(row["constr_opr"])) else: obsPropConstr.append(None) if not row["constr_pro"] in [None, '']: procConstr.append(json.loads(row["constr_pro"])) else: procConstr.append(None) # get ordered list of observed properties in data---- dataKeys = [key for key in filter.data.keys()] # get ordered list of unit of measures provided with data------- dataUoms = [] for key in filter.data.keys(): if "uom" in filter.data[key].keys(): dataUoms.append(filter.data[key]["uom"]) else: dataUoms.append('None') # verify that all the properties observed by this procedure # are provided with the correct data definition and uom for i, opr in enumerate(oprNames): try: k = dataKeys.index(opr) except: raise sosException.SOSException( "NoApplicableCode", None, "parameter '%s' not observed by RegisteredSensor " "%s - %s" % (opr, oprNames, dataKeys)) if not dataUoms[k] == oprUoms[i]: raise sosException.SOSException( "NoApplicableCode", None, "parameter '%s' not observed with provided unit of " "measure" % (opr)) # verify if time and coordinates are passed as data parameters # and create the parameters list and parameters ID xobs = yobs = zobs = tpar = None pars = [] # Observed parameters parsId = [] parsConsObs = [] parsConsPro = [] # urn of different parameters for i, dn in enumerate(dataKeys): if dn.split(":")[-1] in filter.sosConfig.parGeom["x"]: xobs = dataKeys[i] elif dn.split(":")[-1] in filter.sosConfig.parGeom["y"]: yobs = dataKeys[i] elif dn.split(":")[-1] in filter.sosConfig.parGeom["z"]: zobs = dataKeys[i] elif dn.find("iso8601") >= 0: tpar = dataKeys[i] else: if dn.split(":")[-1] != "qualityIndex": pars.append(dn) try: parsId.append(proIds[oprNames.index(dn)]) parsConsObs.append(obsPropConstr[oprNames.index(dn)]) parsConsPro.append(procConstr[oprNames.index(dn)]) except: raise Exception( "parameter %s not observed by this sensor " "%s - %s" % (dn, pars, oprNames)) # set default quality index if not provided for par in pars: try: dataKeys.index(par + ":qualityIndex") except: filter.data[par + ":qualityIndex"] = { "vals": [filter.sosConfig.default_qi] * len(filter.data[par]["vals"]) } # verify that mobile sensors provide coordinates as X,Y,Z if (xobs is False and yobs is False and zobs is False) and (prc["name_oty"] == "insitu-mobile-point"): raise Exception("Mobile sensors require x, y, z parameters") # verify that time parameter is provided if not tpar: raise Exception( "parameter 'time:iso8601' is required for InsertObservation") # verify that eventime are in provided samplingTime if len(filter.data[tpar]["vals"]) > 0: maxDate = iso.parse_datetime(max(filter.data[tpar]["vals"])) minDate = iso.parse_datetime(min(filter.data[tpar]["vals"])) if not maxDate <= end and minDate >= start: raise Exception( "provided data (min: %s, max:%s) are not included in " "provided <samplingTime> period (%s / %s) for " "procedure %s" % (minDate.isoformat(), maxDate.isoformat(), start.isoformat(), end.isoformat(), prc["name_prc"])) # insert observation # delete existing observations if force flag is active if filter.forceInsert: sql = """ DELETE FROM %s.event_time""" % (filter.sosConfig.schema) sql += """ WHERE id_prc_fk = %s AND time_eti >= %s::TIMESTAMPTZ AND time_eti <= %s::TIMESTAMPTZ""" params = (prc["id_prc"], stime[0], stime[1]) try: b = pgdb.executeInTransaction(sql, params) com = True except: raise Exception("SQL: %s" % (pgdb.mogrify(sql, params))) # CASE I: observations list is void if len(filter.data[tpar]["vals"]) == 0: self.assignedId = "" ids_eti = [] # CASE I: observations list contains data elif len(filter.data[tpar]["vals"]) > 0: # insert event times ids_eti = [] params = [] sql = """ INSERT INTO %s.event_time (id_prc_fk,time_eti)""" % ( filter.sosConfig.schema) sql += """ VALUES ( %s, %s::TIMESTAMPTZ) RETURNING id_eti""" for val in filter.data[tpar]["vals"]: try: ids_eti.append( pgdb.executeInTransaction( sql, (prc["id_prc"], val))[0]['id_eti']) com = True except Exception as e: raise Exception("Error inserting event times for %s: %s" % (prc["name_prc"], e)) for i, par in enumerate(pars): params = [] ids_msr = [] sql = """ INSERT INTO %s.measures ( id_pro_fk, id_eti_fk, id_qi_fk, val_msr)""" % (filter.sosConfig.schema) sql += """ VALUES (%s, %s, %s, %s) RETURNING id_msr""" pco = parsConsObs[i] pcp = parsConsPro[i] for ii, id_et in enumerate(ids_eti): if not filter.data[par]["vals"][ii] in [ 'NULL', u'NULL', None, 'None', u'None', filter.sosConfig.aggregate_nodata ]: # TODO: add an else statement to add the # aggregate_nodata value OR delete the event time if # not filter.data[par]["vals"][ii] in ['NULL',u'NULL', # None]: pqi = int( float(filter.data[par + ":qualityIndex"]["vals"][ii])) # Constraint quality is done only if the quality index # is equal to the default qi (RAW DATA) if int(filter.sosConfig.default_qi) == pqi: # quality check level I (gross error) val = float(filter.data[par]["vals"][ii]) if filter.sosConfig.correct_qi is not None and ( pco is not None): if 'max' in pco: if val <= (float(pco['max'])): pqi = int(filter.sosConfig.correct_qi) elif 'min' in pco: if val >= (float(pco['min'])): pqi = int(filter.sosConfig.correct_qi) elif 'interval' in pco: if (float(pco['interval'][0]) <= val <= float(pco['interval'][1])): pqi = int(filter.sosConfig.correct_qi) elif 'valueList' in pco: if val in [ float(p) for p in (pco['valueList']) ]: pqi = int(filter.sosConfig.correct_qi) # quality check level II (statistical range) if filter.sosConfig.stat_qi is not None and ( pcp is not None): if 'max' in pcp: if val <= float(pcp['max']): pqi = int(filter.sosConfig.stat_qi) elif 'min' in pcp: if val >= float(pcp['min']): pqi = int(filter.sosConfig.stat_qi) elif 'interval' in pcp: if (float(pcp['interval'][0]) <= val <= float(pcp['interval'][1])): pqi = int(filter.sosConfig.stat_qi) elif 'valueList' in pcp: if val in [ float(p) for p in pcp['valueList'] ]: pqi = int(filter.sosConfig.stat_qi) params = (int(parsId[i]), int(id_et), pqi, float(filter.data[par]["vals"][ii])) try: nid_msr = pgdb.executeInTransaction(sql, params) ids_msr.append(str(nid_msr[0]['id_msr'])) except Exception as e: com = False raise e #--insert position values if required if prc["name_oty"] == "insitu-mobile-point": xparspl = xobs.split(":") epsg = xparspl[xparspl.index("EPSG") + 1] params = [] sql = """ INSERT INTO %s.positions ( id_qi_fk, id_eti_fk, geom_pos)""" % (filter.sosConfig.schema) sql += """ VALUES ( %s, %s, ST_Transform( ST_SetSRID(ST_MakePoint(%s, %s, %s), %s), %s))""" for i, id_et in enumerate(ids_eti): params = (filter.sosConfig.default_qi, id_et, filter.data[xobs]["vals"][i], filter.data[yobs]["vals"][i], filter.data[zobs]["vals"][i], epsg, filter.sosConfig.istsosepsg) try: ids_pos = pgdb.executeInTransaction(sql, params) com = True except Exception as a: com = False raise Exception("%s\nSQL: %s" % (a, pgdb.mogrify(sql, params))) # register assigned IDs of measures self.assignedId = "@".join([str(p) for p in ids_eti]) # commit executed operations #Register the transactional operation in Log table if filter.sosConfig.transactional_log in ['True', 'true', 1]: sqlLog = """ INSERT INTO %s.tran_log ( operation_trl, procedure_trl, begin_trl, end_trl, count, stime_prc, etime_prc)""" % (filter.sosConfig.schema) sqlLog += """ VALUES ( 'InsertObservation', %s, %s::TIMESTAMPTZ, %s::TIMESTAMPTZ, %s, %s::TIMESTAMPTZ, %s::TIMESTAMPTZ)""" params = (str(filter.procedure), start, end, len(ids_eti), prc["stime_prc"], prc["etime_prc"]) try: pgdb.executeInTransaction(sqlLog, params) com = True except: raise Exception("SQL: %s" % (pgdb.mogrify(sqlLog, params))) if com is True: pgdb.commitTransaction() # broadcasting to mqtt broker if configured if filter.sosConfig.mqtt["broker_url"] != '' and ( filter.sosConfig.mqtt["broker_port"] != ''): from istmqttlib import PahoPublisher PahoPublisher({ "broker_url": filter.sosConfig.mqtt["broker_url"], "broker_port": filter.sosConfig.mqtt["broker_port"], "broker_topic": "%s%s" % (filter.sosConfig.mqtt["broker_topic"], filter.procedure), "data": filter.dataArray }).start()
def ogcSpatCons2PostgisSql(ogcSpatialOperator, geomField, epsgField): """parse an ogc spatial operator element and convert it to a PostGIS SQL spatial WHERE clause""" ogcSupportedSpatialOperators = { 'ogc:Disjoint': 'ST_Disjoint', 'ogc:Equals': 'ST_Equals', 'ogc:Intersect': 'ST_Intersects', 'ogc:Touches': 'ST_Touches', 'ogc:Crosses': 'ST_Crosses', 'ogc:Within': 'ST_Within', 'ogc:Contains': 'ST_Contains', 'ogc:Overlaps': 'ST_Overlaps', } ogcSupportedDistanceBufferType = ['ogc:DWithin'] ogcBBOXType = ['ogc:BBOX'] ogcUnsupportedSpatialOperators = ['ogc:Beyond'] if ogcSpatialOperator.__class__.__name__ in ["str", "StringField"]: xmlString = """<?xml version="1.0" encoding="UTF-8"?><sos:featureOfInterest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.opengis.net/sos/1.0.0/sosAll.xsd" xmlns:sos="http://www.opengis.net/sos/1.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:om="http://www.opengis.net/om/1.0" service="SOS" version='1.0.0'> """ xmlString += ogcSpatialOperator + "</sos:featureOfInterest>" xmlObject = minidom.parseString(xmlString) foi = xmlObject.getElementsByTagName("sos:featureOfInterest")[0] ogcSpatialOperator = childElementNodes(foi)[0] try: ogcOperator = ogcSpatialOperator.nodeName.encode() except: raise sosException.SOSException( "NoApplicableCode", None, "ogcSpatCons2PostgisSql: argunment must be an ''XML object'' or a valid ''XML string''" ) sql = '' #--------------------------- # PARSE OPTIONS #--------------------------- if ogcOperator in ogcSupportedSpatialOperators.keys(): childs = childElementNodes(ogcSpatialOperator) propertyName = childs[0].firstChild.data.encode() geometry = childs[1] try: epsg = geometry.attributes['srsName'].value.split(":")[-1] except: epsg = None if not epsg.isdigit() and not epsg == None: raise sosException.SOSException( "NoApplicableCode", None, "Error: srsName '%s' must be numeric!" % (epsg)) GMLgeom = str(geometry.toxml()).replace("epsg:", "EPSG:") if epsgField == epsg or epsg == None: sql = "%s(%s,ST_GeomFromGML('%s'),%s))" % ( ogcSupportedSpatialOperators[ogcOperator], geomField, GMLgeom, epsgField) else: sql = "%s(%s,ST_Transform(ST_Transform(ST_GeomFromGML('%s'),%s),%s))" % ( ogcSupportedSpatialOperators[ogcOperator], geomField, GMLgeom, epsg, epsgField) return sql elif ogcOperator == 'ogc:BBOX': childs = childElementNodes(ogcSpatialOperator) propertyName = childs[0].firstChild.data.encode() geometry = childs[1] try: epsg = geometry.attributes['srsName'].value.split(":")[-1] except: epsg = None if not epsg.isdigit() and not epsg == None: raise sosException.SOSException( "NoApplicableCode", None, "Error: srsName '%s' must be numeric!" % (epsg)) coords_llur = ",".join( geometry.getElementsByTagName('gml:coordinates') [0].firstChild.data.split(" ")) ce = [float(a) for a in coords_llur.split(",")] if epsgField == epsg or epsg == None: sql = "%s && ST_MakeEnvelope(%s,%s,%s,%s,%s)" % ( geomField, ce[0], ce[1], ce[2], ce[3], epsgField) else: sql = "%s && ST_Transform(ST_MakeEnvelope(%s,%s,%s,%s,%s),%s)" % ( geomField, ce[0], ce[1], ce[2], ce[3], epsg, epsgField) return sql elif ogcOperator == 'ogc:DWithin': childs = childElementNodes(ogcSpatialOperator) propertyName = childs[0].firstChild.data.encode() geometry = childs[1] distance = childs[2].firstChild.data.encode() try: epsg = geometry.attributes['srsName'].value.split(":")[-1] except: epsg = None if not epsg.isdigit() and not epsg == None: raise sosException.SOSException( "NoApplicableCode", None, "Error: srsName '%s' must be numeric!" % (epsg)) GMLgeom = str(geometry.toxml()).replace("epsg:", "EPSG:") if epsgField == epsg or epsg == None: sql = "ST_DWithin(%s,ST_GeomFromGML('%s'),%s)" % ( geomField, GMLgeom, distance) else: sql = "ST_DWithin(%s,ST_Transform(ST_GeomFromGML('%s'),%s),%s)" % ( geomField, GMLgeom, epsgField, distance) return sql elif ogcOperator in ogcUnsupportedSpatialOperators: raise sosException.SOSException( "NoApplicableCode", None, "Spatial Operator nor supported. Available methods are: %s" % (",".join(ogcSupportedSpatialOperators.keys()))) else: raise sosException.SOSException("NoApplicableCode", None, "ogcSpatialOperator format ERROR")
def __init__(self, sosRequest, method, requestObject, sosConfig): f.sosFilter.__init__(self, sosRequest, method, requestObject, sosConfig) #************************** if method == "GET": raise sosException.SOSException( "NoApplicableCode", None, "registerSensor request support only POST method!") if method == "POST": from StringIO import StringIO tree, ns = parse_and_get_ns(StringIO(requestObject)) #---SensorDescription #---------------------- SensorDescription = tree.find("{%s}SensorDescription" % ns['sos']) if SensorDescription == None: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "sos:SensorDescription parameter is mandatory with multiplicity 1" ) #---Procedure Name name = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}name" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) self.procedure = name.text #---ProcedureDescription description = tree.find( "{%s}SensorDescription/{%s}member/{%s}System/{%s}description" % (ns['sos'], ns['sml'], ns['sml'], ns['gml'])) if not description == None: self.proc_desc = description.text else: self.proc_desc = 'NULL' # Add capabilities time to db # Convert all to seconds #---Capabilities capabilities = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/{%s}capabilities/{%s}DataRecord/{%s}field" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['swe'], ns['swe'])) #print >> sys.stderr, "capabilities: ",capabilities self.time_sam_val = "0" self.time_acq_val = "0" for cap in capabilities: if cap.attrib.has_key('name') and cap.attrib[ 'name'] == 'Sampling time resolution': # parse Sampling time resolution tmpSam = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if uom.attrib.has_key('code'): uomSam = uom.attrib['code'] self.time_sam_val = convertToSec[uomSam]( tmpSam) #convertToSec(uomSam,tmpSam) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "sml:capabilities, missing uom for Sampling time resolution" ) elif cap.attrib.has_key('name') and cap.attrib[ 'name'] == 'Acquisition time resolution': # parse Acquisition time resolution tmpAcq = int( cap.find("{%s}Quantity/{%s}value" % (ns['swe'], ns['swe'])).text) uom = cap.find("{%s}Quantity/{%s}uom" % (ns['swe'], ns['swe'])) if uom.attrib.has_key('code'): uomAcq = uom.attrib['code'] self.time_acq_val = convertToSec[uomAcq]( tmpAcq) #convertToSec(uomAcq,tmpAcq) else: raise sosException.SOSException( "MissingParameterValue", "SensorDescription", "sml:capabilities, missing uom for Sampling time resolution" ) #print >> sys.stderr, self.time_sam_val #---System type # From istSOS 2.0 the system type became mandatory (insitu-fixed-point, insitu-mobile-point, ...) self.systemType = None classifiers = tree.findall( "{%s}SensorDescription/{%s}member/{%s}System/{%s}classification/{%s}ClassifierList/{%s}classifier" % (ns['sos'], ns['sml'], ns['sml'], ns['sml'], ns['sml'], ns['sml'])) for classifier in classifiers: if classifier.attrib.has_key( 'name') and classifier.attrib['name'] == 'System Type': val = classifier.find("{%s}Term/{%s}value" % (ns['sml'], ns['sml'])) if val != None: self.systemType = val.text member = tree.find("{%s}SensorDescription/{%s}member" % (ns['sos'], ns['sml'])) root = et.Element("{%s}SensorML" % ns['sml']) root.attrib["{%s}schemaLocation" % ns[ 'xsi']] = "http://www.opengis.net/sensorML/1.0.1 http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd" root.attrib["version"] = "1.0.1" root.append(member) self.xmlSensorDescription = root """ from xml.dom.minidom import parseString txt = et.tostring(root, encoding="UTF-8") self.xmlSensorDescription = parseString(txt).toprettyxml() """ #---ObservationTemplate #---------------------- ObservationTemplate = tree.find("{%s}ObservationTemplate" % ns['sos']) if ObservationTemplate == None: raise sosException.SOSException( "MissingParameterValue", "ObservationTemplate", "ObservationTemplate parameter is mandatory with multiplicity 1" ) Observation = ObservationTemplate.find("{%s}Observation" % ns['om']) if Observation == None: raise sosException.SOSException( "NoApplicableCode", None, "om:Observation tag is mandatory with multiplicity 1") #-------procedure procedure = Observation.find("{%s}procedure" % ns['om']) self.procedure = procedure.attrib["{%s}href" % ns['xlink']].split(":")[-1] if procedure == None: raise sosException.SOSException( "NoApplicableCode", None, "om:procedure tag is mandatory with multiplicity 1") #-------ObservedProperties self.oprDef = [] self.oprDesc = [] self.oprName = [] self.beginPosition = 'NULL' try: name = Observation.find( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}name" % (ns['om'], ns['swe'], ns['gml'])) except: raise sosException.SOSException( "NoApplicableCode", None, "swe:CompositePhenomenon mandatory name element is missing" ) components = Observation.findall( "{%s}observedProperty/{%s}CompositePhenomenon/{%s}component" % (ns['om'], ns['swe'], ns['swe'])) if not components == []: for comp in components: try: self.oprDef.append(comp.attrib["{%s}href" % ns['xlink']]) except: raise sosException.SOSException( "NoApplicableCode", None, "om:observedProperty/component attribute missing: 'xlink:href' required" ) """ NON STANDARD try: desc = comp.find("{%s}description" % ns['gml']) self.oprDesc.append(desc.text) except: self.oprDesc.append("NULL") try: desc = comp.find("{%s}name" % ns['gml']) self.oprName.append(desc.text) except: self.oprName.append("NULL") """ """ PER COSA È? CASO NON COMPOSITEPHENOMENON? else: observedProperty = Observation.find("{%s}observedProperty" % ns['om']) try: self.oprName.append(observedProperty.attrib["{%s}href" % ns['xlink']]) except: name = Observation.find("{%s}observedProperty/{%s}name" %(ns['om'],ns['gml']) ) try: self.oprName.append(name.txt) except: raise sosException.SOSException(1, "om:observedProperty Name is missing: 'xlink:href' or 'gml:name' required") desc = Observation.find("{%s}observedProperty/{%s}description" %(ns['om'],ns['gml']) ) try: self.oprDesc.append(desc.txt) except: self.oprDesc.append("NULL") """ #-------samplingTime #============================================================================== # samplingTime = Observation.find("{%s}samplingTime" % ns['om'] ) # if samplingTime == None: # raise sosException.SOSException("NoApplicableCode",None,"om:samplingTime tag is mandatory with multiplicity 1") # else: # duration = samplingTime.find("{%s}TimePeriod/{%s}TimeLength/{%s}duration" # %(ns['gml'],ns['gml'],ns['gml'], ) ) # # if not duration==None: # # strdur = str( parse_duration( duration.text.strip() ) ).split(",") # if len(strdur)>1: # self.time_res_val = strdur[0].split(" ")[0] # self.time_res_unit = strdur[0].split(" ")[1] # elif len(strdur)==1: # time = strdur[0].split(":") # self.time_res_val = parse_duration( duration.text.strip() ).seconds # self.time_res_unit = "sec" # else: # self.time_res_unit = "unknown" # self.time_res_val = "NULL" #============================================================================== #------featureOfInterest featureOfInterest = Observation.find("{%s}featureOfInterest" % ns['om']) if featureOfInterest == None: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest tag is mandatory with multiplicity 1" ) try: self.foiName = featureOfInterest.attrib["{%s}href" % ns['xlink']] except: raise sosException.SOSException( "NoApplicableCode", None, "om:featureOfInterest: attribute 'xlink:href' is required") """ NON COMPLIANT name = Observation.find("{%s}featureOfInterest/{%s}name" %(ns['om'],ns['gml']) ) try: self.foiName = name.text except: raise sosException.SOSException(1,"om:featureOfInterest name is missing: 'xlink:href' or 'gml:name' is required") """ description = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/{%s}description" % (ns['om'], ns['gml'], ns['gml'])) if not description == None: self.foiDesc = description.text else: self.foiDesc = "NULL" #--foiWKZ # gml_type = ["gml:Polygon", "gml:LineString", "gml:Point", "gml:Box", "gml:GeometryCollection", # "gml:MultiPoint", "gml:MultiLineString", "gml:MultiPolygon"] self.foiType = None for geomtype in sosConfig.foiGeometryType: geomtype = geomtype.split(":")[1] GMLfeature = Observation.find( "{%s}featureOfInterest/{%s}FeatureCollection/{%s}location/{%s}%s" % (ns['om'], ns['gml'], ns['gml'], ns['gml'], geomtype)) if not GMLfeature == None: self.foiType = geomtype self.foiSRS = GMLfeature.attrib["srsName"].split(":")[-1] self.foiGML = et.tostring( GMLfeature, encoding="UTF-8").replace( "<?xml version='1.0' encoding='UTF-8'?>", "") if self.foiType == None: raise sosException.SOSException( "NoApplicableCode", None, "not found valid GML feature, supported: %s " % (";".join(sosConfig.foiGeometryType))) #--result result = Observation.find("{%s}result" % ns['om']) self.parameters = [] self.uoms = [] self.names = [] self.descs = [] self.constr = [] self.partime = [] if not result == None: sdr = Observation.find("{%s}result/{%s}SimpleDataRecord" % (ns['om'], ns['swe'])) da = Observation.find("{%s}result/{%s}DataArray" % (ns['om'], ns['swe'])) if sdr != None and da == None: fields = sdr.findall("{%s}field" % ns['swe']) elif da != None and sdr == None: fields = da.findall( "{%s}elementType/{%s}DataRecord/{%s}field" % (ns['swe'], ns['swe'], ns['swe'])) else: err_txt = "in <swe:result>: <swe:DataRecord> or <swe:DataArray> are mandatory in multiplicity 1" raise sosException.SOSException("NoApplicableCode", None, err_txt) timetag = False for field in fields: defin = None uom = None self.names.append(field.attrib['name']) tf = field.find("{%s}Time" % ns['swe']) qf = field.find("{%s}Quantity" % ns['swe']) if not tf == None and qf == None: self.partime.append(1) timetag = True self.parameters.append(tf.attrib["definition"]) uom = tf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = tf.find("{%s}description" % ns['swe']) if not desc == None: self.descs.append(desc.text) else: self.descs.append("NULL") #self.constr.append(None) #self.constr.append("NULL") elif not qf == None and tf == None: self.partime.append(0) self.parameters.append(qf.attrib["definition"]) uom = qf.find("{%s}uom" % ns['swe']) self.uoms.append(uom.attrib["code"]) desc = qf.find("{%s}description" % ns['swe']) if not desc == None: self.descs.append(desc.text) else: self.descs.append("NULL") # look for constraints [min,max,interval,valueList] #=================================================== #import sys cc = {} constraints = qf.findall("{%s}constraint" % (ns['swe'])) if len(constraints) == 0: self.constr.append(None) else: for constraint in constraints: if constraint: if "{%s}role" % ns[ "xlink"] in constraint.attrib: if constraint.attrib["{%s}role" % ns[ "xlink"]] == "urn:ogc:def:classifiers:x-istsos:1.0:qualityIndex:check:reasonable": crole = constraint.attrib[ "{%s}role" % ns["xlink"]] allow = constraint.find( "{%s}AllowedValues" % (ns['swe'])) if allow is None: err_txt = "in <swe:constraint>: <swe:AllowedValues> is mandatory in multiplicity 1" raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: cvals = None if len(allow) == 1: ct = allow[0].tag if not ct in [ "{%s}min" % ns["swe"], "{%s}max" % ns["swe"], "{%s}interval" % ns["swe"], "{%s}valueList" % ns["swe"] ]: err_txt = "in <swe:constraint>: support only min, max, interval, valueList tag" raise sosException.SOSException( "NoApplicableCode", None, err_txt) xvals = allow[ 0].text.strip().split( " ") if ct == "{%s}min" % ns[ "swe"]: ct = "min" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float( xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}max" % ns[ "swe"]: ct = "max" if not len(xvals) == 1: err_txt = "'%s' constraint support/need one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = float( xvals[0]) except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}interval" % ns[ "swe"]: ct = "interval" if not len(xvals) == 2: err_txt = "'%s' constraint support/need two values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float( xvals[0]), float(xvals[1]) ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) elif ct == "{%s}valueList" % ns[ "swe"]: ct = "valueList" if not len(xvals) > 0: err_txt = "'%s' constraint support/need at least one values" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) try: cvals = [ float(a) for a in xvals ] except: err_txt = "'%s' constraint requires float value" % ct raise sosException.SOSException( "NoApplicableCode", None, err_txt) cc["role"] = crole cc["%s" % ct] = cvals if not cc == {}: self.constr.append(json.dumps(cc)) else: self.constr.append(None) else: err_txt = "swe:Time or swe:Quantity is mandatory in multiplicity 1:N" raise sosException.SOSException( "NoApplicableCode", None, err_txt) else: err_txt = "om:result is mandatory in multiplicity 1:N" raise sosException.SOSException("NoApplicableCode", None, err_txt) #case simple om:result """ WAS elif len(sdr)==0 and len(da)==0: if len(observedProperties)==1: self.parameters.append(observedProperties[0]) self.uoms.append(getElemAtt(res[0],"uom")) else: raise sosException.SOSException(1,"om:observedProperty is mandatory with multiplicity 1") else: err_txt = "om:observation ERROR" raise sosException.SOSException(1,err_txt) """ """
def __init__(self, filter, pgdb): pgdb.setTimeTZ("UTC") self.version = filter.version self.smlFile = "" sql = "SELECT id_prc, stime_prc, etime_prc, name_oty from %s.procedures, %s.obs_type" %(filter.sosConfig.schema,filter.sosConfig.schema) sql += " WHERE id_oty=id_oty_fk AND name_prc = %s" params = (str(filter.procedure),) try: res=pgdb.select(sql,params) except: raise Exception("Error! sql: %s." %(pgdb.mogrify(sql,params)) ) # raise error if the procedure is not found in db if res==None: raise sosException.SOSException("InvalidParameterValue","procedure","Procedure '%s' not exist or can't be found.") # look for observation end time try: self.procedureType = res[0]['name_oty'] except: self.procedureType = None if self.procedureType == 'virtual': vpFolder = os.path.join(filter.sosConfig.virtual_processes_folder,filter.procedure) try: sys.path.append(vpFolder) except: raise Exception("Error in loading virtual procedure path") # check if python file exist if os.path.isfile("%s/%s.py" % (vpFolder,filter.procedure)): #import procedure process exec "import %s as vproc" %(filter.procedure) # Initialization of virtual procedure will load the source data vp = vproc.istvp() vp._configure(filter,pgdb) self.stime, self.etime = vp.getSampligTime() else: self.stime = None self.etime = None else: # look for observation start time try: self.stime = res[0]['stime_prc'] except: self.stime = None #raise sosException.SOSException(1,"Procedure '%s' has no valid stime."%(filter.procedure)) # look for observation end time try: self.etime = res[0]['etime_prc'] except: self.etime = None # check if folder containing SensorML exists if not os.path.isdir(filter.sosConfig.sensorMLpath): raise Exception("istsos configuration error, cannot find sensorMLpath!") # clean up the procedure name to produce a valid file name filename = filter.procedure valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits) for c in filename: if not c in valid_chars: raise Exception("procedure name '%s' is not a valid: use only letters or digits!"%(filter.procedure)) filename += '.xml' self.smlFile = os.path.join(filter.sosConfig.sensorMLpath, filename) # check if file exist if not os.path.isfile(self.smlFile): raise Exception("SensorML file for procedure '%s' not found!" % (filter.procedure)) sqlProc = "SELECT def_opr, name_opr, desc_opr, constr_pro, name_uom, id_pro" sqlProc += " FROM %s.observed_properties opr, %s.proc_obs po," %(filter.sosConfig.schema,filter.sosConfig.schema) sqlProc += " %s.procedures pr, %s.uoms um" %(filter.sosConfig.schema,filter.sosConfig.schema) sqlProc += " WHERE opr.id_opr=po.id_opr_fk AND pr.id_prc=po.id_prc_fk AND um.id_uom = po.id_uom_fk" sqlProc += " AND name_prc = %s ORDER BY id_pro" params = (str(filter.procedure),) try: self.observedProperties = pgdb.select(sqlProc, params) except Exception as exe: raise Exception("Error! %s\n > sql: %s." % (str(exe), pgdb.mogrify(sqlProc, params)))