/** * Copyright (C) 2012-2017 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * License version 2 and the aforementioned licenses. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. */ package org.n52.sos.convert; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.n52.sos.ogc.gml.ReferenceType; import org.n52.sos.ogc.om.NamedValue; import org.n52.sos.ogc.om.values.TextValue; import org.n52.sos.ogc.sensorML.AbstractProcess; import org.n52.sos.ogc.sensorML.AbstractSensorML; import org.n52.sos.ogc.sensorML.ProcessModel; import org.n52.sos.ogc.sensorML.SensorML; import org.n52.sos.ogc.sensorML.SensorMLConstants; import org.n52.sos.ogc.sensorML.System; import org.n52.sos.ogc.sensorML.elements.AbstractSmlDocumentation; import org.n52.sos.ogc.sensorML.elements.SmlCapabilities; import org.n52.sos.ogc.sensorML.elements.SmlCharacteristics; import org.n52.sos.ogc.sensorML.elements.SmlClassifier; import org.n52.sos.ogc.sensorML.elements.SmlDocumentation; import org.n52.sos.ogc.sensorML.elements.SmlDocumentationList; import org.n52.sos.ogc.sensorML.elements.SmlDocumentationListMember; import org.n52.sos.ogc.sensorML.elements.SmlIdentifier; import org.n52.sos.ogc.sensorML.elements.SmlIo; import org.n52.sos.ogc.sos.SosProcedureDescription; import org.n52.sos.ogc.swe.SweField; import org.n52.sos.ogc.swe.simpleType.SweAbstractSimpleType; import org.n52.sos.ogc.swe.simpleType.SweObservableProperty; import org.n52.sos.ogc.wml.ObservationProcess; import org.n52.sos.ogc.wml.WaterMLConstants; import org.n52.sos.util.CollectionHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Joiner; /** * @since 4.0.0 * */ public class WaterMLv20SensorMLv101Converter implements Converter<SosProcedureDescription, SosProcedureDescription> { /* * TODO - Add function to read mapping information */ private static final Logger LOGGER = LoggerFactory.getLogger(WaterMLv20SensorMLv101Converter.class); private static final List<ConverterKeyType> CONVERTER_KEY_TYPES = CollectionHelper.list( new ConverterKeyType(WaterMLConstants.NS_WML_20_PROCEDURE_ENCODING, SensorMLConstants.SENSORML_OUTPUT_FORMAT_URL), new ConverterKeyType(WaterMLConstants.NS_WML_20_PROCEDURE_ENCODING, SensorMLConstants.SENSORML_OUTPUT_FORMAT_MIME_TYPE), new ConverterKeyType(SensorMLConstants.SENSORML_OUTPUT_FORMAT_URL,WaterMLConstants.NS_WML_20_PROCEDURE_ENCODING), new ConverterKeyType(SensorMLConstants.SENSORML_OUTPUT_FORMAT_MIME_TYPE,WaterMLConstants.NS_WML_20_PROCEDURE_ENCODING)); public WaterMLv20SensorMLv101Converter() { LOGGER.debug("Converter for the following keys initialized successfully: {}!", Joiner.on(", ").join(CONVERTER_KEY_TYPES)); } @Override public List<ConverterKeyType> getConverterKeyTypes() { return Collections.unmodifiableList(CONVERTER_KEY_TYPES); } @Override public SosProcedureDescription convert(final SosProcedureDescription objectToConvert) throws ConverterException { if (objectToConvert.getDescriptionFormat().equals(WaterMLConstants.NS_WML_20_PROCEDURE_ENCODING)) { return convertWML2ObservationProcessToSensorML101(objectToConvert); } else if (objectToConvert.getDescriptionFormat().equals(SensorMLConstants.SENSORML_OUTPUT_FORMAT_URL) || objectToConvert.getDescriptionFormat().equals(SensorMLConstants.SENSORML_OUTPUT_FORMAT_MIME_TYPE)) { return convertSensorML101ToWML2ObservationProcess(objectToConvert); } return null; } private SosProcedureDescription convertSensorML101ToWML2ObservationProcess(final SosProcedureDescription objectToConvert) { final ObservationProcess observationProcess = new ObservationProcess(); if (objectToConvert instanceof SensorML) { final SensorML sensorML = (SensorML) objectToConvert; if (sensorML.isWrapper()) { for (final AbstractProcess member : sensorML.getMembers()) { // TODO get values and add to obsProcess if (member.isSetIdentifier()) { observationProcess.setIdentifier(member.getIdentifierCodeWithAuthority()); } if (member instanceof System) { convertSystemToObservationProcess(observationProcess, (System) member); } else if (member instanceof ProcessModel) { convertProcessModelToObservationProcess(observationProcess, (ProcessModel) member); } } } // TODO add 'else' to get values and add to obsProcess from sensorML } else { observationProcess.setProcessType(new ReferenceType(WaterMLConstants.PROCESS_TYPE_UNKNOWN)); } observationProcess.setIdentifier(objectToConvert.getIdentifierCodeWithAuthority()); observationProcess.setDescriptionFormat(WaterMLConstants.NS_WML_20_PROCEDURE_ENCODING); return observationProcess; } private SosProcedureDescription convertWML2ObservationProcessToSensorML101(final SosProcedureDescription objectToConvert) { final SensorML sensorML = new SensorML(); if (objectToConvert instanceof ObservationProcess) { final ObservationProcess observationProcess = new ObservationProcess(); if (observationProcess.isSetProcessType()) { AbstractProcess process; if (checkProcessType(observationProcess.getProcessType(), WaterMLConstants.PROCESS_TYPE_SENSOR)) { process = convertObservationProcessToSystem(observationProcess); } else { process = convertObservationProcessToProcessModel(observationProcess); } process.setClassifications(convertProcessTypeToClassification(observationProcess.getProcessType())); sensorML.addMember(process); } } else { sensorML.addIdentifier(createUniqueIDIdentifier(objectToConvert.getIdentifier())); } return sensorML; } private System convertObservationProcessToSystem(final ObservationProcess observationProcess) { final System system = new System(); system.addIdentifier(createUniqueIDIdentifier(observationProcess.getIdentifier())); // TODO add all other stuff // if (observationProcess.isSetVerticalDatum()) { // } return system; } private ProcessModel convertObservationProcessToProcessModel(final ObservationProcess observationProcess) { final ProcessModel processModel = new ProcessModel(); processModel.addIdentifier(createUniqueIDIdentifier(observationProcess.getIdentifier())); // duration is not valid for validTime element observationProcess.getAggregationDuration(); if (observationProcess.isSetComments()) { processModel.addDocumentation(convertCommentsToDocumentation(observationProcess.getComments())); } if (observationProcess.isSetInputs()) { processModel.setInputs(convertObservationProcessInputsToSMLInputs(observationProcess.getInputs())); } observationProcess.getOriginatingProcess(); observationProcess.getParameters(); if (observationProcess.isSetProcessReference()) { processModel.addDocumentation(convertProcessReferenceToDocumentation(observationProcess .getProcessReference())); } observationProcess.getVerticalDatum(); // TODO add all other stuff return processModel; } private boolean checkProcessType(final ReferenceType processType, final String processTypeName) { if (processType.isSetHref()) { return processType.getHref().equals(processTypeName); } return false; } private SmlIdentifier createUniqueIDIdentifier(final String procedureIdentifier) { return new SmlIdentifier("uniqueID", "urn:ogc:def:identifier:OGC:uniqueID", procedureIdentifier); } private List<SmlClassifier> convertProcessTypeToClassification(final ReferenceType processType) { final String definition = "urn:ogc:def:classifier:OGC:1.0:sensorType"; final SmlClassifier sosSMLClassifier = new SmlClassifier(processType.getTitle(), definition, null, processType.getHref()); return Collections.singletonList(sosSMLClassifier); } private AbstractSmlDocumentation convertCommentsToDocumentation(final List<String> comments) { // TODO check for correctness if (comments.size() > 1) { final SmlDocumentation documentation = new SmlDocumentation(); documentation.setDescription(comments.get(0)); return documentation; } else { final SmlDocumentationList documentationList = new SmlDocumentationList(); for (final String comment : comments) { final SmlDocumentationListMember member = new SmlDocumentationListMember(); final SmlDocumentation documentation = new SmlDocumentation(); documentation.setDescription(comment); member.setDocumentation(documentation); documentationList.addMember(member); } return documentationList; } } private List<SmlIo<?>> convertObservationProcessInputsToSMLInputs(final List<ReferenceType> inputs) { final List<SmlIo<?>> smlInputs = new ArrayList<SmlIo<?>>(inputs.size()); for (final ReferenceType referenceType : inputs) { final SmlIo<String> io = new SmlIo<String>(); if (referenceType.isSetTitle()) { io.setIoName(referenceType.getTitle()); } final SweObservableProperty ioValue = new SweObservableProperty(); ioValue.setDefinition(referenceType.getHref()); io.setIoValue(ioValue); } return smlInputs; } private AbstractSmlDocumentation convertProcessReferenceToDocumentation(final ReferenceType processReference) { final SmlDocumentation documentation = new SmlDocumentation(); final StringBuilder builder = new StringBuilder(); builder.append(processReference.getHref()); builder.append(";"); builder.append(processReference.getTitle()); documentation.setDescription(builder.toString()); return documentation; } private void convertAbstractSensorMLToObservationProcess(final ObservationProcess observationProcess, final AbstractSensorML abstractSensorML) { if (abstractSensorML.isSetCapabilities()) { convertSMLCapabilitiesToObservationProcessParameter(observationProcess, abstractSensorML.getCapabilities()); } if (abstractSensorML.isSetCharacteristics()) { convertSMLCharacteristicsToObservationProcessParameter(observationProcess, abstractSensorML.getCharacteristics()); } if (abstractSensorML.isSetClassifications()) { convertSMLClassificationsToObservationProcessParameter(observationProcess, abstractSensorML.getClassifications()); } if (abstractSensorML.isSetDocumentation()) { convertSMLDocumentationToObservationProcessComment(observationProcess, abstractSensorML.getDocumentation()); } if (abstractSensorML.isSetIdentifications()) { convertSMLIdentificationsToObservationProcessParameter(observationProcess, abstractSensorML.getIdentifications()); } } private void convertAbstractProcessToObservationProcess(final ObservationProcess observationProcess, final AbstractProcess abstractProces) { if (abstractProces.isSetParameters()) { convertSMLParametersToObservationProcessParameter(observationProcess, abstractProces.getParameters()); } if (abstractProces.isSetInputs()) { observationProcess.setInputs(convertSMLInputsToObservationProcessInputs(abstractProces.getInputs())); } if (abstractProces.isSetOutputs()) { convertSMLOutputsToObservationProcessParameter(observationProcess, abstractProces.getOutputs()); } } private void convertSystemToObservationProcess(final ObservationProcess observationProcess, final System system) { observationProcess.setProcessType(new ReferenceType(WaterMLConstants.PROCESS_TYPE_SENSOR)); convertAbstractSensorMLToObservationProcess(observationProcess, system); convertAbstractProcessToObservationProcess(observationProcess, system); // TODO the rest } private void convertProcessModelToObservationProcess(final ObservationProcess observationProcess, final ProcessModel processModel) { observationProcess.setProcessType(new ReferenceType(WaterMLConstants.PROCESS_TYPE_ALGORITHM)); convertAbstractSensorMLToObservationProcess(observationProcess, processModel); convertAbstractProcessToObservationProcess(observationProcess, processModel); // TODO the rest } private void convertSMLCharacteristicsToObservationProcessParameter(final ObservationProcess observationProcess, final List<SmlCharacteristics> characteristics) { for (final SmlCharacteristics characteristic : characteristics) { if (characteristic.isSetAbstractDataRecord() && characteristic.getDataRecord().isSetFields()) { for (final SweField field : characteristic.getDataRecord().getFields()) { final NamedValue<String> namedValueProperty = convertSMLFieldToNamedValuePair(field); if (namedValueProperty != null) { observationProcess.addParameter(namedValueProperty); } } } } } private void convertSMLClassificationsToObservationProcessParameter(final ObservationProcess observationProcess, final List<SmlClassifier> classifications) { for (final SmlClassifier classifier : classifications) { final NamedValue<String> namedValueProperty = new NamedValue<String>(); // TODO What to do if optional value is not available? final ReferenceType refType = new ReferenceType( classifier.isSetDefinition()? classifier.getDefinition(): "http://example.com/error/classfier_definition_not_set"); refType.setTitle(classifier.getName()); namedValueProperty.setName(refType); namedValueProperty.setValue(new TextValue(classifier.getValue())); observationProcess.addParameter(namedValueProperty); } } private void convertSMLIdentificationsToObservationProcessParameter(final ObservationProcess observationProcess, final List<SmlIdentifier> identifications) { for (final SmlIdentifier identifier : identifications) { final NamedValue<String> namedValueProperty = new NamedValue<String>(); final ReferenceType refType = new ReferenceType(identifier.getDefinition()); refType.setTitle(identifier.getName()); // TODO uncomment if supported // if (identifier.getDefinition().contains("name")) { // CodeType codeType = new CodeType(identifier.getValue()); // codeType.setCodeSpace(identifier.getDefinition()); // observationProcess.addName(codeType); // } namedValueProperty.setName(refType); namedValueProperty.setValue(new TextValue(identifier.getValue())); observationProcess.addParameter(namedValueProperty); } } private void convertSMLDocumentationToObservationProcessComment(final ObservationProcess observationProcess, final List<AbstractSmlDocumentation> documentation) { // TODO Auto-generated method stub } private void convertSMLParametersToObservationProcessParameter(final ObservationProcess observationProcess, final List<String> parameters) { // TODO Auto-generated method stub } private void convertSMLOutputsToObservationProcessParameter(final ObservationProcess observationProcess, final List<SmlIo<?>> outputs) { for (final SmlIo<?> sosSMLIo : outputs) { final ReferenceType referenceType = new ReferenceType("output"); final NamedValue<String> namedValueProperty = new NamedValue<String>(); namedValueProperty.setName(referenceType); namedValueProperty.setValue(new TextValue(sosSMLIo.getIoValue().getDefinition())); // NamedValuePair namedValueProperty = // getNamedValuePairForSosSweAbstractSimpleType(sosSMLIo.getIoValue()); // namedValueProperty.getName().setTitle(sosSMLIo.getIoName()); observationProcess.addParameter(namedValueProperty); } } private List<ReferenceType> convertSMLInputsToObservationProcessInputs(final List<SmlIo<?>> inputs) { final List<ReferenceType> oPInputs = new ArrayList<ReferenceType>(inputs.size()); for (final SmlIo<?> sosSMLIo : inputs) { final ReferenceType refType = new ReferenceType(sosSMLIo.getIoValue().getDefinition()); refType.setTitle(sosSMLIo.getIoName()); oPInputs.add(refType); } return oPInputs; } private void convertSMLCapabilitiesToObservationProcessParameter(final ObservationProcess observationProcess, final List<SmlCapabilities> capabilities) { for (final SmlCapabilities capability : capabilities) { if (capability.isSetAbstractDataRecord() && capability.getDataRecord().isSetFields()) { for (final SweField field : capability.getDataRecord().getFields()) { final NamedValue<String> namedValueProperty = convertSMLFieldToNamedValuePair(field); if (namedValueProperty != null) { observationProcess.addParameter(namedValueProperty); } } } } } private NamedValue<String> convertSMLFieldToNamedValuePair(final SweField field) { if (field.getElement() instanceof SweAbstractSimpleType) { final NamedValue<String> namedValueProperty = getNamedValuePairForSosSweAbstractSimpleType((SweAbstractSimpleType) field.getElement(), field.getName().getValue()); namedValueProperty.getName().setTitle(field.getName().getValue()); return namedValueProperty; } return null; } private NamedValue<String> getNamedValuePairForSosSweAbstractSimpleType(final SweAbstractSimpleType<?> element, String name) { final NamedValue<String> namedValueProperty = new NamedValue<String>(); final ReferenceType refType; if (element.isSetDefinition()) { refType = new ReferenceType(element.getDefinition()); } else { refType = new ReferenceType(name); } namedValueProperty.setName(refType); if (element.isSetValue()) { namedValueProperty.setValue(new TextValue(element.getStringValue())); } return namedValueProperty; } }