/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ package org.geotoolkit.observation.xml.v200; import java.util.ArrayList; import java.util.List; import java.util.Objects; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.geotoolkit.gml.xml.v321.AbstractFeatureType; import org.geotoolkit.gml.xml.v321.AbstractTimeObjectType; import org.geotoolkit.gml.xml.v321.FeaturePropertyType; import org.geotoolkit.gml.xml.v321.ReferenceType; import org.geotoolkit.gml.xml.v321.TimeInstantPropertyType; import org.geotoolkit.gml.xml.v321.TimePeriodPropertyType; import org.geotoolkit.gml.xml.v321.TimePeriodType; import org.apache.sis.internal.jaxb.metadata.DQ_Element; import org.apache.sis.internal.jaxb.metadata.MD_Metadata; import org.apache.sis.metadata.iso.DefaultIdentifier; import org.geotoolkit.observation.xml.AbstractObservation; import org.geotoolkit.sampling.xml.v200.SFSamplingFeatureType; import org.geotoolkit.swe.xml.v200.DataArrayPropertyType; import org.apache.sis.util.ComparisonMode; import org.geotoolkit.gml.xml.v321.TimeInstantType; import org.geotoolkit.gml.xml.v321.TimePositionType; import org.geotoolkit.swe.xml.AnyScalar; import org.geotoolkit.swe.xml.DataArray; import org.geotoolkit.swe.xml.DataArrayProperty; import org.geotoolkit.swe.xml.DataComponentProperty; import org.geotoolkit.swe.xml.DataRecord; import org.geotoolkit.swe.xml.PhenomenonProperty; import org.geotoolkit.swe.xml.SimpleDataRecord; import org.opengis.metadata.Identifier; import org.opengis.metadata.Metadata; import org.opengis.metadata.quality.Element; import org.opengis.observation.Observation; import org.opengis.observation.Phenomenon; import org.opengis.observation.sampling.SamplingFeature; import org.opengis.temporal.Period; import org.opengis.temporal.TemporalGeometricPrimitive; import org.opengis.temporal.TemporalObject; /** * Generic observation, whose result is anyType The following properties * are inherited from AbstractFeatureType: * * * * <p>Java class for OM_ObservationType complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType name="OM_ObservationType"> * <complexContent> * <extension base="{http://www.opengis.net/gml/3.2}AbstractFeatureType"> * <sequence> * <group ref="{http://www.opengis.net/om/2.0}OM_CommonProperties"/> * <element ref="{http://www.opengis.net/om/2.0}result"/> * </sequence> * </extension> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "OM_ObservationType", propOrder = { "type", "metadata", "relatedObservation", "phenomenonTime", "resultTime", "validTime", "procedure", "parameter", "observedProperty", "featureOfInterest", "resultQuality", "result" }) @XmlSeeAlso({OMObservationType.InternalPhenomenon.class, OMObservationType.InternalCompositePhenomenon.class}) @XmlRootElement(name = "Observation") public class OMObservationType extends AbstractFeatureType implements AbstractObservation { private ReferenceType type; @XmlJavaTypeAdapter(MD_Metadata.class) private Metadata metadata; private List<ObservationContextPropertyType> relatedObservation; @XmlElement(required = true) private TimeObjectPropertyType phenomenonTime; @XmlElement(required = true) private TimeInstantPropertyType resultTime; private TimePeriodPropertyType validTime; @XmlElement(required = true, nillable = true) private OMProcessPropertyType procedure; private List<NamedValuePropertyType> parameter; @XmlElement(required = true, nillable = true) private ReferenceType observedProperty; @XmlElement(required = true, nillable = true) private FeaturePropertyType featureOfInterest; @XmlJavaTypeAdapter(DQ_Element.class) private List<Element> resultQuality; @XmlElement(required = true) private Object result; public OMObservationType() { } public OMObservationType(final String id, final String name, final String type, final AbstractTimeObjectType phenomenonTime, final String procedure, final String observedProperty, final FeaturePropertyType foi, final Object result) { super(id, name, null); this.type = new ReferenceType(type); this.phenomenonTime = new TimeObjectPropertyType(phenomenonTime); this.resultTime = new TimeInstantPropertyType(); if (procedure != null) { this.procedure = new OMProcessPropertyType(procedure); } this.observedProperty = new ReferenceType(observedProperty); this.featureOfInterest = foi; this.result = result; } /** * Build a clone of an observation * * @param observation observation to clone. */ public OMObservationType(final OMObservationType observation) { super(observation); this.type = observation.type; this.metadata = observation.metadata; if (observation.relatedObservation != null) { this.relatedObservation = new ArrayList<>(observation.relatedObservation); } this.phenomenonTime = observation.phenomenonTime; this.validTime = observation.validTime; this.resultTime = observation.resultTime; this.procedure = observation.procedure; if (observation.parameter != null) { this.parameter = new ArrayList<>(observation.parameter); } this.observedProperty = observation.observedProperty; this.featureOfInterest = observation.featureOfInterest; if (observation.resultQuality != null) { this.resultQuality = new ArrayList<>(observation.resultQuality); } if (observation.result instanceof DataArrayPropertyType) { this.result = new DataArrayPropertyType((DataArrayPropertyType)observation.result); } else { this.result = observation.result; } } @Override public String getDefinition() { return null; // not defined in SOS 2.0.0 } /** * Gets the value of the type property. * * @return * possible object is * {@link ReferenceType } * */ public ReferenceType getType() { return type; } /** * Sets the value of the type property. * * @param value * allowed object is * {@link ReferenceType } * */ public void setType(ReferenceType value) { this.type = value; } /** * Gets the value of the metadata property. * * @return * possible object is * {@link MDMetadataPropertyType } * */ @Override public Metadata getObservationMetadata() { return metadata; } /** * Sets the value of the metadata property. * * @param value * allowed object is * {@link MDMetadataPropertyType } * */ public void setObservationMetadata(Metadata value) { this.metadata = value; } /** * Gets the value of the relatedObservation property. * * Objects of the following type(s) are allowed in the list * {@link ObservationContextPropertyType } * * */ public List<ObservationContextPropertyType> getRelatedObservation() { if (relatedObservation == null) { relatedObservation = new ArrayList<>(); } return this.relatedObservation; } /** * Gets the value of the phenomenonTime property. * * @return * possible object is * {@link TimeObjectPropertyType } * */ public TimeObjectPropertyType getPhenomenonTime() { return phenomenonTime; } /** * Sets the value of the phenomenonTime property. * * @param value * allowed object is * {@link TimeObjectPropertyType } * */ public void setPhenomenonTime(TimeObjectPropertyType value) { this.phenomenonTime = value; } public void setPhenomenonTime(AbstractTimeObjectType value) { if (value != null) { this.phenomenonTime = new TimeObjectPropertyType(value); } } @Override public TemporalObject getSamplingTime() { if (phenomenonTime != null) { return phenomenonTime.getTimeObject(); } return null; } @Override public void emptySamplingTime() { this.phenomenonTime = null; } @Override public void setSamplingTimePeriod(final Period period) { if (period instanceof TimePeriodType) { this.phenomenonTime = new TimeObjectPropertyType((TimePeriodType)period); } else if (period != null) { final TimePeriodType pt = new TimePeriodType(period.getBeginning(), period.getEnding()); this.phenomenonTime = new TimeObjectPropertyType(pt); } } @Override public void extendSamplingTime(final String newEndBound) { if (newEndBound != null) { if (phenomenonTime != null && phenomenonTime.getTimeObject() instanceof TimePeriodType) { ((TimePeriodType)phenomenonTime.getTimeObject()).setEndPosition(new TimePositionType(newEndBound)); } else if (phenomenonTime != null && phenomenonTime.getTimeObject() instanceof TimeInstantType) { final TimeInstantType instant = (TimeInstantType) phenomenonTime.getTimeObject(); if (!newEndBound.equals(instant.getTimePosition().getValue())) { final TimePeriodType period = new TimePeriodType(instant.getId(), instant.getTimePosition().getValue(), newEndBound); phenomenonTime.setTimeObject(period); } } } } @Override public TemporalObject getProcedureTime() { throw new UnsupportedOperationException("Not supported yet."); } /** * Gets the value of the resultTime property. * * @return * possible object is * {@link TimeInstantPropertyType } * */ public TimeInstantPropertyType getResultTime() { return resultTime; } /** * Sets the value of the resultTime property. * * @param value * allowed object is * {@link TimeInstantPropertyType } * */ public void setResultTime(TimeInstantPropertyType value) { this.resultTime = value; } /** * Gets the value of the validTime property. * * @return * possible object is * {@link TimePeriodPropertyType } * */ public TimePeriodPropertyType getValidTime() { return validTime; } /** * Sets the value of the validTime property. * * @param value * allowed object is * {@link TimePeriodPropertyType } * */ public void setValidTime(TimePeriodPropertyType value) { this.validTime = value; } /** * Gets the value of the procedure property. * * @return * possible object is * {@link OMProcessPropertyType } * */ @Override public OMProcessPropertyType getProcedure() { return procedure; } /** * Sets the value of the procedure property. * * @param value * allowed object is * {@link OMProcessPropertyType } * */ public void setProcedure(final OMProcessPropertyType value) { this.procedure = value; } @Override public void setProcedure(final String procedureID) { if (procedureID != null) { this.procedure = new OMProcessPropertyType(procedureID); } } /** * Gets the value of the parameter property. * * Objects of the following type(s) are allowed in the list * {@link NamedValuePropertyType } * * */ public List<NamedValuePropertyType> getParameter() { if (parameter == null) { parameter = new ArrayList<>(); } return this.parameter; } @Override public Object getProcedureParameter() { if (parameter != null && !parameter.isEmpty()) { return parameter.get(0); } return null; } /** * Gets the value of the observedProperty property. * * @return * possible object is * {@link ReferenceType } * */ public ReferenceType getObservedPropertyRef() { return observedProperty; } @Override public Phenomenon getObservedProperty() { if (observedProperty != null) { if (result instanceof DataArrayProperty) { final List<String> fields = getFieldsFromResult((DataArrayProperty) result); final List<InternalPhenomenon> phenomenons = new ArrayList<>(); for (String field : fields) { phenomenons.add(new InternalPhenomenon(field)); } return new InternalCompositePhenomenon(observedProperty.getHref(), phenomenons); } return new InternalPhenomenon(observedProperty.getHref()); } return null; } /** * Sets the value of the observedProperty property. * * @param value * allowed object is * {@link ReferenceType } * */ public void setObservedProperty(ReferenceType value) { this.observedProperty = value; } @Override public PhenomenonProperty getPropertyObservedProperty() { if (observedProperty != null) { final Phenomenon phen = getObservedProperty(); return new InternalPhenomenonProperty(observedProperty, (org.geotoolkit.swe.xml.Phenomenon) phen); } return null; } /** * Gets the value of the featureOfInterest property. * * @return * possible object is * {@link FeaturePropertyType } * */ @Override public FeaturePropertyType getPropertyFeatureOfInterest() { return featureOfInterest; } @Override public SamplingFeature getFeatureOfInterest() { if (featureOfInterest != null) { if (featureOfInterest.getAbstractFeature() instanceof SamplingFeature) { return (SFSamplingFeatureType)featureOfInterest.getAbstractFeature(); } else { LOGGER.warning("information lost getFeatureOfInterest() is deprecated use getPropertyFeatureOfInterest() instead"); } } return null; } /** * Sets the value of the featureOfInterest property. * * @param value * allowed object is * {@link FeaturePropertyType } * */ public void setFeatureOfInterest(FeaturePropertyType value) { this.featureOfInterest = value; } /** * Gets the value of the resultQuality property. * * Objects of the following type(s) are allowed in the list * {@link DQElementPropertyType } * */ public List<Element> getResultQuality() { if (resultQuality == null) { resultQuality = new ArrayList<Element>(); } return this.resultQuality; } @Override public Element getQuality() { if (resultQuality != null && !resultQuality.isEmpty()) { return resultQuality.get(0); } return null; } /** * Gets the value of the result property. * * @return * possible object is * {@link Object } * */ @Override public Object getResult() { return result; } /** * Sets the value of the result property. * * @param value * allowed object is * {@link Object } * */ @Override public void setResult(final Object value) { this.result = value; } @Override public boolean matchTemplate(final Observation abstractTemplate) { return true; } @Override public OMObservationType getTemporaryTemplate(final String temporaryName, final TemporalGeometricPrimitive time) { throw new UnsupportedOperationException("Not supported yet."); } private List<String> getFieldsFromResult(final DataArrayProperty arrayProp) { final List<String> fields = new ArrayList<>(); if (arrayProp.getDataArray() != null) { final DataArray array = arrayProp.getDataArray(); if (array.getPropertyElementType().getAbstractRecord() instanceof DataRecord) { final DataRecord record = (DataRecord)array.getPropertyElementType().getAbstractRecord(); for (DataComponentProperty field : record.getField()) { fields.add(field.getName()); } } else if (array.getPropertyElementType().getAbstractRecord() instanceof SimpleDataRecord) { final SimpleDataRecord record = (SimpleDataRecord)array.getPropertyElementType().getAbstractRecord(); for (AnyScalar field : record.getField()) { fields.add(field.getName()); } } } return fields; } @Override public String toString() { final StringBuilder sb = new StringBuilder(super.toString()); if (featureOfInterest != null) { sb.append("featureOfInterest:").append(featureOfInterest).append('\n'); } if (metadata != null) { sb.append("metadata:").append(metadata).append('\n'); } if (observedProperty != null) { sb.append("observedProperty:").append(observedProperty).append('\n'); } if (parameter != null) { sb.append("parameter:\n"); for (NamedValuePropertyType p: parameter) { sb.append(p).append('\n'); } } if (phenomenonTime != null) { sb.append("phenomenonTime:").append(phenomenonTime).append('\n'); } if (procedure != null) { sb.append("procedure:").append(procedure).append('\n'); } if (relatedObservation != null) { sb.append("relatedObservation:\n"); for (ObservationContextPropertyType p: relatedObservation) { sb.append(p).append('\n'); } } if (result != null) { sb.append("result:").append(result).append('\n'); } if (resultQuality != null) { sb.append("resultQuality:\n"); for (Element p: resultQuality) { sb.append(p).append('\n'); } } if (resultTime != null) { sb.append("resultTime:").append(resultTime).append('\n'); } if (type != null) { sb.append("type:").append(type).append('\n'); } if (validTime != null) { sb.append("validTime:").append(validTime).append('\n'); } return sb.toString(); } /** * Vérifie que cette station est identique à l'objet spécifié */ @Override public boolean equals(final Object object, final ComparisonMode mode) { if (object == this) { return true; } if (object instanceof OMObservationType && super.equals(object, mode)) { final OMObservationType that = (OMObservationType) object; return Objects.equals(this.featureOfInterest, that.featureOfInterest) && Objects.equals(this.metadata, that.metadata) && Objects.equals(this.observedProperty, that.observedProperty) && Objects.equals(this.parameter, that.parameter) && Objects.equals(this.phenomenonTime, that.phenomenonTime) && Objects.equals(this.procedure, that.procedure) && Objects.equals(this.relatedObservation, that.relatedObservation) && Objects.equals(this.result, that.result) && Objects.equals(this.resultQuality, that.resultQuality) && Objects.equals(this.resultTime, that.resultTime) && Objects.equals(this.type, that.type) && Objects.equals(this.validTime, that.validTime); } return false; } @Override public int hashCode() { int hash = 7; hash = 37 * hash + super.hashCode(); hash = 37 * hash + (this.featureOfInterest != null ? this.featureOfInterest.hashCode() : 0); hash = 37 * hash + (this.metadata != null ? this.metadata.hashCode() : 0); hash = 37 * hash + (this.observedProperty != null ? this.observedProperty.hashCode() : 0); hash = 37 * hash + (this.parameter != null ? this.parameter.hashCode() : 0); hash = 37 * hash + (this.phenomenonTime != null ? this.phenomenonTime.hashCode() : 0); hash = 37 * hash + (this.procedure != null ? this.procedure.hashCode() : 0); hash = 37 * hash + (this.relatedObservation != null ? this.relatedObservation.hashCode() : 0); hash = 37 * hash + (this.result != null ? this.result.hashCode() : 0); hash = 37 * hash + (this.resultQuality != null ? this.resultQuality.hashCode() : 0); hash = 37 * hash + (this.resultTime != null ? this.resultTime.hashCode() : 0); hash = 37 * hash + (this.type != null ? this.type.hashCode() : 0); hash = 37 * hash + (this.validTime != null ? this.validTime.hashCode() : 0); return hash; } @XmlRootElement public static class InternalPhenomenon implements org.geotoolkit.swe.xml.Phenomenon { private final String name; public InternalPhenomenon() { this.name = null; } public InternalPhenomenon(final String name) { this.name = name; } @Override public Identifier getName() { return new DefaultIdentifier(name); } @Override public boolean equals(final Object obj) { if (obj instanceof Phenomenon) { final org.geotoolkit.swe.xml.Phenomenon that = (org.geotoolkit.swe.xml.Phenomenon) obj; return Objects.equals(this.getName(), that.getName()); } return false; } @Override public String toString() { return "[Anonymous Phenomenon] name:" + getName(); } @Override public int hashCode() { int hash = 7; hash = 7 * hash + (this.getName() != null ? this.getName().hashCode() : 0); return hash; } } @XmlRootElement public static class InternalCompositePhenomenon implements org.geotoolkit.swe.xml.CompositePhenomenon { private final String name; private final List<InternalPhenomenon> phenomenons; public InternalCompositePhenomenon() { this.name = null; this.phenomenons = new ArrayList<>(); } public InternalCompositePhenomenon(final String name, List<InternalPhenomenon> phenomenons) { this.name = name; this.phenomenons = phenomenons; } @Override public Identifier getName() { return new DefaultIdentifier(name); } @Override public List<? extends PhenomenonProperty> getRealComponent() { final List<InternalPhenomenonProperty> phenProps = new ArrayList<>(); for (InternalPhenomenon phen : phenomenons) { phenProps.add(new InternalPhenomenonProperty(new ReferenceType(phen.name), phen)); } return phenProps; } @Override public List<? extends Phenomenon> getComponent() { return phenomenons; } @Override public Phenomenon getBase() { return null; } @Override public int getDimension() { return phenomenons.size(); } @Override public boolean equals(final Object obj) { if (obj instanceof Phenomenon) { final org.geotoolkit.swe.xml.Phenomenon that = (org.geotoolkit.swe.xml.Phenomenon) obj; return Objects.equals(this.getName(), that.getName()); } return false; } @Override public String toString() { return "[Anonymous composite Phenomenon] name:" + getName(); } @Override public int hashCode() { int hash = 7; hash = 7 * hash + (this.getName() != null ? this.getName().hashCode() : 0); return hash; } } @XmlRootElement public static class InternalPhenomenonProperty implements org.geotoolkit.swe.xml.PhenomenonProperty { private final String href; private final org.geotoolkit.swe.xml.Phenomenon phenomenon; public InternalPhenomenonProperty() { this.href = null; this.phenomenon = null; } public InternalPhenomenonProperty(final ReferenceType phenRef, final org.geotoolkit.swe.xml.Phenomenon phenomenon) { this.href = phenRef.getHref(); this.phenomenon = phenomenon; } @Override public String getHref() { return href; } @Override public void setToHref() { // already in href mode } @Override public org.geotoolkit.swe.xml.Phenomenon getPhenomenon() { return phenomenon; } @Override public boolean equals(final Object obj) { if (obj instanceof org.geotoolkit.swe.xml.PhenomenonProperty) { final org.geotoolkit.swe.xml.PhenomenonProperty that = (org.geotoolkit.swe.xml.PhenomenonProperty) obj; return Objects.equals(this.href, that.getHref()); } return false; } @Override public String toString() { return "[Anonymous Phenomenon Property] href:" + getHref(); } @Override public int hashCode() { int hash = 7; hash = 7 * hash + (this.getHref() != null ? this.getHref().hashCode() : 0); return hash; } } }