/* * 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; // J2SE dependencies 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.constellation.sos.io.lucene.LuceneObservationIndexer; import org.geotoolkit.gml.xml.AbstractGeometry; import org.geotoolkit.lucene.IndexingException; import org.constellation.sos.io.ObservationWriter; import org.geotoolkit.sampling.xml.SamplingFeature; import org.geotoolkit.sos.xml.ObservationOffering; import org.geotoolkit.sos.xml.SOSMarshallerPool; import org.geotoolkit.swe.xml.Phenomenon; import org.geotoolkit.swes.xml.ObservationTemplate; import org.opengis.observation.Observation; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.geotoolkit.observation.xml.AbstractObservation; /** * * @author Guilhem Legal (Geomatys) */ public class FileObservationWriter implements ObservationWriter { private File offeringDirectory; private File phenomenonDirectory; private File observationDirectory; private File observationTemplateDirectory; //private File sensorDirectory; private File foiDirectory; //private File resultDirectory; private static final MarshallerPool MARSHALLER_POOL; static { MARSHALLER_POOL = SOSMarshallerPool.getInstance(); } private LuceneObservationIndexer indexer; private final String observationTemplateIdBase; private final String observationIdBase; private static final String FILE_EXTENSION = ".xml"; private static final Logger LOGGER = Logging.getLogger("org.constellation.sos.io.filesystem"); public FileObservationWriter(final Automatic configuration, final Map<String, Object> properties) throws DataStoreException { super(); this.observationTemplateIdBase = (String) properties.get(OMFactory.OBSERVATION_TEMPLATE_ID_BASE); this.observationIdBase = (String) properties.get(OMFactory.OBSERVATION_ID_BASE); final File dataDirectory = configuration.getDataDirectory(); if (dataDirectory.exists()) { offeringDirectory = new File(dataDirectory, "offerings"); phenomenonDirectory = new File(dataDirectory, "phenomenons"); observationDirectory = new File(dataDirectory, "observations"); //sensorDirectory = new File(dataDirectory, "sensors"); foiDirectory = new File(dataDirectory, "features"); //resultDirectory = new File(dataDirectory, "results"); observationTemplateDirectory = new File(dataDirectory, "observationTemplates"); } if (MARSHALLER_POOL == null) { throw new DataStoreException("JAXB exception while initializing the file observation reader"); } try { indexer = new LuceneObservationIndexer(configuration, "", true); } catch (IndexingException ex) { throw new DataStoreException("Indexing exception while initializing the file observation reader", ex); } } @Override public String writeObservationTemplate(final ObservationTemplate template) throws DataStoreException { final Observation observation = template.getObservation(); if (observation == null) { return null; } try { final Marshaller marshaller = MARSHALLER_POOL.acquireMarshaller(); final File observationFile = new File(observationTemplateDirectory, observation.getName() + FILE_EXTENSION); if (observationFile.exists()) { final boolean created = observationFile.createNewFile(); if (!created) { throw new DataStoreException("unable to create an observation file."); } } else { LOGGER.log(Level.WARNING, "we overwrite the file:{0}", observationFile.getPath()); } marshaller.marshal(observation, observationFile); MARSHALLER_POOL.recycle(marshaller); writePhenomenon((Phenomenon) observation.getObservedProperty()); if (observation.getFeatureOfInterest() != null) { writeFeatureOfInterest((SamplingFeature) observation.getFeatureOfInterest()); } indexer.indexDocument(observation); return observation.getName().getCode(); } catch (JAXBException | IOException ex) { throw new DataStoreException("Exception while marshalling the observation file.", ex); } } private 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 String writeObservation(final Observation observation) throws DataStoreException { try { final File observationFile; if (observation instanceof AbstractObservation && (observation.getName() == null || observation.getName().getCode() == null)) { ((AbstractObservation)observation).setName(getNewObservationId()); } if (observation.getName().getCode().startsWith(observationTemplateIdBase)) { observationFile = new File(observationTemplateDirectory, observation.getName().getCode() + FILE_EXTENSION); } else { observationFile = new File(observationDirectory, observation.getName().getCode() + FILE_EXTENSION); } if (observationFile.exists()) { final boolean created = observationFile.createNewFile(); if (!created) { throw new DataStoreException("unable to create an observation file:" + observationFile.getName()); } } else { LOGGER.log(Level.WARNING, "we overwrite the file:{0}", observationFile.getPath()); } final Marshaller marshaller = MARSHALLER_POOL.acquireMarshaller(); marshaller.marshal(observation, observationFile); MARSHALLER_POOL.recycle(marshaller); writePhenomenon((Phenomenon) observation.getObservedProperty()); if (observation.getFeatureOfInterest() != null) { writeFeatureOfInterest((SamplingFeature) observation.getFeatureOfInterest()); } indexer.indexDocument(observation); return observation.getName().getCode(); } catch (JAXBException | IOException ex) { throw new DataStoreException("Exception while marshalling the observation file.", ex); } } /** * {@inheritDoc} */ @Override public List<String> writeObservations(List<Observation> observations) throws DataStoreException { final List<String> results = new ArrayList<>(); for (Observation observation : observations) { final String oid = writeObservation(observation); results.add(oid); } return results; } @Override public void removeObservation(final String observationID) throws DataStoreException { final File observationFile; if (observationID.startsWith(observationTemplateIdBase)) { observationFile = new File(observationTemplateDirectory, observationID + FILE_EXTENSION); } else { observationFile = new File(observationDirectory, observationID + FILE_EXTENSION); } if (observationFile.exists()) { observationFile.delete(); } else { LOGGER.log(Level.WARNING, "unable to find t he fiel to delete:{0}", observationFile.getPath()); } } @Override public void removeObservationForProcedure(final String procedureID) throws DataStoreException { throw new UnsupportedOperationException("Not supported yet in this implementation."); } @Override public void removeProcedure(final String procedureID) throws DataStoreException { throw new UnsupportedOperationException("Not supported yet in this implementation."); } private void writePhenomenon(final Phenomenon phenomenon) throws DataStoreException { try { if (!phenomenonDirectory.exists()) { phenomenonDirectory.mkdir(); } final File phenomenonFile = new File(phenomenonDirectory, phenomenon.getName() + FILE_EXTENSION); if (!phenomenonFile.exists()) { final boolean created = phenomenonFile.createNewFile(); if (!created) { throw new DataStoreException("unable to create a phenomenon file."); } final Marshaller marshaller = MARSHALLER_POOL.acquireMarshaller(); marshaller.marshal(phenomenon, phenomenonFile); MARSHALLER_POOL.recycle(marshaller); } } catch (JAXBException ex) { throw new DataStoreException("JAXB exception while marshalling the phenomenon file.", ex); } catch (IOException ex) { throw new DataStoreException("IO exception while marshalling the phenomenon file.", ex); } } private void writeFeatureOfInterest(final SamplingFeature foi) throws DataStoreException { try { if (!foiDirectory.exists()) { foiDirectory.mkdir(); } final File foiFile = new File(foiDirectory, foi.getId() + FILE_EXTENSION); if (!foiFile.exists()) { final boolean created = foiFile.createNewFile(); if (!created) { throw new DataStoreException("unable to create a feature of interest file."); } final Marshaller marshaller = MARSHALLER_POOL.acquireMarshaller(); marshaller.marshal(foi, foiFile); MARSHALLER_POOL.recycle(marshaller); } } catch (JAXBException | IOException ex) { throw new DataStoreException("Exception while marshalling the feature of interest file.", ex); } } /** * {@inheritDoc} */ @Override public void writePhenomenons(final List<org.opengis.observation.Phenomenon> phenomenons) throws DataStoreException { for (org.opengis.observation.Phenomenon phenomenon : phenomenons) { if (phenomenon instanceof Phenomenon) { writePhenomenon((Phenomenon)phenomenon); } else if (phenomenon != null) { LOGGER.log(Level.WARNING, "Bad implementation of phenomenon:{0}", phenomenon.getClass().getName()); } } } /** * {@inheritDoc} */ @Override public String writeOffering(final ObservationOffering offering) throws DataStoreException { try { if (!offeringDirectory.exists()) { offeringDirectory.mkdir(); } final File offeringFile = new File(offeringDirectory, offering.getId() + FILE_EXTENSION); final boolean created = offeringFile.createNewFile(); if (!created) { throw new DataStoreException("unable to create an offering file."); } final Marshaller marshaller = MARSHALLER_POOL.acquireMarshaller(); marshaller.marshal(offering, offeringFile); MARSHALLER_POOL.recycle(marshaller); return offering.getId(); } catch (JAXBException | IOException ex) { throw new DataStoreException("Exception while marshalling the offering file.", ex); } } /** * {@inheritDoc} */ @Override public void updateOffering(final String offeringID, final String offProc, final List<String> offPheno, final String offSF) throws DataStoreException { // TODO } /** * {@inheritDoc} */ @Override public void updateOfferings() { //do nothing } /** * {@inheritDoc} */ @Override public void recordProcedureLocation(final String physicalID, final AbstractGeometry position) throws DataStoreException { // do nothing } @Override public void writeProcedure(final String procedureID, final AbstractGeometry position, final String parent, final String type) throws DataStoreException { // do nothing } /** * {@inheritDoc} */ @Override public String getInfos() { return "Constellation Filesystem O&M Writer 0.9"; } /** * {@inheritDoc} */ @Override public void destroy() { indexer.destroy(); } }