/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.sos.io.filesystem; import org.apache.sis.storage.DataStoreException; import org.apache.sis.util.logging.Logging; import org.apache.sis.xml.MarshallerPool; import org.constellation.generic.database.Automatic; import org.constellation.sos.factory.OMFactory; import org.geotoolkit.gml.xml.AbstractGeometry; import org.geotoolkit.sos.xml.ObservationOffering; import org.geotoolkit.sos.xml.ResponseModeType; import org.geotoolkit.sos.xml.SOSMarshallerPool; import org.geotoolkit.swe.xml.DataArrayProperty; import org.opengis.observation.Observation; import org.opengis.observation.sampling.SamplingFeature; import org.opengis.temporal.TemporalGeometricPrimitive; import org.opengis.temporal.TemporalPrimitive; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.namespace.QName; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.constellation.sos.io.ObservationReader; /** * * @author Guilhem Legal (Geomatys) */ public class FileObservationReader implements ObservationReader { /** * use for debugging purpose */ protected static final Logger LOGGER = Logging.getLogger("org.constellation.sos"); /** * The base for observation id. */ protected final String observationIdBase; protected final String phenomenonIdBase; private File offeringDirectory; private File phenomenonDirectory; private File observationDirectory; private File observationTemplateDirectory; private File sensorDirectory; private File foiDirectory; private static final MarshallerPool MARSHALLER_POOL; static { MARSHALLER_POOL = SOSMarshallerPool.getInstance(); } private static final String FILE_EXTENSION = ".xml"; public FileObservationReader(final Automatic configuration, final Map<String, Object> properties) throws DataStoreException { this.observationIdBase = (String) properties.get(OMFactory.OBSERVATION_ID_BASE); this.phenomenonIdBase = (String) properties.get(OMFactory.PHENOMENON_ID_BASE); final File dataDirectory = configuration.getDataDirectory(); if (dataDirectory != null && dataDirectory.exists()) { offeringDirectory = new File(dataDirectory, "offerings"); phenomenonDirectory = new File(dataDirectory, "phenomenons"); observationDirectory = new File(dataDirectory, "observations"); observationTemplateDirectory = new File(dataDirectory, "observationTemplates"); sensorDirectory = new File(dataDirectory, "sensors"); foiDirectory = new File(dataDirectory, "features"); } else { throw new DataStoreException("There is no data Directory"); } if (MARSHALLER_POOL == null) { throw new DataStoreException("JAXB exception while initializing the file observation reader"); } } /** * {@inheritDoc} */ @Override public Collection<String> getOfferingNames(final String version) throws DataStoreException { final List<String> offeringNames = new ArrayList<>(); if (offeringDirectory.isDirectory()) { final File offeringVersionDir = new File(observationDirectory, version); if (offeringVersionDir.isDirectory()) { for (File offeringFile: offeringVersionDir.listFiles()) { String offeringName = offeringFile.getName(); offeringName = offeringName.substring(0, offeringName.indexOf(FILE_EXTENSION)); offeringNames.add(offeringName); } } } return offeringNames; } @Override public Collection<String> getOfferingNames(String version, String sensorType) throws DataStoreException { // no filter yet return getOfferingNames(version); } /** * {@inheritDoc} */ @Override public List<ObservationOffering> getObservationOfferings(final List<String> offeringNames, final String version) throws DataStoreException { final List<ObservationOffering> offerings = new ArrayList<>(); for (String offeringName : offeringNames) { offerings.add(getObservationOffering(offeringName, version)); } return offerings; } /** * {@inheritDoc} */ @Override public ObservationOffering getObservationOffering(final String offeringName, final String version) throws DataStoreException { final File offeringVersionDir = new File(offeringDirectory, version); if (offeringVersionDir.isDirectory()) { final File offeringFile = new File(offeringVersionDir, offeringName + FILE_EXTENSION); if (offeringFile.exists()) { try { final Unmarshaller unmarshaller = MARSHALLER_POOL.acquireUnmarshaller(); Object obj = unmarshaller.unmarshal(offeringFile); MARSHALLER_POOL.recycle(unmarshaller); if (obj instanceof JAXBElement) { obj = ((JAXBElement)obj).getValue(); } if (obj instanceof ObservationOffering) { return (ObservationOffering) obj; } throw new DataStoreException("The file " + offeringFile + " does not contains an offering Object."); } catch (JAXBException ex) { throw new DataStoreException("Unable to unmarshall The file " + offeringFile, ex); } } } else { throw new DataStoreException("Unsuported version:" + version); } return null; } /** * {@inheritDoc} */ @Override public List<ObservationOffering> getObservationOfferings(final String version) throws DataStoreException { final List<ObservationOffering> offerings = new ArrayList<>(); if (offeringDirectory.exists()) { final File offeringVersionDir = new File(offeringDirectory, version); if (offeringVersionDir.isDirectory()) { for (File offeringFile: offeringVersionDir.listFiles()) { try { final Unmarshaller unmarshaller = MARSHALLER_POOL.acquireUnmarshaller(); Object obj = unmarshaller.unmarshal(offeringFile); MARSHALLER_POOL.recycle(unmarshaller); if (obj instanceof JAXBElement) { obj = ((JAXBElement)obj).getValue(); } if (obj instanceof ObservationOffering) { offerings.add((ObservationOffering) obj); } else { throw new DataStoreException("The file " + offeringFile + " does not contains an offering Object."); } } catch (JAXBException ex) { String msg = ex.getMessage(); if (msg == null && ex.getCause() != null) { msg = ex.getCause().getMessage(); } LOGGER.warning("Unable to unmarshall The file " + offeringFile + " cause:" + msg); } } } else { throw new DataStoreException("Unsuported version:" + version); } } return offerings; } @Override public List<ObservationOffering> getObservationOfferings(String version, String sensorType) throws DataStoreException { // no filter yet return getObservationOfferings(version); } /** * {@inheritDoc} */ @Override public Collection<String> getProcedureNames() throws DataStoreException { final List<String> sensorNames = new ArrayList<>(); if (sensorDirectory.exists()) { for (File sensorFile: sensorDirectory.listFiles()) { String sensorName = sensorFile.getName(); sensorName = sensorName.substring(0, sensorName.indexOf(FILE_EXTENSION)); sensorNames.add(sensorName); } } return sensorNames; } @Override public Collection<String> getProcedureNames(String sensorType) throws DataStoreException { // no filter yet return getProcedureNames(); } /** * {@inheritDoc} */ @Override public Collection<String> getPhenomenonNames() throws DataStoreException { final List<String> phenomenonNames = new ArrayList<>(); if (phenomenonDirectory.exists()) { for (File phenomenonFile: phenomenonDirectory.listFiles()) { String phenomenonName = phenomenonFile.getName(); phenomenonName = phenomenonName.substring(0, phenomenonName.indexOf(FILE_EXTENSION)); phenomenonNames.add(phenomenonName); } } return phenomenonNames; } @Override public Collection<String> getProceduresForPhenomenon(String observedProperty) throws DataStoreException { throw new UnsupportedOperationException("Not supported yet in this implementation."); } @Override public Collection<String> getPhenomenonsForProcedure(String sensorID) throws DataStoreException { throw new UnsupportedOperationException("Not supported yet in this implementation."); } /** * {@inheritDoc} */ @Override public boolean existPhenomenon(String phenomenonName) throws DataStoreException { // we remove the phenomenon id base if (phenomenonName.contains(phenomenonIdBase)) { phenomenonName = phenomenonName.replace(phenomenonIdBase, ""); } final File phenomenonFile = new File(phenomenonDirectory, phenomenonName + FILE_EXTENSION); return phenomenonFile.exists(); } /** * {@inheritDoc} */ @Override public Collection<String> getFeatureOfInterestNames() throws DataStoreException { final List<String> foiNames = new ArrayList<>(); if (foiDirectory.exists()) { for (File foiFile: foiDirectory.listFiles()) { String foiName = foiFile.getName(); foiName = foiName.substring(0, foiName.indexOf(FILE_EXTENSION)); foiNames.add(foiName); } } return foiNames; } /** * {@inheritDoc} */ @Override public SamplingFeature getFeatureOfInterest(final String samplingFeatureName, final String version) throws DataStoreException { final File samplingFeatureFile = new File(foiDirectory, samplingFeatureName + FILE_EXTENSION); if (samplingFeatureFile.exists()) { try { final Unmarshaller unmarshaller = MARSHALLER_POOL.acquireUnmarshaller(); Object obj = unmarshaller.unmarshal(samplingFeatureFile); MARSHALLER_POOL.recycle(unmarshaller); if (obj instanceof JAXBElement) { obj = ((JAXBElement)obj).getValue(); } if (obj instanceof SamplingFeature) { return (SamplingFeature) obj; } throw new DataStoreException("The file " + samplingFeatureFile + " does not contains an foi Object."); } catch (JAXBException ex) { throw new DataStoreException("Unable to unmarshall The file " + samplingFeatureFile, ex); } } return null; } /** * {@inheritDoc} */ @Override public Observation getObservation(final String identifier, final QName resultModel, final ResponseModeType mode, final String version) throws DataStoreException { File observationFile = new File(observationDirectory, identifier + FILE_EXTENSION); if (!observationFile.exists()) { observationFile = new File(observationTemplateDirectory, identifier + FILE_EXTENSION); } if (observationFile.exists()) { try { final Unmarshaller unmarshaller = MARSHALLER_POOL.acquireUnmarshaller(); Object obj = unmarshaller.unmarshal(observationFile); MARSHALLER_POOL.recycle(unmarshaller); if (obj instanceof JAXBElement) { obj = ((JAXBElement)obj).getValue(); } if (obj instanceof Observation) { return (Observation) obj; } throw new DataStoreException("The file " + observationFile + " does not contains an observation Object."); } catch (JAXBException ex) { throw new DataStoreException("Unable to unmarshall The file " + observationFile, ex); } } throw new DataStoreException("The file " + observationFile + " does not exist"); } /** * {@inheritDoc} */ @Override public Object getResult(final String identifier, final QName resultModel, final String version) throws DataStoreException { final File anyResultFile = new File(observationDirectory, identifier + FILE_EXTENSION); if (anyResultFile.exists()) { try { final Unmarshaller unmarshaller = MARSHALLER_POOL.acquireUnmarshaller(); Object obj = unmarshaller.unmarshal(anyResultFile); MARSHALLER_POOL.recycle(unmarshaller); if (obj instanceof JAXBElement) { obj = ((JAXBElement)obj).getValue(); } if (obj instanceof Observation) { final Observation obs = (Observation) obj; final DataArrayProperty arrayP = (DataArrayProperty) obs.getResult(); return arrayP.getDataArray(); } throw new DataStoreException("The file " + anyResultFile + " does not contains an observation Object."); } catch (JAXBException ex) { throw new DataStoreException("Unable to unmarshall The file " + anyResultFile, ex); } } throw new DataStoreException("The file " + anyResultFile + " does not exist"); } /** * {@inheritDoc} */ @Override public boolean existProcedure(final String href) throws DataStoreException { if (sensorDirectory.exists()) { for (File sensorFile: sensorDirectory.listFiles()) { String sensorName = sensorFile.getName(); sensorName = sensorName.substring(0, sensorName.indexOf(FILE_EXTENSION)); if (sensorName.equals(href)) { return true; } } } return false; } /** * {@inheritDoc} */ @Override public String getNewObservationId() throws DataStoreException { String obsID = null; boolean exist = true; int i = observationDirectory.list().length; while (exist) { obsID = observationIdBase + i; final File newFile = new File(observationDirectory, obsID); exist = newFile.exists(); i++; } return obsID; } /** * {@inheritDoc} */ @Override public List<String> getEventTime() throws DataStoreException { return Arrays.asList("undefined", "now"); } /** * {@inheritDoc} */ @Override public TemporalPrimitive getFeatureOfInterestTime(final String samplingFeatureName, final String version) throws DataStoreException { throw new DataStoreException("The Filesystem implementation of SOS does not support GetFeatureofInterestTime"); } /** * {@inheritDoc} */ @Override public void destroy() { // nothing to destroy } /** * {@inheritDoc} */ @Override public String getInfos() { return "Constellation Filesystem O&M Reader 0.9"; } /** * {@inheritDoc} */ @Override public List<ResponseModeType> getResponseModes() throws DataStoreException { return Arrays.asList(ResponseModeType.INLINE, ResponseModeType.RESULT_TEMPLATE); } /** * {@inheritDoc} */ @Override public List<String> getResponseFormats() throws DataStoreException { return Arrays.asList("text/xml; subtype=\"om/1.0.0\""); } /** * {@inheritDoc} */ @Override public AbstractGeometry getSensorLocation(String sensorID, String version) throws DataStoreException { throw new UnsupportedOperationException("Not supported yet in this implementation."); } /** * {@inheritDoc} */ @Override public TemporalGeometricPrimitive getTimeForProcedure(final String version, final String sensorID) throws DataStoreException { throw new UnsupportedOperationException("Not supported yet in this implementation."); } @Override public Observation getTemplateForProcedure(String procedure, String version) throws DataStoreException { for (File templateFile : observationTemplateDirectory.listFiles()) { try { final Unmarshaller unmarshaller = MARSHALLER_POOL.acquireUnmarshaller(); Object obj = unmarshaller.unmarshal(templateFile); MARSHALLER_POOL.recycle(unmarshaller); if (obj instanceof JAXBElement) { obj = ((JAXBElement)obj).getValue(); } if (obj instanceof Observation) { final Observation obs = (Observation) obj; if (obs.getProcedure() instanceof org.geotoolkit.observation.xml.Process) { final String processID = ((org.geotoolkit.observation.xml.Process)obs.getProcedure()).getHref(); if (processID.equals(procedure)) { return obs; } } } } catch (JAXBException ex) { throw new DataStoreException("Unable to unmarshall The file " + templateFile, ex); } } return null; } }