/** * 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.encode.streaming; import java.util.List; import javax.xml.stream.XMLStreamException; import org.apache.commons.lang.StringEscapeUtils; import org.n52.sos.encode.EncodingValues; import org.n52.sos.ogc.gml.GmlConstants; import org.n52.sos.ogc.om.MultiObservationValues; import org.n52.sos.ogc.om.OmConstants; import org.n52.sos.ogc.om.OmObservableProperty; import org.n52.sos.ogc.om.OmObservation; import org.n52.sos.ogc.om.SingleObservationValue; import org.n52.sos.ogc.om.StreamingValue; import org.n52.sos.ogc.om.TimeValuePair; import org.n52.sos.ogc.om.values.CountValue; import org.n52.sos.ogc.om.values.QuantityValue; import org.n52.sos.ogc.om.values.TVPValue; import org.n52.sos.ogc.om.values.TextValue; import org.n52.sos.ogc.om.values.Value; import org.n52.sos.ogc.ows.OwsExceptionReport; import org.n52.sos.ogc.wml.WaterMLConstants; import org.n52.sos.util.StringHelper; import org.n52.sos.w3c.W3CConstants; /** * Implementation of {@link AbstractOmV20XmlStreamWriter} to write WaterML 2.0 * encoded {@link OmObservation}s to stream * * @author Carsten Hollmann <c.hollmann@52north.org> * @since 4.1.0 * */ public class WmlTVPEncoderv20XmlStreamWriter extends AbstractOmV20XmlStreamWriter { /** * constructor */ public WmlTVPEncoderv20XmlStreamWriter() { super(); } /** * constructor * * @param observation * {@link OmObservation} to write to stream */ public WmlTVPEncoderv20XmlStreamWriter(OmObservation observation) { super(observation); } @Override protected void writeResult(OmObservation observation, EncodingValues encodingValues) throws XMLStreamException, OwsExceptionReport { start(OmConstants.QN_OM_20_RESULT); namespace(WaterMLConstants.NS_WML_20_PREFIX, WaterMLConstants.NS_WML_20); writeNewLine(); start(WaterMLConstants.QN_MEASUREMENT_TIMESERIES); attr(GmlConstants.QN_ID_32, "timeseries." + observation.getObservationID()); writeNewLine(); writeMeasurementTimeseriesMetadata(observation.getPhenomenonTime().getGmlId()); writeNewLine(); if (observation.getValue() instanceof SingleObservationValue) { SingleObservationValue<?> observationValue = (SingleObservationValue<?>) observation.getValue(); writeDefaultPointMetadata(observationValue.getValue().getUnit()); writeNewLine(); String time = getTimeString(observationValue.getPhenomenonTime()); writePoint(time, getValue(observation.getValue().getValue())); writeNewLine(); close(); } else if (observation.getValue() instanceof MultiObservationValues) { MultiObservationValues<?> observationValue = (MultiObservationValues<?>) observation.getValue(); writeDefaultPointMetadata(observationValue.getValue().getUnit()); writeNewLine(); TVPValue tvpValue = (TVPValue) observationValue.getValue(); List<TimeValuePair> timeValuePairs = tvpValue.getValue(); for (TimeValuePair timeValuePair : timeValuePairs) { writePoint(getTimeString(timeValuePair.getTime()), getValue(timeValuePair.getValue())); writeNewLine(); } close(); } else if (observation.getValue() instanceof StreamingValue) { StreamingValue observationValue = (StreamingValue) observation.getValue(); if (observationValue.isSetUnit()) { writeDefaultPointMetadata(observationValue.getUnit()); } else if (observation.getObservationConstellation().getObservableProperty() instanceof OmObservableProperty && ((OmObservableProperty) observation.getObservationConstellation().getObservableProperty()) .isSetUnit()) { writeDefaultPointMetadata(((OmObservableProperty) observation.getObservationConstellation().getObservableProperty()) .getUnit()); } writeNewLine(); while (observationValue.hasNextValue()) { TimeValuePair timeValuePair = observationValue.nextValue(); if (timeValuePair != null) { writePoint(getTimeString(timeValuePair.getTime()), getValue(timeValuePair.getValue())); writeNewLine(); } } close(); } else { super.writeResult(observation, encodingValues); } } /** * Close written wml:MeasurementTimeseries and om:result tags * * @throws XMLStreamException * If an error occurs when writing to stream */ private void close() throws XMLStreamException { indent--; end(WaterMLConstants.QN_MEASUREMENT_TIMESERIES); writeNewLine(); end(OmConstants.QN_OM_20_RESULT); indent++; } /** * Write timeseries metadata to stream * * @param id * Observation id * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeMeasurementTimeseriesMetadata(String id) throws XMLStreamException { start(WaterMLConstants.QN_METADATA); writeNewLine(); start(WaterMLConstants.QN_MEASUREMENT_TIMESERIES_METADATA); writeNewLine(); empty(WaterMLConstants.QN_TEMPORAL_EXTENT); addXlinkHrefAttr("#" + id); writeNewLine(); indent--; end(WaterMLConstants.QN_MEASUREMENT_TIMESERIES_METADATA); writeNewLine(); end(WaterMLConstants.QN_METADATA); indent++; } /** * Write wml:defaultPointMetadata to stream * * @param unit * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeDefaultPointMetadata(String unit) throws XMLStreamException { start(WaterMLConstants.QN_DEFAULT_POINT_METADATA); writeNewLine(); start(WaterMLConstants.QN_DEFAULT_TVP_MEASUREMENT_METADATA); writeNewLine(); writeUOM(unit); writeNewLine(); writeInterpolationType(); writeNewLine(); indent--; end(WaterMLConstants.QN_DEFAULT_TVP_MEASUREMENT_METADATA); writeNewLine(); end(WaterMLConstants.QN_DEFAULT_POINT_METADATA); indent++; } /** * Write UOM attribute to stream * * @param code * UOM code * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeUOM(String code) throws XMLStreamException { if (StringHelper.isNotEmpty(code)) { empty(WaterMLConstants.UOM); attr("code", code); } } /** * Write wml:interpolationType to stream * * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeInterpolationType() throws XMLStreamException { empty(WaterMLConstants.QN_INTERPOLATION_TYPE); addXlinkHrefAttr("http://www.opengis.net/def/timeseriesType/WaterML/2.0/continuous"); addXlinkTitleAttr("Instantaneous"); } /** * Get the {@link String} representation of {@link Value} * * @param value * {@link Value} to get {@link String} representation from * @return {@link String} representation of {@link Value} */ private String getValue(Value<?> value) { if (value instanceof QuantityValue) { QuantityValue quantityValue = (QuantityValue) value; return Double.toString(quantityValue.getValue().doubleValue()); } else if (value instanceof CountValue) { CountValue countValue = (CountValue) value; return Integer.toString(countValue.getValue().intValue()); } else if (value instanceof TextValue) { TextValue textValue = (TextValue) value; String nonXmlEscapedText = textValue.getValue(); return StringEscapeUtils.escapeXml(nonXmlEscapedText); } return null; } /** * Write wml:point to stream * * @param time * time as {@link String} * @param value * value as {@link String} * @throws XMLStreamException * If an error occurs when writing to stream */ private void writePoint(String time, String value) throws XMLStreamException { if (StringHelper.isNotEmpty(time)) { start(WaterMLConstants.QN_POINT); writeNewLine(); writeMeasurementTVP(time, value); writeNewLine(); indent--; end(WaterMLConstants.QN_POINT); indent++; } } /** * Write wml:MeasurementTVP to stream * * @param time * time as {@link String} * @param value * value as {@link String} * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeMeasurementTVP(String time, String value) throws XMLStreamException { start(WaterMLConstants.QN_MEASUREMENT_TVP); writeNewLine(); writeTime(time); writeNewLine(); writeValue(value); writeNewLine(); indent--; end(WaterMLConstants.QN_MEASUREMENT_TVP); indent++; } /** * Write wml:time to stream * * @param time * time to write * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeTime(String time) throws XMLStreamException { start(WaterMLConstants.QN_TIME); chars(time); endInline(WaterMLConstants.QN_TIME); } /** * Write wml:value to stream * * @param value * value to write * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeValue(String value) throws XMLStreamException { if (StringHelper.isNotEmpty(value)) { start(WaterMLConstants.QN_VALUE); chars(value); endInline(WaterMLConstants.QN_VALUE); } else { empty(WaterMLConstants.QN_VALUE); attr(W3CConstants.QN_XSI_NIL, "true"); writeValueMetadata(); } } /** * Write missing value metadata to stream * * @throws XMLStreamException * If an error occurs when writing to stream */ private void writeValueMetadata() throws XMLStreamException { start(WaterMLConstants.QN_METADATA); start(WaterMLConstants.QN_TVP_MEASUREMENT_METADATA); empty(WaterMLConstants.QN_NIL_REASON); addXlinkHrefAttr("missing"); endInline(WaterMLConstants.QN_TVP_MEASUREMENT_METADATA); endInline(WaterMLConstants.QN_METADATA); } }