/*
* 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.generic;
import org.apache.sis.storage.DataStoreException;
import org.constellation.generic.database.Automatic;
import org.constellation.generic.database.From;
import org.constellation.generic.database.Query;
import org.constellation.generic.database.Select;
import org.constellation.generic.database.Where;
import org.geotoolkit.gml.xml.Envelope;
import org.geotoolkit.observation.ObservationResult;
import org.geotoolkit.observation.ObservationStoreException;
import org.geotoolkit.sos.xml.ObservationOffering;
import org.geotoolkit.sos.xml.ResponseModeType;
import org.opengis.temporal.Instant;
import org.opengis.temporal.Period;
import javax.xml.namespace.QName;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import static org.constellation.sos.ws.SOSConstants.EVENT_TIME;
import static org.constellation.sos.ws.SOSConstants.OBSERVATION_QNAME;
import static org.constellation.sos.ws.SOSConstants.PROCEDURE;
import static org.constellation.sos.ws.SOSUtils.getTimeValue;
import static org.geotoolkit.ows.xml.OWSExceptionCode.INVALID_PARAMETER_VALUE;
import static org.geotoolkit.sos.xml.ResponseModeType.INLINE;
import static org.geotoolkit.sos.xml.ResponseModeType.RESULT_TEMPLATE;
/**
*
* @author Guilhem Legal
*/
public class GenericObservationFilter extends AbstractGenericObservationFilter {
/**
* Clone a Generic Observation Filter for CSTL O&M datasource.
* @param omFilter
*/
public GenericObservationFilter(final GenericObservationFilter omFilter) {
super(omFilter);
}
/**
* Build a new Generic Observation Filter for CSTL O&M datasource.
*
* @param configuration
* @param properties
*
* @throws DataStoreException
*/
public GenericObservationFilter(final Automatic configuration, final Map<String, Object> properties) throws DataStoreException {
super(configuration, properties);
}
@Override
protected Connection acquireConnection() throws SQLException {
final Connection c = super.acquireConnection();
c.setAutoCommit(true);
return c;
}
/**
* {@inheritDoc}
*/
@Override
public void initFilterObservation(final ResponseModeType requestMode, final QName resultModel) {
currentQuery = new Query();
final Select select = new Select(configurationQuery.getSelect("filterObservation"));
final From from;
if (resultModel.equals(OBSERVATION_QNAME)) {
from = new From(configurationQuery.getFrom("observations"));
} else {
from = new From(configurationQuery.getFrom("measurements"));
}
final Where where = new Where(configurationQuery.getWhere("observationType"));
if (requestMode == INLINE) {
where.replaceVariable("observationIdBase", observationIdBase, false);
} else if (requestMode == RESULT_TEMPLATE) {
where.replaceVariable("observationIdBase", observationTemplateIdBase, false);
}
currentQuery.addSelect(select);
currentQuery.addFrom(from);
currentQuery.addWhere(where);
}
/**
* {@inheritDoc}
*/
@Override
public void initFilterGetResult(final String procedure, final QName resultModel) {
currentQuery = new Query();
final Select select = new Select(configurationQuery.getSelect("filterResult"));
final From from = new From(configurationQuery.getFrom("observations"));
final Where where = new Where(configurationQuery.getWhere(PROCEDURE));
where.replaceVariable(PROCEDURE, procedure, true);
currentQuery.addSelect(select);
currentQuery.addFrom(from);
currentQuery.addWhere(where);
}
/**
* {@inheritDoc}
*/
@Override
public void initFilterGetFeatureOfInterest() throws DataStoreException {
// do nothing no implemented
}
/**
* {@inheritDoc}
*/
@Override
public void setProcedure(final List<String> procedures, final List<ObservationOffering> offerings) {
if (!procedures.isEmpty()) {
for (String s : procedures) {
if (s != null) {
final Where where = new Where(configurationQuery.getWhere(PROCEDURE));
where.replaceVariable(PROCEDURE, s, true);
currentQuery.addWhere(where);
}
}
} else {
//if is not specified we use all the process of the offering
for (ObservationOffering off : offerings) {
for (String proc : off.getProcedures()) {
final Where where = new Where(configurationQuery.getWhere(PROCEDURE));
where.replaceVariable(PROCEDURE, proc, true);
currentQuery.addWhere(where);
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void setObservedProperties(final List<String> phenomenon) {
for (String p : phenomenon) {
if (p.contains(phenomenonIdBase)) {
p = p.replace(phenomenonIdBase, "");
}
final Where where = new Where(configurationQuery.getWhere("phenomenon"));
where.replaceVariable("phenomenon", p, true);
currentQuery.addWhere(where);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setFeatureOfInterest(final List<String> fois) {
for (String foi : fois) {
final Where where = new Where(configurationQuery.getWhere("foi"));
where.replaceVariable("foi", foi, true);
currentQuery.addWhere(where);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setTimeEquals(final Object time) throws DataStoreException {
if (time instanceof Period) {
final Period tp = (Period) time;
final String begin = getTimeValue(tp.getBeginning().getDate());
final String end = getTimeValue(tp.getEnding().getDate());
final Where where = new Where(configurationQuery.getWhere("tequalsTP"));
where.replaceVariable("begin", begin, true);
where.replaceVariable("end", end, true);
currentQuery.addWhere(where);
// if the temporal object is a timeInstant
} else if (time instanceof Instant) {
final Instant ti = (Instant) time;
final String position = getTimeValue(ti.getDate());
final Where where = new Where(configurationQuery.getWhere("tequalsTI"));
where.replaceVariable("position", position, true);
currentQuery.addWhere(where);
} else {
throw new ObservationStoreException("TM_Equals operation require timeInstant or TimePeriod!",
INVALID_PARAMETER_VALUE, EVENT_TIME);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setTimeBefore(final Object time) throws DataStoreException {
// for the operation before the temporal object must be an timeInstant
if (time instanceof Instant) {
final Instant ti = (Instant) time;
final String position = getTimeValue(ti.getDate());
final Where where = new Where(configurationQuery.getWhere("tbefore"));
where.replaceVariable("time", position, true);
currentQuery.addWhere(where);
} else {
throw new ObservationStoreException("TM_Before operation require timeInstant!",
INVALID_PARAMETER_VALUE, EVENT_TIME);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setTimeAfter(final Object time) throws DataStoreException {
// for the operation after the temporal object must be an timeInstant
if (time instanceof Instant) {
final Instant ti = (Instant) time;
final String position = getTimeValue(ti.getDate());
final Where where = new Where(configurationQuery.getWhere("tafter"));
where.replaceVariable("time", position, true);
currentQuery.addWhere(where);
} else {
throw new ObservationStoreException("TM_After operation require timeInstant!",
INVALID_PARAMETER_VALUE, EVENT_TIME);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setTimeDuring(final Object time) throws DataStoreException {
if (time instanceof Period) {
final Period tp = (Period) time;
final String begin = getTimeValue(tp.getBeginning().getDate());
final String end = getTimeValue(tp.getEnding().getDate());
final Where where = new Where(configurationQuery.getWhere("tduring"));
where.replaceVariable("begin", begin, true);
where.replaceVariable("end", end, true);
currentQuery.addWhere(where);
} else {
throw new ObservationStoreException("TM_During operation require TimePeriod!",
INVALID_PARAMETER_VALUE, EVENT_TIME);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setOfferings(final List<ObservationOffering> offerings) throws DataStoreException {
// not used in this implementations
}
/**
* {@inheritDoc}
*/
@Override
public List<ObservationResult> filterResult() throws DataStoreException {
final String request = currentQuery.buildSQLQuery();
LOGGER.log(Level.INFO, "request:{0}", request);
try {
final List<ObservationResult> results = new ArrayList<>();
final Connection connection = acquireConnection();
final Statement currentStatement = connection.createStatement();
final ResultSet result = currentStatement.executeQuery(request);
while (result.next()) {
results.add(new ObservationResult(result.getString(1),
result.getTimestamp(2),
result.getTimestamp(3)));
}
result.close();
currentStatement.close();
connection.close();
return results;
} catch (SQLException ex) {
LOGGER.log(Level.WARNING, "SQLException while executing the query: {0}", request);
throw new DataStoreException("the service has throw a SQL Exception:" + ex.getMessage() + '\n' + "while executing the request:" + request);
}
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> filterObservation() throws DataStoreException {
final String request = currentQuery.buildSQLQuery();
LOGGER.log(Level.INFO, "request:{0}", request);
try {
final Set<String> results = new LinkedHashSet<>();
final Connection connection = acquireConnection();
final Statement currentStatement = connection.createStatement();
final ResultSet result = currentStatement.executeQuery(request);
while (result.next()) {
results.add(result.getString(1));
}
result.close();
currentStatement.close();
connection.close();
return results;
} catch (SQLException ex) {
LOGGER.log(Level.WARNING, "SQLException while executing the query: {0} \nmsg:{1}", new Object[]{request, ex.getMessage()});
throw new DataStoreException("the service has throw a SQL Exception:" + ex.getMessage(), ex);
}
}
/**
* {@inheritDoc}
*/
@Override
public String getInfos() {
return "Constellation Generic O&M Filter 0.9";
}
/**
* {@inheritDoc}
*/
@Override
public boolean isBoundedObservation() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void setBoundingBox(final Envelope e) throws DataStoreException {
throw new DataStoreException("SetBoundingBox is not supported by this ObservationFilter implementation.");
}
@Override
public void setTimeLatest() throws DataStoreException {
throw new DataStoreException("setTimeLatest is not supported by this ObservationFilter implementation.");
}
@Override
public void setTimeFirst() throws DataStoreException {
throw new DataStoreException("setTimeFirst is not supported by this ObservationFilter implementation.");
}
@Override
public Set<String> filterFeatureOfInterest() throws DataStoreException {
throw new DataStoreException("filterFeatureOfInterest is not supported by this ObservationFilter implementation.");
}
@Override
public void destroy() {
// do nothing
}
}