2014-09-03 08:43:11 -04:00

320 lines
14 KiB
Python

# encoding: utf-8
from owslib.etree import etree
from owslib import crs, util
from owslib.util import testXMLValue, testXMLAttribute, nspath_eval, xmltag_split, dict_union, extract_xml_list
from owslib.namespaces import Namespaces
def get_namespaces():
n = Namespaces()
namespaces = n.get_namespaces(["sml","gml","xlink"])
namespaces["ism"] = "urn:us:gov:ic:ism:v2"
return namespaces
namespaces = get_namespaces()
def nsp(path):
return nspath_eval(path, namespaces)
class SensorML(object):
def __init__(self, element):
if isinstance(element, str):
self._root = etree.fromstring(element)
else:
self._root = element
if hasattr(self._root, 'getroot'):
self._root = self._root.getroot()
self.members = [Member(x) for x in self._root.findall(nsp('sml:member'))]
class Member(object):
def __new__(cls, element):
t = element[-1].tag.split("}")[-1]
if t == "System":
return System(element.find(nsp("sml:System")))
elif t == "ProcessChain":
return ProcessChain(element.find(nsp("sml:ProcessChain")))
elif t == "ProcessModel":
return ProcessModel(element.find(nsp("sml:ProcessModel")))
elif t == "Component":
return Component(element.find(nsp("sml:Component")))
class PropertyGroup(object):
def __init__(self, element):
# Both capabilities and characteristics contain a single swe:DataRecord element
self.capabilities = {}
for cap in element.findall(nsp('sml:capabilities')):
name = testXMLAttribute(cap, "name")
if name is not None:
self.capabilities[name] = cap[0]
self.characteristics = {}
for cha in element.findall(nsp('sml:characteristics')):
name = testXMLAttribute(cha, "name")
if name is not None:
self.characteristics[name] = cha[0]
def get_capabilities_by_name(self, name):
"""
Return list of element by name, case insensitive
"""
return [self.capabilities[capab] for capab in self.capabilities.keys() if capab.lower() == name.lower()]
def get_characteristics_by_name(self, name):
"""
Return list of element objects by name, case insensitive
"""
return [self.characteristics[charac] for charac in self.characteristics.keys() if charac.lower() == name.lower()]
class ConstraintGroup(object):
def __init__(self, element):
# ism:SecurityAttributesOptionsGroup
self.security = element.findall(nsp("sml:securityConstraint/sml:Security/ism:SecurityAttributesOptionGroup"))
# gml:TimeInstant or gml:TimePeriod element
self.validTime = element.find(nsp("sml:validTime"))
self.rights = [Right(x) for x in element.findall(nsp("sml:legalConstraint/sml:Rights"))]
class Documentation(object):
def __init__(self, element):
self.arcrole = testXMLAttribute(element, nsp("xlink:arcrole"))
self.url = testXMLAttribute(element, nsp("xlink:href"))
self.documents = [Document(d) for d in element.findall(nsp("sml:Document"))]
class Document(object):
def __init__(self, element):
self.id = testXMLAttribute(element, nsp("gml:id"))
self.version = testXMLValue(element.find(nsp("sml:version")))
self.description = testXMLValue(element.find(nsp("gml:description")))
self.date = testXMLValue(element.find(nsp("sml:date")))
try:
self.contact = Contact(element.find(nsp("sml:contact")))
except AttributeError:
self.contact = None
self.format = testXMLValue(element.find(nsp('sml:format')))
self.url = testXMLAttribute(element.find(nsp('sml:onlineResource')), nsp('xlink:href'))
class Right(object):
def __init__(self, element):
self.id = testXMLAttribute(element, nsp('gml:id'))
self.privacyAct = testXMLAttribute(element, nsp('sml:privacyAct'))
self.intellectualPropertyRights = testXMLAttribute(element, nsp('sml:intellectualPropertyRights'))
self.copyRights = testXMLAttribute(element, nsp('sml:copyRights'))
self.documentation = [Documentation(x) for x in element.findall(nsp("sml:documentation"))]
class ReferenceGroup(object):
def __init__(self, element):
self.contacts = {}
for contact in element.findall(nsp('sml:contact')):
cont = Contact(contact)
self.contacts[cont.role] = cont
self.documentation = [Documentation(x) for x in element.findall(nsp("sml:documentation"))]
def get_contacts_by_role(self, role):
"""
Return a Contact by role, case insensitive
"""
return [self.contacts[contact] for contact in self.contacts.keys() if contact.lower() == role.lower()]
class GeneralInfoGroup(object):
def __init__(self, element):
self.keywords = extract_xml_list(element.findall(nsp('sml:keywords/sml:KeywordList/sml:keyword')))
self.identifiers = {}
for identifier in element.findall(nsp('sml:identification/sml:IdentifierList/sml:identifier')):
ident = Identifier(identifier)
self.identifiers[ident.name] = ident
self.classifiers = {}
for classifier in element.findall(nsp('sml:classification/sml:ClassifierList/sml:classifier')):
classi = Classifier(classifier)
self.classifiers[classi.name] = classi
def get_identifiers_by_name(self, name):
"""
Return list of Identifier objects by name, case insensitive
"""
return [self.identifiers[identifier] for identifier in self.identifiers.keys() if identifier.lower() == name.lower()]
def get_classifiers_by_name(self, name):
"""
Return list of Classifier objects by name, case insensitive
"""
return [self.classifiers[classi] for classi in self.classifiers.keys() if classi.lower() == name.lower()]
class Contact(object):
def __init__(self, element):
# TODO: This only supports the sml:contact/sml:ResponsibleParty elements, but there are numerous ways to store
# contact information here.
self.role = testXMLAttribute(element, nsp("xlink:role"))
self.href = testXMLAttribute(element, nsp("xlink:href"))
self.organization = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:organizationName')))
self.phone = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:phone/sml:voice')))
self.address = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:address/sml:deliveryPoint')))
self.city = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:address/sml:city')))
self.region = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:address/sml:administrativeArea')))
self.postcode = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:address/sml:postalCode')))
self.country = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:address/sml:country')))
self.email = testXMLValue(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:address/sml:electronicMailAddress')))
self.url = testXMLAttribute(element.find(nsp('sml:ResponsibleParty/sml:contactInfo/sml:onlineResource')), nsp("xlink:href"))
class HistoryGroup(object):
def __init__(self, element):
self.history = {}
for event_member in element.findall(nsp('sml:history/sml:EventList/sml:member')):
name = testXMLAttribute(event_member, "name")
if self.history.get(name) is None:
self.history[name] = []
for e in event_member.findall(nsp("sml:Event")):
self.history[name].append(Event(e))
def get_history_by_name(self, name):
"""
Return Events list by members name
"""
return self.history.get(name.lower(), [])
class Event(ReferenceGroup, GeneralInfoGroup):
def __init__(self, element):
ReferenceGroup.__init__(self, element)
GeneralInfoGroup.__init__(self, element)
self.id = testXMLAttribute(element, nsp("gml:id"))
self.date = testXMLValue(element.find(nsp('sml:date')))
self.description = testXMLValue(element.find(nsp('gml:description')))
class MetadataGroup(GeneralInfoGroup, PropertyGroup, ConstraintGroup, ReferenceGroup, HistoryGroup):
def __init__(self, element):
GeneralInfoGroup.__init__(self, element)
PropertyGroup.__init__(self, element)
ConstraintGroup.__init__(self, element)
ReferenceGroup.__init__(self, element)
HistoryGroup.__init__(self, element)
class AbstractFeature(object):
def __init__(self, element):
self.name = testXMLValue(element.find(nsp("gml:name")))
self.description = testXMLValue(element.find(nsp("gml:description")))
self.gmlBoundedBy = testXMLValue(element.find(nsp("gml:boundedBy")))
class AbstractProcess(AbstractFeature, MetadataGroup):
def __init__(self, element):
AbstractFeature.__init__(self, element)
MetadataGroup.__init__(self, element)
# sml:IoComponentPropertyType
self.inputs = element.findall(nsp("sml:input"))
# sml:IoComponentPropertyType
self.outputs = element.findall(nsp("sml:output"))
# swe:DataComponentPropertyType
self.parameters = element.findall(nsp("sml:parameter"))
class AbstractRestrictedProcess(AbstractFeature):
""" Removes ('restricts' in xml schema language) gml:name, gml:description, and sml:metadataGroup from an AbstractProcess """
def __init__(self, element):
AbstractFeature.__init__(self, element)
self.name = None
self.description = None
class AbstractPureProcess(AbstractRestrictedProcess):
def __init__(self, element):
AbstractRestrictedProcess.__init__(self, element)
# sml:IoComponentPropertyType
self.inputs = element.findall(nsp("sml:input"))
# sml:IoComponentPropertyType
self.outputs = element.findall(nsp("sml:output"))
# swe:DataComponentPropertyType
self.parameters = element.findall(nsp("sml:parameter"))
class ProcessModel(AbstractPureProcess):
def __init__(self, element):
AbstractPureProcess.__init__(self, element)
self.method = ProcessMethod(element.find("method"))
class CompositePropertiesGroup(object):
def __init__(self, element):
# All components should be of instance AbstractProcess (sml:_Process)
self.components = element.findall(nsp("sml:components/sml:ComponentList/sml:component"))
# sml:Link or sml:ArrayLink element
self.connections = element.findall(nsp("sml:connections/sml:ConnectionList/sml:connection"))
class PhysicalPropertiesGroup(object):
def __init__(self, element):
# gml:EngieeringCRS element
self.spatialReferenceFrame = element.find(nsp("sml:spatialReferenceFrame/gml:EngineeringCRS"))
# gml:TemporalCRS element
self.temporalReferenceFrame = element.find(nsp("sml:temporalReferenceFrame/gml:TemporalCRS"))
# gml:Envelope element
self.smlBoundedBy = element.find(nsp("sml:boundedBy"))
# swe:Time or sml:_Process element
self.timePosition = element.find(nsp("sml:timePosition"))
# It is either a sml:position OR and sml:location element here. Process both.
# swe:Position, swe:Vector, or sml:_Process element
self.positions = element.findall(nsp("sml:position"))
# gml:Point of gml:_Curve
self.location = element.find(nsp("sml:location"))
try:
self.interface = Interface(element.find(nsp("sml:interface")))
except AttributeError:
self.interface = None
class ProcessChain(AbstractPureProcess, CompositePropertiesGroup):
def __init__(self, element):
AbstractPureProcess.__init__(self, element)
CompositePropertiesGroup.__init__(self, element)
class System(AbstractProcess, PhysicalPropertiesGroup, CompositePropertiesGroup):
def __init__(self, element):
AbstractProcess.__init__(self, element)
PhysicalPropertiesGroup.__init__(self, element)
CompositePropertiesGroup.__init__(self, element)
class Component(AbstractProcess, PhysicalPropertiesGroup):
def __init__(self, element):
AbstractProcess.__init__(self, element)
PhysicalPropertiesGroup.__init__(self, element)
self.method = ProcessMethod(element.find("method"))
class Term(object):
def __init__(self, element):
self.codeSpace = testXMLAttribute(element.find(nsp('sml:Term/sml:codeSpace')), nsp("xlink:href"))
self.definition = testXMLAttribute(element.find(nsp('sml:Term')), "definition")
self.value = testXMLValue(element.find(nsp('sml:Term/sml:value')))
class Classifier(Term):
def __init__(self, element):
Term.__init__(self, element)
self.name = testXMLAttribute(element, "name")
class Identifier(Term):
def __init__(self, element):
Term.__init__(self, element)
self.name = testXMLAttribute(element, "name")
class ProcessMethod(MetadataGroup):
""" Inherits from gml:AbstractGMLType """
def __init__(self, element):
MetadataGroup.__init__(self, element)
self.rules = element.find(nsp("sml:rules"))
self.ioStructure = element.find(nsp("sml:IOStructureDefinition"))
self.algorithm = element.find(nsp("sml:algorithm"))
self.implementations = element.findall(nsp("sml:implementation"))
class Interface(object):
def __init__(self, element):
self.name = testXMLAttribute(element, "name")
self.interface_definition = InterfaceDefinition(element.find(nsp("sml:InterfaceDefinition")))
class InterfaceDefinition(object):
def __init__(self, element):
raise NotImplementedError("InterfaceDefinition is not implemented in OWSLib (yet)")
class Link(object):
def __init__(self, element):
raise NotImplementedError("Link is not implemented in OWSLib (yet)")
class ArrayLink(object):
def __init__(self, element):
raise NotImplementedError("ArrayLink is not implemented in OWSLib (yet)")