/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2015, 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;
* version 2.1 of the License.
*
* 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;
import java.net.URI;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.gml.xml.AbstractFeature;
import org.geotoolkit.gml.xml.AbstractGeometry;
import org.geotoolkit.gml.xml.BoundingShape;
import org.geotoolkit.gml.xml.Envelope;
import static org.geotoolkit.ows.xml.OWSExceptionCode.INVALID_PARAMETER_VALUE;
import static org.geotoolkit.ows.xml.OWSExceptionCode.MISSING_PARAMETER_VALUE;
import org.geotoolkit.sml.xml.AbstractDerivableComponent;
import org.geotoolkit.sml.xml.AbstractIdentification;
import org.geotoolkit.sml.xml.AbstractIdentifier;
import org.geotoolkit.sml.xml.AbstractProcess;
import org.geotoolkit.sml.xml.AbstractSensorML;
import org.geotoolkit.sos.xml.SOSXmlFactory;
import org.geotoolkit.temporal.object.ISODateParser;
import org.opengis.observation.Observation;
/**
* Utility methods for SOS / Sensor.
*
* @author Guilhem Legal (Geomatys)
*/
public class Utils {
private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.observation");
/**
* Return the physical ID of a sensor.
* This ID is found into a "Identifier" mark with the name 'supervisorCode'
*
* @param sensor
* @return
*/
public static String getPhysicalID(final AbstractSensorML sensor) {
if (sensor != null && sensor.getMember().size() > 0) {
final AbstractProcess process = sensor.getMember().get(0).getRealProcess();
final List<? extends AbstractIdentification> idents = process.getIdentification();
for(AbstractIdentification ident : idents) {
if (ident.getIdentifierList() != null) {
for (AbstractIdentifier identifier: ident.getIdentifierList().getIdentifier()) {
if ("supervisorCode".equals(identifier.getName()) && identifier.getTerm() != null) {
return identifier.getTerm().getValue();
}
}
}
}
}
return null;
}
/**
* Return the position of a sensor.
*
* @param sensor
* @return
*/
public static AbstractGeometry getSensorPosition(final AbstractSensorML sensor) {
if (sensor.getMember().size() == 1) {
if (sensor.getMember().get(0).getRealProcess() instanceof AbstractDerivableComponent) {
final AbstractDerivableComponent component = (AbstractDerivableComponent) sensor.getMember().get(0).getRealProcess();
if (component.getSMLLocation() != null && component.getSMLLocation().getGeometry()!= null) {
return component.getSMLLocation().getGeometry();
} else if (component.getPosition() != null && component.getPosition().getPosition() != null &&
component.getPosition().getPosition().getLocation() != null && component.getPosition().getPosition().getLocation().getVector() != null) {
final URI crs = component.getPosition().getPosition().getReferenceFrame();
return component.getPosition().getPosition().getLocation().getVector().getGeometry(crs);
}
}
}
LOGGER.warning("there is no sensor position in the specified sensorML");
return null;
}
/**
* return a SQL formatted timestamp
*
* @param time a GML time position object.
* @return
* @throws org.geotoolkit.observation.ObservationStoreException
*/
public static String getTimeValue(final Date time) throws ObservationStoreException {
if (time != null) {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS");
final String value = df.format(time);
//here t is not used but it allow to verify the syntax of the timestamp
final ISODateParser parser = new ISODateParser();
final Date d = parser.parseToDate(value);
final Timestamp t = new Timestamp(d.getTime());
return t.toString();
} catch(IllegalArgumentException e) {
throw new ObservationStoreException("Unable to parse the value: " + time.toString() + '\n' +
"Bad format of timestamp:\n" + e.getMessage(),
INVALID_PARAMETER_VALUE, "eventTime");
}
} else {
String locator;
if (time == null) {
locator = "Timeposition";
} else {
locator = "TimePosition value";
}
throw new ObservationStoreException("bad format of time, " + locator + " mustn't be null",
MISSING_PARAMETER_VALUE, "eventTime");
}
}
/**
* Return an envelope containing all the Observation member of the collection.
*
* @param version
* @param observations
* @param srsName
* @return
*/
public static Envelope getCollectionBound(final String version, final List<Observation> observations, final String srsName) {
double minx = Double.MAX_VALUE;
double miny = Double.MAX_VALUE;
double maxx = -Double.MAX_VALUE;
double maxy = -Double.MAX_VALUE;
for (Observation observation: observations) {
final AbstractFeature feature = (AbstractFeature) observation.getFeatureOfInterest();
if (feature != null) {
if (feature.getBoundedBy() != null) {
final BoundingShape bound = feature.getBoundedBy();
if (bound.getEnvelope() != null) {
if (bound.getEnvelope().getLowerCorner() != null
&& bound.getEnvelope().getLowerCorner().getCoordinate() != null
&& bound.getEnvelope().getLowerCorner().getCoordinate().length == 2 ) {
final double[] lower = bound.getEnvelope().getLowerCorner().getCoordinate();
if (lower[0] < minx) {
minx = lower[0];
}
if (lower[1] < miny) {
miny = lower[1];
}
}
if (bound.getEnvelope().getUpperCorner() != null
&& bound.getEnvelope().getUpperCorner().getCoordinate() != null
&& bound.getEnvelope().getUpperCorner().getCoordinate().length == 2 ) {
final double[] upper = bound.getEnvelope().getUpperCorner().getCoordinate();
if (upper[0] > maxx) {
maxx = upper[0];
}
if (upper[1] > maxy) {
maxy = upper[1];
}
}
}
}
}
}
if (minx == Double.MAX_VALUE) {
minx = -180.0;
}
if (miny == Double.MAX_VALUE) {
miny = -90.0;
}
if (maxx == (-Double.MAX_VALUE)) {
maxx = 180.0;
}
if (maxy == (-Double.MAX_VALUE)) {
maxy = 90.0;
}
final Envelope env = SOSXmlFactory.buildEnvelope(version, null, minx, miny, maxx, maxy, srsName);
env.setSrsDimension(2);
env.setAxisLabels(Arrays.asList("Y X"));
return env;
}
}