/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2008 - 2009, 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.v100; // jaxb import import java.util.Objects; import java.util.logging.Logger; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; import org.apache.sis.metadata.iso.DefaultIdentifier; // openGis dependencies import org.geotoolkit.gml.xml.v311.*; import org.opengis.metadata.quality.Element; import org.opengis.metadata.Metadata; import org.opengis.observation.Observation; import org.opengis.observation.Phenomenon; import org.opengis.observation.sampling.SamplingFeature; // GeotoolKit dependencies import org.geotoolkit.internal.sql.table.Entry; import org.geotoolkit.sampling.xml.v100.SamplingFeatureType; import org.geotoolkit.sampling.xml.v100.SamplingPointType; import org.geotoolkit.swe.xml.v101.AnyResultType; import org.geotoolkit.swe.xml.v101.DataArrayType; import org.geotoolkit.swe.xml.v101.DataArrayPropertyType; import org.geotoolkit.swe.xml.v101.PhenomenonType; import org.geotoolkit.swe.xml.v101.PhenomenonPropertyType; import org.geotoolkit.swe.xml.v101.TimeGeometricPrimitivePropertyType; import org.apache.sis.metadata.iso.DefaultMetadata; import org.geotoolkit.observation.xml.AbstractObservation; import org.geotoolkit.sampling.xml.v100.SamplingCurveType; import org.geotoolkit.sampling.xml.v100.SamplingSolidType; import org.geotoolkit.sampling.xml.v100.SamplingSurfaceType; import org.apache.sis.util.logging.Logging; import org.opengis.metadata.Identifier; import org.opengis.temporal.Period; import org.opengis.temporal.TemporalGeometricPrimitive; /** * Implémentation d'une entrée représentant une {@linkplain Observation observation}. * * @version $Id: ObservationType.java 1559 2009-04-23 14:42:42Z glegal $ * @author Martin Desruisseaux * @author Antoine Hnawia * @author Guilhem Legal * @module */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Observation", propOrder = { "name", "samplingTime", "procedure", "procedureParameter", "procedureTime", "observedProperty", "featureOfInterest", "result" }) @XmlRootElement(name = "Observation") @XmlSeeAlso({ MeasurementType.class}) public class ObservationType implements Entry, AbstractObservation { /** * Pour compatibilités entre les enregistrements binaires de différentes versions. */ private static final long serialVersionUID = 3269639171560208276L; protected static final org.geotoolkit.sampling.xml.v100.ObjectFactory SAMPLING_FACTORY = new org.geotoolkit.sampling.xml.v100.ObjectFactory(); protected static final org.geotoolkit.gml.xml.v311.ObjectFactory GML_FACTORY = new org.geotoolkit.gml.xml.v311.ObjectFactory(); protected static final ObjectFactory OM_FACTORY = new ObjectFactory(); /** * A logger (debugging purpose) */ protected static final Logger LOGGER = Logging.getLogger("org.geotoolkit.observation.xml.v100"); /** *The observation name */ @XmlElement(namespace = "http://www.opengis.net/gml") private String name; /** * La description de l'observation */ @XmlTransient private String definition; /** * La station à laquelle a été pris cet échantillon. */ @XmlElement(required = true) private FeaturePropertyType featureOfInterest; /** * Référence vers le {@linkplain Phenomenon phénomène} observé. */ @XmlElement(required = true) private PhenomenonPropertyType observedProperty; /** * Référence vers la {@linkplain Procedure procédure} associée à cet observable. */ @XmlElement(required = true) private ProcessType procedure; /** * Référence vers la {@linkplain Distribution distribution} associée à cet observable. @XmlTransient private Distribution distribution;*/ /** * La qualité de la donnée. Peut être nul si cette information n'est pas disponible. */ @XmlTransient private ElementType resultQuality; /** * le resultat de l'observation de n'importe quel type */ @XmlElementRef(name= "result", namespace="http://www.opengis.net/om/1.0") private JAXBElement<Object> result; /** * */ @XmlElement private TimeGeometricPrimitivePropertyType samplingTime; /** * */ @XmlTransient private DefaultMetadata observationMetadata; /** * */ @XmlElement private TimeGeometricPrimitivePropertyType procedureTime; /** * */ @XmlElement private Object procedureParameter; /** * Build An empty observation (used for JAXB serialization) */ public ObservationType() {} /** * Build a clone of an observation */ public ObservationType(final ObservationType observation) { this.definition = observation.definition; this.featureOfInterest = observation.featureOfInterest; this.name = observation.name; this.observationMetadata = observation.observationMetadata; this.observedProperty = observation.observedProperty; this.procedure = observation.procedure; this.procedureParameter = observation.procedureParameter; this.procedureTime = observation.procedureTime; if (observation.result != null && observation.result.getValue() instanceof DataArrayPropertyType) { this.result = OM_FACTORY.createResult(new DataArrayPropertyType((DataArrayPropertyType)observation.result.getValue())); } else { this.result = observation.result; } this.resultQuality = observation.resultQuality; this.samplingTime = observation.samplingTime; } /** * Construit une observation. * * * @param featureOfInterest La station d'observation (par exemple une position de pêche). * @param observedProperty Le phénomène observé. * @param procedure La procédure associée. * @param resultQuality La qualité de la donnée, ou {@code null} si inconnue. */ public ObservationType(final String name, final String definition, final SamplingFeatureType featureOfInterest, final PhenomenonType observedProperty, final ProcessType procedure, final ElementType quality, final Object result, final AbstractTimeGeometricPrimitiveType samplingTime, final DefaultMetadata observationMetadata, final AbstractTimeGeometricPrimitiveType procedureTime, final Object procedureParameter) { this.name = name; this.definition = definition; if (featureOfInterest instanceof SamplingPointType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingPoint((SamplingPointType)featureOfInterest)); } else if (featureOfInterest instanceof SamplingCurveType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingCurve((SamplingCurveType)featureOfInterest)); } else if (featureOfInterest instanceof SamplingSolidType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingSolid((SamplingSolidType)featureOfInterest)); } else if (featureOfInterest instanceof SamplingSurfaceType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingSurface((SamplingSurfaceType)featureOfInterest)); } if (observedProperty != null) { this.observedProperty = new PhenomenonPropertyType(observedProperty); } this.procedure = procedure; this.resultQuality = quality; this.result = OM_FACTORY.createResult(result); this.observationMetadata = observationMetadata; this.procedureParameter = procedureParameter; this.samplingTime = new TimeGeometricPrimitivePropertyType(samplingTime); this.procedureTime = new TimeGeometricPrimitivePropertyType(procedureTime); } /** * Build a new observation. * * * @param featureOfInterest The observation station. * @param observedProperty The observed phenomenon. * @param procedure The associated procedure. */ public ObservationType(final String name, final String definition, final SamplingFeatureType featureOfInterest, final PhenomenonType observedProperty, final String procedure, final Object result, final AbstractTimeGeometricPrimitiveType samplingTime) { this.name = name; this.definition = definition; if (featureOfInterest instanceof SamplingPointType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingPoint((SamplingPointType)featureOfInterest)); } else if (featureOfInterest instanceof SamplingCurveType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingCurve((SamplingCurveType)featureOfInterest)); } else if (featureOfInterest instanceof SamplingSolidType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingSolid((SamplingSolidType)featureOfInterest)); } else if (featureOfInterest instanceof SamplingSurfaceType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingSurface((SamplingSurfaceType)featureOfInterest)); } if (observedProperty != null) { this.observedProperty = new PhenomenonPropertyType(observedProperty); } if (procedure != null) { this.procedure = new ProcessType(procedure); } this.resultQuality = null; this.result = OM_FACTORY.createResult(result); this.observationMetadata = null; this.procedureTime = null; this.procedureParameter = null; this.samplingTime = new TimeGeometricPrimitivePropertyType(samplingTime); } /** * Build a new observation. * * * @param featureOfInterest The observation station. * @param observedProperty The observed phenomenon. * @param procedure The associated procedure. */ public ObservationType(final String name, final String definition, final FeaturePropertyType featureOfInterest, final PhenomenonPropertyType observedProperty, final String procedure, final Object result, final AbstractTimeGeometricPrimitiveType samplingTime) { this.name = name; this.definition = definition; this.featureOfInterest = featureOfInterest; this.observedProperty = observedProperty; if (procedure != null) { this.procedure = new ProcessType(procedure); } this.resultQuality = null; this.result = OM_FACTORY.createResult(result); this.observationMetadata = null; this.procedureTime = null; this.procedureParameter = null; this.samplingTime = new TimeGeometricPrimitivePropertyType(samplingTime); } /** * Build a new observation. * * * @param featureOfInterest The observation station. * @param observedProperty The observed phenomenon. * @param procedure The associated procedure. */ public ObservationType(final String name, final String definition, final FeaturePropertyType featureOfInterest, final PhenomenonType observedProperty, final String procedure, final Object result, final AbstractTimeGeometricPrimitiveType samplingTime) { this(name, definition, featureOfInterest, new PhenomenonPropertyType(observedProperty), procedure, result, samplingTime); } /** * Construit un nouveau template temporaire d'observation a partir d'un template fournit en argument. * On y rajoute un samplingTime et un id temporaire. */ @Override public ObservationType getTemporaryTemplate(final String temporaryName, TemporalGeometricPrimitive time) { if (time == null) { TimePositionType begin = new TimePositionType("1900-01-01T00:00:00"); time = new TimePeriodType(begin); } //debugging purpose Object res = null; if (this.result != null) { res = this.result.getValue(); if (this.result.getValue() instanceof DataArrayPropertyType) { DataArrayType d = ((DataArrayPropertyType)this.result.getValue()).getDataArray(); d.setElementCount(0); d.setValues(""); } } return new ObservationType(temporaryName, this.definition, this.featureOfInterest, this.observedProperty, this.procedure.getHref(), res, (AbstractTimeGeometricPrimitiveType)time); } /** */ @Override public void setName(final String name) { this.name = name; } @Override public Identifier getName() { return new DefaultIdentifier(this.name); } @Override public String getIdentifier() { return name; } /** * {@inheritDoc} */ @Override @Deprecated public SamplingFeatureType getFeatureOfInterest() { if (featureOfInterest != null) { if (featureOfInterest.getAbstractFeature() instanceof SamplingFeature) { return (SamplingFeatureType)featureOfInterest.getAbstractFeature(); } else { LOGGER.warning("information lost getFeatureOfInterest() is deprecated use getPropertyFeatureOfInterest() instead"); } } return null; } public void setFeatureOfInterest(final AbstractFeatureType featureOfInterest) { if (featureOfInterest != null) { if (featureOfInterest instanceof SamplingPointType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingPoint((SamplingPointType) featureOfInterest)); } else if (featureOfInterest instanceof SamplingCurveType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingCurve((SamplingCurveType) featureOfInterest)); } else if (featureOfInterest instanceof SamplingSolidType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingSolid((SamplingSolidType) featureOfInterest)); } else if (featureOfInterest instanceof SamplingSurfaceType) { this.featureOfInterest = new FeaturePropertyType(SAMPLING_FACTORY.createSamplingSurface((SamplingSurfaceType) featureOfInterest)); } else if (featureOfInterest instanceof FeatureCollectionType) { this.featureOfInterest = new FeaturePropertyType(GML_FACTORY.createFeatureCollection((FeatureCollectionType) featureOfInterest)); } } } @Override public FeaturePropertyType getPropertyFeatureOfInterest(){ return featureOfInterest; } public void setPropertyFeatureOfInterest(final FeaturePropertyType featureOfInterest){ this.featureOfInterest = featureOfInterest; } /** * {@inheritDoc} */ @Override public PhenomenonType getObservedProperty() { if (observedProperty != null) { return observedProperty.getPhenomenon(); } else { return null; } } /** * {@inheritDoc} */ public void setObservedProperty(final PhenomenonType observedProperty) { if (observedProperty != null) { this.observedProperty = new PhenomenonPropertyType(observedProperty); } } public void setPropertyObservedProperty(final PhenomenonPropertyType observedProperty) { this.observedProperty = observedProperty; } @Override public PhenomenonPropertyType getPropertyObservedProperty() { return observedProperty; } /** * {@inheritDoc} */ @Override public ProcessType getProcedure() { return procedure; } @Override public void setProcedure(final String procedureID) { if (procedureID != null) { this.procedure = new ProcessType(procedureID); } } /** * fixe le capteur qui a effectué cette observation. */ public void setProcedure(final ProcessType process) { this.procedure = process; } /** * {@inheritDoc} */ @Override public Element getQuality() { return resultQuality; } /** * {@inheritDoc} */ @Override public Object getResult() { if (result != null) { return result.getValue(); } return null; } /** * Set the result of the observation. */ @Override public void setResult(final Object result) { if (!(result instanceof ReferenceType) && !(result instanceof AnyResultType) && !(result instanceof DataArrayPropertyType) && !(result instanceof MeasureType)) { throw new IllegalArgumentException("this type " + result.getClass().getSimpleName() + " is not allowed in result"); } this.result = OM_FACTORY.createResult(result); } /** * Update the result of the obervation by setting the specified String value and numbers of result. * and the last date of measure. * * @param values A datablock of values. * @param nbResult the number of result in the datablock. * @param lastDate The last date of measure. If this parameter is null, the last date will be kept. * @throws IllegalArgumentException if the resulat of the observation is not a DataArray. */ public void updateDataArrayResult(final String values, final int nbResult, final String lastDate) { if (lastDate != null) { extendSamplingTime(lastDate); } if (getResult() instanceof DataArrayPropertyType) { DataArrayType array = ((DataArrayPropertyType)getResult()).getDataArray(); array.updateArray(values, nbResult); } else { throw new IllegalArgumentException("The result is not a data array."); } } /** * {@inheritDoc} */ @Override public AbstractTimeGeometricPrimitiveType getSamplingTime() { if (samplingTime != null) { return samplingTime.getTimeGeometricPrimitive(); } return null; } @Override public void emptySamplingTime() { this.samplingTime = null; } /** * {@inheritDoc} */ public void setSamplingTime(final AbstractTimeGeometricPrimitiveType value) { this.samplingTime = new TimeGeometricPrimitivePropertyType(value); } /** * {@inheritDoc} */ @Override public void extendSamplingTime(final String newEndBound) { if (newEndBound != null) { if (samplingTime != null && samplingTime.getTimeGeometricPrimitive() instanceof TimePeriodType) { ((TimePeriodType)samplingTime.getTimeGeometricPrimitive()).setEndPosition(new TimePositionType(newEndBound)); } else if (samplingTime != null && samplingTime.getTimeGeometricPrimitive() instanceof TimeInstantType) { final TimeInstantType instant = (TimeInstantType) samplingTime.getTimeGeometricPrimitive(); if (!newEndBound.equals(instant.getTimePosition().getValue())) { final TimePeriodType period = new TimePeriodType(instant.getId(), instant.getTimePosition().getValue(), newEndBound); samplingTime.setTimeGeometricPrimitive(period); } } } } @Override public void setSamplingTimePeriod(final Period period) { if (period instanceof TimePeriodType) { this.samplingTime = new TimeGeometricPrimitivePropertyType((TimePeriodType)period); } else if (period != null) { final TimePeriodType pt = new TimePeriodType(period.getBeginning(), period.getEnding()); this.samplingTime = new TimeGeometricPrimitivePropertyType(pt); } } /** * {@inheritDoc} */ @Override public Metadata getObservationMetadata() { return observationMetadata; } /** * {@inheritDoc} */ @Override public AbstractTimeGeometricPrimitiveType getProcedureTime() { if (procedureTime != null) { return procedureTime.getTimeGeometricPrimitive(); } return null; } /** * {@inheritDoc} */ @Override public Object getProcedureParameter() { return procedureParameter; } /** * {@inheritDoc} */ @Override public String getDefinition() { return definition; } /** * Return true if the observation match the specified template. * @param abstractTemplate */ @Override public boolean matchTemplate(final Observation abstractTemplate) { if (abstractTemplate == null) { throw new IllegalArgumentException("cannot match null template"); } else if (!(abstractTemplate instanceof ObservationType)) { throw new IllegalArgumentException("Unexpected object version"); } final ObservationType template = (ObservationType) abstractTemplate; final boolean obsProperty; if (this.observedProperty != null && template.observedProperty != null) { obsProperty = Objects.equals(this.observedProperty.getPhenomenon(), template.observedProperty.getPhenomenon()); if (!obsProperty) { LOGGER.info("\ncomparing observed property:\nTHIS => " + this.observedProperty.getPhenomenon() + "\nTEMPLATE => " + template.observedProperty.getPhenomenon() + '\n'); } } else { obsProperty = this.observedProperty == null && template.observedProperty == null; } final boolean obsFoi; if (this.featureOfInterest != null && template.featureOfInterest != null) { obsFoi = Objects.equals(this.featureOfInterest.getAbstractFeature(), template.featureOfInterest.getAbstractFeature()); if (!obsFoi) { LOGGER.info("\ncomparing feature of interest:\nTHIS => "+ this.featureOfInterest.getAbstractFeature() + "\nTEMPLATE => " + template.featureOfInterest.getAbstractFeature() + '\n'); } } else { obsFoi = this.featureOfInterest == null && template.featureOfInterest == null; } boolean match = obsFoi && Objects.equals(this.procedure, template.procedure) && Objects.equals(this.resultQuality, template.resultQuality) && Objects.equals(this.observationMetadata, template.observationMetadata) && Objects.equals(this.procedureTime, template.procedureTime) && Objects.equals(this.procedureParameter, template.procedureParameter) && obsProperty; if (!match) { LOGGER.severe("error matching template report:" + "\nFOI =>" + obsFoi + "\nPROC =>" + Objects.equals(this.procedure, template.procedure) + "\nQUAL =>" + Objects.equals(this.resultQuality, template.resultQuality) + "\nMETA =>" + Objects.equals(this.observationMetadata, template.observationMetadata) + "\nPTI =>" + Objects.equals(this.procedureTime, template.procedureTime) + "\nPPAM =>" + Objects.equals(this.procedureParameter, template.procedureParameter) + "\nPHEN =>" + obsProperty); } return match; } /** * Retourne un code représentant cette observation. */ @Override public final int hashCode() { return featureOfInterest.hashCode() ^ observedProperty.hashCode() ^ result.hashCode(); } /** * Verify if this entry is identical to specified object. */ @Override public boolean equals(final Object object) { if (object == this) { return true; } if (object instanceof ObservationType) { final ObservationType that = (ObservationType) object; boolean res = false; if (this.result == null && that.result == null) { res = true; } else if (this.result != null && that.result != null) { res = Objects.equals(this.result.getValue(), that.result.getValue()); } return Objects.equals(this.featureOfInterest, that.featureOfInterest) && Objects.equals(this.observedProperty, that.observedProperty) && Objects.equals(this.procedure, that.procedure) && Objects.equals(this.resultQuality, that.resultQuality) && res && Objects.equals(this.samplingTime, that.samplingTime) && Objects.equals(this.observationMetadata, that.observationMetadata) && Objects.equals(this.procedureTime, that.procedureTime) && Objects.equals(this.procedureParameter, that.procedureParameter); } return false; } /** * Verifie si l'observation est complete. */ public boolean isComplete() { //TODO appeler les isCOmplete des attributs return (procedure != null) && (observedProperty != null) && (featureOfInterest != null) && (result != null); } /** * Retourne une chaine de charactere representant l'observation. */ @Override public String toString() { StringBuilder s = new StringBuilder("[").append(this.getClass().getSimpleName()).append(']'); char lineSeparator = '\n'; s.append(lineSeparator); s.append("name = ").append(name); if (definition != null) { s.append("definition = ").append(definition); } s.append(lineSeparator); if (samplingTime != null) { s.append("samplingTime = ").append(samplingTime.toString()).append(lineSeparator); } if (procedure != null) { s.append("procedure = ").append(procedure.toString()).append(lineSeparator); } else { s.append("procedure is null!").append(lineSeparator); } if (observedProperty != null) { s.append("observedProperty = ").append(observedProperty.toString()).append(lineSeparator); } else { s.append("observed property is null!").append(lineSeparator); } if (featureOfInterest != null) { s.append("feature Of Interest = ").append(featureOfInterest.toString()).append(lineSeparator); } else { s.append("feature Of Interest is null!").append(lineSeparator); } if (result != null) { s.append(" result = ").append(result.getValue()).append(lineSeparator); } return s.toString(); } @Override public String getId() { return name; } @Override public void setId(String id) { // do nothing no id on v 1.0.0 } }