/**
* Copyright (C) 2012-2017 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* If the program is linked with libraries which are licensed under one of
* the following licenses, the combination of the program with the linked
* library is not considered a "derivative work" of the program:
*
* - Apache License, version 2.0
* - Apache Software License, version 1.0
* - GNU Lesser General Public License, version 3
* - Mozilla Public License, versions 1.0, 1.1 and 2.0
* - Common Development and Distribution License (CDDL), version 1.0
*
* Therefore the distribution of the program linked with libraries licensed
* under the aforementioned licenses, is permitted by the copyright holders
* if the distribution is compliant with both the GNU General Public
* License version 2 and the aforementioned licenses.
*
* This program 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 General
* Public License for more details.
*/
package org.n52.sos.ds.hibernate.dao;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.hibernate.sql.JoinType;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.n52.sos.ds.hibernate.dao.series.AbstractSeriesObservationDAO;
import org.n52.sos.ds.hibernate.dao.series.SeriesObservationDAO;
import org.n52.sos.ds.hibernate.entities.AbstractObservation;
import org.n52.sos.ds.hibernate.entities.EntitiyHelper;
import org.n52.sos.ds.hibernate.entities.FeatureOfInterest;
import org.n52.sos.ds.hibernate.entities.ObservableProperty;
import org.n52.sos.ds.hibernate.entities.Observation;
import org.n52.sos.ds.hibernate.entities.ObservationConstellation;
import org.n52.sos.ds.hibernate.entities.ObservationInfo;
import org.n52.sos.ds.hibernate.entities.Offering;
import org.n52.sos.ds.hibernate.entities.Procedure;
import org.n52.sos.ds.hibernate.entities.ProcedureDescriptionFormat;
import org.n52.sos.ds.hibernate.entities.TProcedure;
import org.n52.sos.ds.hibernate.entities.ValidProcedureTime;
import org.n52.sos.ds.hibernate.entities.series.Series;
import org.n52.sos.ds.hibernate.entities.series.SeriesObservationInfo;
import org.n52.sos.ds.hibernate.util.HibernateHelper;
import org.n52.sos.ds.hibernate.util.NoopTransformerAdapter;
import org.n52.sos.ds.hibernate.util.TimeExtrema;
import org.n52.sos.ds.hibernate.util.QueryHelper;
import org.n52.sos.exception.CodedException;
import org.n52.sos.exception.ows.concrete.UnsupportedOperatorException;
import org.n52.sos.exception.ows.concrete.UnsupportedTimeException;
import org.n52.sos.exception.ows.concrete.UnsupportedValueReferenceException;
import org.n52.sos.ogc.gml.time.Time;
import org.n52.sos.ogc.ows.OwsExceptionReport;
import org.n52.sos.util.CollectionHelper;
import org.n52.sos.util.DateTimeHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* Hibernate data access class for procedure
*
* @author CarstenHollmann
* @since 4.0.0
*/
public class ProcedureDAO extends AbstractIdentifierNameDescriptionDAO implements HibernateSqlQueryConstants {
//public class ProcedureDAO extends TimeCreator implements HibernateSqlQueryConstants {
private static final Logger LOGGER = LoggerFactory.getLogger(ProcedureDAO.class);
private static final String SQL_QUERY_GET_PROCEDURES_FOR_ALL_FEATURES_OF_INTEREST = "getProceduresForAllFeaturesOfInterest";
private static final String SQL_QUERY_GET_PROCEDURES_FOR_FEATURE_OF_INTEREST = "getProceduresForFeatureOfInterest";
private static final String SQL_QUERY_GET_PROCEDURE_TIME_EXTREMA = "getProcedureTimeExtrema";
private static final String SQL_QUERY_GET_MIN_DATE_FOR_PROCEDURE = "getMinDate4Procedure";
private static final String SQL_QUERY_GET_MAX_DATE_FOR_PROCEDURE = "getMaxDate4Procedure";
/**
* Get all procedure objects
*
* @param session
* Hibernate session
* @return Procedure objects
*/
@SuppressWarnings("unchecked")
public List<Procedure> getProcedureObjects(final Session session) {
Criteria criteria = getDefaultCriteria(session);
LOGGER.debug("QUERY getProcedureObjects(): {}", HibernateHelper.getSqlString(criteria));
return criteria.list();
}
/**
* Get map keyed by undeleted procedure identifiers with
* collections of parent procedures (if supported) as values
* @param session
* @return Map keyed by procedure identifier with values of parent procedure identifier collections
*/
public Map<String,Collection<String>> getProcedureIdentifiers(final Session session) {
boolean tProcedureSupported = HibernateHelper.isEntitySupported(TProcedure.class);
Criteria criteria = getDefaultCriteria(session);
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property(Procedure.IDENTIFIER));
if (tProcedureSupported) {
criteria.createAlias(TProcedure.PARENTS, "pp", JoinType.LEFT_OUTER_JOIN);
projectionList.add(Projections.property("pp." + Procedure.IDENTIFIER));
}
criteria.setProjection(projectionList);
//return as List<Object[]> even if there's only one column for consistency
criteria.setResultTransformer(NoopTransformerAdapter.INSTANCE);
LOGGER.debug("QUERY getProcedureIdentifiers(): {}", HibernateHelper.getSqlString(criteria));
@SuppressWarnings("unchecked")
List<Object[]> results = criteria.list();
Map<String,Collection<String>> map = Maps.newHashMap();
for (Object[] result : results) {
String procedureIdentifier = (String) result[0];
String parentProcedureIdentifier = null;
if (tProcedureSupported) {
parentProcedureIdentifier = (String) result[1];
}
if (parentProcedureIdentifier == null) {
map.put(procedureIdentifier, null);
} else {
CollectionHelper.addToCollectionMap(procedureIdentifier, parentProcedureIdentifier, map);
}
}
return map;
}
/**
* Get Procedure object for procedure identifier
*
* @param identifier
* Procedure identifier
* @param session
* Hibernate session
* @return Procedure object
*/
public Procedure getProcedureForIdentifier(final String identifier, final Session session) {
Criteria criteria = getDefaultCriteria(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
LOGGER.debug("QUERY getProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
Procedure procedure = (Procedure)criteria.uniqueResult();
if (procedure instanceof TProcedure && HibernateHelper.isEntitySupported(TProcedure.class)) {
criteria.createCriteria(TProcedure.VALID_PROCEDURE_TIME).add(Restrictions.isNull(ValidProcedureTime.END_TIME));
LOGGER.debug("QUERY getProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
Procedure proc = (Procedure)criteria.uniqueResult();
if (proc != null) {
return proc;
}
}
return procedure;
}
//
// private Procedure getProcedureWithLatestValidProcedureDescription(String identifier, Session session) {
// Criteria criteria = getDefaultCriteria(session);
// criteria.add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
// criteria.createCriteria(TProcedure.VALID_PROCEDURE_TIME).add(Restrictions.isNull(ValidProcedureTime.END_TIME));
// LOGGER.debug("QUERY getProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
// return (Procedure) criteria.uniqueResult();
// }
/**
* Get Procedure object for procedure identifier inclusive deleted procedure
*
* @param identifier
* Procedure identifier
* @param session
* Hibernate session
* @return Procedure object
*/
public Procedure getProcedureForIdentifierIncludeDeleted(final String identifier, final Session session) {
Criteria criteria =
session.createCriteria(Procedure.class).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
LOGGER.debug("QUERY getProcedureForIdentifierIncludeDeleted(identifier): {}",
HibernateHelper.getSqlString(criteria));
return (Procedure) criteria.uniqueResult();
}
/**
* Get Procedure object for procedure identifier
*
* @param identifier
* Procedure identifier
* @param session
* Hibernate session
* @return Procedure object
*/
public Procedure getProcedureForIdentifier(final String identifier, Time time, final Session session) {
Criteria criteria = getDefaultCriteria(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
LOGGER.debug("QUERY getProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
return (Procedure) criteria.uniqueResult();
}
/**
* Get Procedure objects for procedure identifiers
*
* @param identifiers
* Procedure identifiers
* @param session
* Hibernate session
* @return Procedure objects
*/
@SuppressWarnings("unchecked")
public List<Procedure> getProceduresForIdentifiers(final Collection<String> identifiers, final Session session) {
if (identifiers == null || identifiers.isEmpty()) {
return Collections.EMPTY_LIST;
}
Criteria criteria = getDefaultCriteria(session).add(Restrictions.in(Procedure.IDENTIFIER, identifiers));
LOGGER.debug("QUERY getProceduresForIdentifiers(identifiers): {}", HibernateHelper.getSqlString(criteria));
return criteria.list();
}
/**
* Get procedure identifiers for all FOIs
*
* @param session
* Hibernate session
*
* @return Map of foi identifier to procedure identifier collection
* @throws HibernateException
* @throws CodedException
*/
public Map<String,Collection<String>> getProceduresForAllFeaturesOfInterest(final Session session) {
List<Object[]> results = getFeatureProcedureResult(session);
Map<String,Collection<String>> foiProcMap = Maps.newHashMap();
if (CollectionHelper.isNotEmpty(results)) {
for (Object[] result : results) {
String foi = (String) result[0];
String proc = (String) result[1];
Collection<String> foiProcs = foiProcMap.get(foi);
if (foiProcs == null) {
foiProcs = Lists.newArrayList();
foiProcMap.put(foi, foiProcs);
}
foiProcs.add(proc);
}
}
return foiProcMap;
}
/**
* Get FOIs for all procedure identifiers
*
* @param session
* Hibernate session
*
* @return Map of procedure identifier to foi identifier collection
* @throws CodedException
*/
public Map<String,Collection<String>> getFeaturesOfInterestsForAllProcedures(final Session session) {
List<Object[]> results = getFeatureProcedureResult(session);
Map<String,Collection<String>> foiProcMap = Maps.newHashMap();
if (CollectionHelper.isNotEmpty(results)) {
for (Object[] result : results) {
String foi = (String) result[0];
String proc = (String) result[1];
Collection<String> procFois = foiProcMap.get(proc);
if (procFois == null) {
procFois = Lists.newArrayList();
foiProcMap.put(proc, procFois);
}
procFois.add(foi);
}
}
return foiProcMap;
}
@SuppressWarnings("unchecked")
private List<Object[]> getFeatureProcedureResult(Session session) {
List<Object[]> results;
if (HibernateHelper.isNamedQuerySupported(SQL_QUERY_GET_PROCEDURES_FOR_ALL_FEATURES_OF_INTEREST, session)) {
Query namedQuery = session.getNamedQuery(SQL_QUERY_GET_PROCEDURES_FOR_ALL_FEATURES_OF_INTEREST);
LOGGER.debug("QUERY getProceduresForAllFeaturesOfInterest(feature) with NamedQuery: {}",
SQL_QUERY_GET_PROCEDURES_FOR_ALL_FEATURES_OF_INTEREST);
results = namedQuery.list();
} else {
Criteria c = null;
if (EntitiyHelper.getInstance().isSeriesSupported()) {
c = session.createCriteria(EntitiyHelper.getInstance().getSeriesEntityClass())
.createAlias(Series.FEATURE_OF_INTEREST, "f")
.createAlias(Series.PROCEDURE, "p")
.add(Restrictions.eq(Series.DELETED, false))
.setProjection(Projections.distinct(Projections.projectionList()
.add(Projections.property("f." + FeatureOfInterest.IDENTIFIER))
.add(Projections.property("p." + Procedure.IDENTIFIER))));
} else {
c = session.createCriteria(Observation.class)
.createAlias(Observation.FEATURE_OF_INTEREST, "f")
.createAlias(Observation.PROCEDURE, "p")
.add(Restrictions.eq(Observation.DELETED, false))
.setProjection(Projections.distinct(Projections.projectionList()
.add(Projections.property("f." + FeatureOfInterest.IDENTIFIER))
.add(Projections.property("p." + Procedure.IDENTIFIER))));
}
LOGGER.debug("QUERY getProceduresForAllFeaturesOfInterest(feature): {}", HibernateHelper.getSqlString(c));
results = c.list();
}
return results;
}
/**
* Get procedure identifiers for FOI
*
* @param session
* Hibernate session
* @param feature
* FOI object
*
* @return Related procedure identifiers
* @throws CodedException
*/
@SuppressWarnings("unchecked")
public List<String> getProceduresForFeatureOfInterest(final Session session, final FeatureOfInterest feature)
throws OwsExceptionReport {
if (HibernateHelper.isNamedQuerySupported(SQL_QUERY_GET_PROCEDURES_FOR_FEATURE_OF_INTEREST, session)) {
Query namedQuery = session.getNamedQuery(SQL_QUERY_GET_PROCEDURES_FOR_FEATURE_OF_INTEREST);
namedQuery.setParameter(FEATURE, feature.getIdentifier());
LOGGER.debug("QUERY getProceduresForFeatureOfInterest(feature) with NamedQuery: {}",
SQL_QUERY_GET_PROCEDURES_FOR_FEATURE_OF_INTEREST);
return namedQuery.list();
} else {
Criteria c = null;
if (EntitiyHelper.getInstance().isSeriesSupported()) {
c = getDefaultCriteria(session);
c.add(Subqueries.propertyIn(Procedure.ID,
getDetachedCriteriaProceduresForFeatureOfInterestFromSeries(feature, session)));
c.setProjection(Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
} else {
AbstractObservationDAO observationDAO = DaoFactory.getInstance().getObservationDAO();
c = observationDAO.getDefaultObservationInfoCriteria(session);
c.createCriteria(AbstractObservation.FEATURE_OF_INTEREST).add(
Restrictions.eq(FeatureOfInterest.IDENTIFIER, feature.getIdentifier()));
c.createCriteria(AbstractObservation.PROCEDURE).setProjection(
Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
}
LOGGER.debug("QUERY getProceduresForFeatureOfInterest(feature): {}", HibernateHelper.getSqlString(c));
return (List<String>) c.list();
}
}
/**
* Get procedure identifiers for offering identifier
*
* @param offeringIdentifier
* Offering identifier
* @param session
* Hibernate session
* @return Procedure identifiers
* @throws CodedException
* If an error occurs
*/
@SuppressWarnings("unchecked")
public List<String> getProcedureIdentifiersForOffering(final String offeringIdentifier, final Session session)
throws OwsExceptionReport {
final boolean obsConstSupported = HibernateHelper.isEntitySupported(ObservationConstellation.class);
Criteria c = null;
if (obsConstSupported) {
c = getDefaultCriteria(session);
c.add(Subqueries.propertyIn(Procedure.ID,
getDetachedCriteriaProceduresForOfferingFromObservationConstellation(offeringIdentifier, session)));
c.setProjection(Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
} else {
AbstractObservationDAO observationDAO = DaoFactory.getInstance().getObservationDAO();
c = observationDAO.getDefaultObservationInfoCriteria(session);
if (observationDAO instanceof SeriesObservationDAO) {
Criteria seriesCriteria = c.createCriteria(SeriesObservationInfo.SERIES);
seriesCriteria.createCriteria(Series.PROCEDURE).setProjection(
Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
} else {
c.createCriteria(AbstractObservation.PROCEDURE).setProjection(
Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
}
new OfferingDAO().addOfferingRestricionForObservation(c, offeringIdentifier);
}
LOGGER.debug(
"QUERY getProcedureIdentifiersForOffering(offeringIdentifier) using ObservationContellation entitiy ({}): {}",
obsConstSupported, HibernateHelper.getSqlString(c));
return c.list();
}
private Criteria getDefaultCriteria(Session session) {
return session.createCriteria(Procedure.class).add(Restrictions.eq(Procedure.DELETED, false))
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
}
private Criteria getDefaultTProcedureCriteria(Session session) {
return session.createCriteria(TProcedure.class).add(Restrictions.eq(Procedure.DELETED, false))
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
}
private Criteria getDefaultTProcedureCriteriaIncludeDeleted(Session session) {
return session.createCriteria(TProcedure.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
}
/**
* Get procedure identifiers for observable property identifier
*
* @param observablePropertyIdentifier
* Observable property identifier
* @param session
* Hibernate session
* @return Procedure identifiers
* @throws CodedException
*/
@SuppressWarnings("unchecked")
public Collection<String> getProcedureIdentifiersForObservableProperty(final String observablePropertyIdentifier,
final Session session) throws CodedException {
final boolean flag = HibernateHelper.isEntitySupported(ObservationConstellation.class);
Criteria c = null;
if (flag) {
c = getDefaultCriteria(session);
c.setProjection(Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
c.add(Subqueries.propertyIn(
Procedure.ID,
getDetachedCriteriaProceduresForObservablePropertyFromObservationConstellation(
observablePropertyIdentifier, session)));
} else {
if (EntitiyHelper.getInstance().isSeriesSupported()) {
c = getDefaultCriteria(session);
c.setProjection(Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
c.add(Subqueries.propertyIn(
Procedure.ID,
getDetachedCriteriaProceduresForObservablePropertyFromSeries(observablePropertyIdentifier,
session)));
} else {
c = session.createCriteria(ObservationInfo.class).add(Restrictions.eq(ObservationInfo.DELETED, false));
c.createCriteria(ObservationInfo.PROCEDURE).setProjection(
Projections.distinct(Projections.property(Procedure.IDENTIFIER)));
c.createCriteria(ObservationInfo.OBSERVABLE_PROPERTY).add(
Restrictions.eq(ObservableProperty.IDENTIFIER, observablePropertyIdentifier));
}
}
LOGGER.debug(
"QUERY getProcedureIdentifiersForObservableProperty(observablePropertyIdentifier) using ObservationContellation entitiy ({}): {}",
flag, HibernateHelper.getSqlString(c));
return c.list();
}
/**
* Get transactional procedure object for procedure identifier
*
* @param identifier
* Procedure identifier
* @param session
* Hibernate session
* @return Transactional procedure object
*/
public TProcedure getTProcedureForIdentifier(final String identifier, final Session session) {
Criteria criteria = getDefaultTProcedureCriteria(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
LOGGER.debug("QUERY getTProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
return (TProcedure) criteria.uniqueResult();
}
/**
* Get transactional procedure object for procedure identifier, include deleted
*
* @param identifier
* Procedure identifier
* @param session
* Hibernate session
* @return Transactional procedure object
*/
public TProcedure getTProcedureForIdentifierIncludeDeleted(String identifier, Session session) {
Criteria criteria = getDefaultTProcedureCriteriaIncludeDeleted(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
LOGGER.debug("QUERY getTProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
return (TProcedure) criteria.uniqueResult();
}
/**
* Get transactional procedure object for procedure identifier and
* procedureDescriptionFormat
*
* @param identifier
* Procedure identifier
* @param procedureDescriptionFormat
* ProcedureDescriptionFormat identifier
* @param session
* Hibernate session
* @return Transactional procedure object
* @throws UnsupportedOperatorException
* @throws UnsupportedValueReferenceException
* @throws UnsupportedTimeException
*/
public TProcedure getTProcedureForIdentifier(final String identifier, String procedureDescriptionFormat,
Time validTime, final Session session) throws UnsupportedTimeException,
UnsupportedValueReferenceException, UnsupportedOperatorException {
Criteria criteria =
getDefaultTProcedureCriteria(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
Criteria createValidProcedureTime = criteria.createCriteria(TProcedure.VALID_PROCEDURE_TIME);
Criterion validTimeCriterion = QueryHelper.getValidTimeCriterion(validTime);
if (validTime == null || validTimeCriterion == null) {
createValidProcedureTime.add(Restrictions.isNull(ValidProcedureTime.END_TIME));
} else {
createValidProcedureTime.add(validTimeCriterion);
}
createValidProcedureTime.createCriteria(ValidProcedureTime.PROCEDURE_DESCRIPTION_FORMAT).add(
Restrictions.eq(ProcedureDescriptionFormat.PROCEDURE_DESCRIPTION_FORMAT, procedureDescriptionFormat));
LOGGER.debug("QUERY getTProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
return (TProcedure) criteria.uniqueResult();
}
/**
* Get transactional procedure object for procedure identifier and
* procedureDescriptionFormats
*
* @param identifier
* Procedure identifier
* @param procedureDescriptionFormats
* ProcedureDescriptionFormat identifiers
* @param session
* Hibernate session
* @return Transactional procedure object
*/
public TProcedure getTProcedureForIdentifier(final String identifier, Set<String> procedureDescriptionFormats,
final Session session) {
Criteria criteria =
getDefaultTProcedureCriteria(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
criteria.createCriteria(TProcedure.VALID_PROCEDURE_TIME).add(
Restrictions.in(ValidProcedureTime.PROCEDURE_DESCRIPTION_FORMAT, procedureDescriptionFormats));
LOGGER.debug("QUERY getTProcedureForIdentifier(identifier): {}", HibernateHelper.getSqlString(criteria));
return (TProcedure) criteria.uniqueResult();
}
/**
* Get procedure for identifier, possible procedureDescriptionFormats and
* valid time
*
* @param identifier
* Identifier of the procedure
* @param possibleProcedureDescriptionFormats
* Possible procedureDescriptionFormats
* @param validTime
* Valid time of the procedure
* @param session
* Hibernate Session
* @return Procedure entity that match the parameters
* @throws UnsupportedTimeException
* If the time is not supported
* @throws UnsupportedValueReferenceException
* If the valueReference is not supported
* @throws UnsupportedOperatorException
* If the temporal operator is not supported
*/
public TProcedure getTProcedureForIdentifier(String identifier, Set<String> possibleProcedureDescriptionFormats,
Time validTime, Session session) throws UnsupportedTimeException, UnsupportedValueReferenceException,
UnsupportedOperatorException {
Criteria criteria =
getDefaultTProcedureCriteria(session).add(Restrictions.eq(Procedure.IDENTIFIER, identifier));
Criteria createValidProcedureTime = criteria.createCriteria(TProcedure.VALID_PROCEDURE_TIME);
Criterion validTimeCriterion = QueryHelper.getValidTimeCriterion(validTime);
if (validTime == null || validTimeCriterion == null) {
createValidProcedureTime.add(Restrictions.isNull(ValidProcedureTime.END_TIME));
} else {
createValidProcedureTime.add(validTimeCriterion);
}
createValidProcedureTime.createCriteria(ValidProcedureTime.PROCEDURE_DESCRIPTION_FORMAT).add(
Restrictions.in(ProcedureDescriptionFormat.PROCEDURE_DESCRIPTION_FORMAT,
possibleProcedureDescriptionFormats));
LOGGER.debug(
"QUERY getTProcedureForIdentifier(identifier, possibleProcedureDescriptionFormats, validTime): {}",
HibernateHelper.getSqlString(criteria));
return (TProcedure) criteria.uniqueResult();
}
public boolean isProcedureTimeExtremaNamedQuerySupported(Session session) {
return HibernateHelper.isNamedQuerySupported(SQL_QUERY_GET_PROCEDURE_TIME_EXTREMA, session);
}
public TimeExtrema getProcedureTimeExtremaFromNamedQuery(Session session, String procedureIdentifier) {
Object[] result = null;
if (isProcedureTimeExtremaNamedQuerySupported(session)) {
Query namedQuery = session.getNamedQuery(SQL_QUERY_GET_PROCEDURE_TIME_EXTREMA);
namedQuery.setParameter(PROCEDURE, procedureIdentifier);
LOGGER.debug("QUERY getProcedureTimeExtrema({}) with NamedQuery '{}': {}", procedureIdentifier,
SQL_QUERY_GET_PROCEDURE_TIME_EXTREMA, namedQuery.getQueryString());
result = (Object[]) namedQuery.uniqueResult();
}
return parseProcedureTimeExtremaResult(result);
}
private TimeExtrema parseProcedureTimeExtremaResult(Object[] result) {
TimeExtrema pte = new TimeExtrema();
if (result != null) {
pte.setMinTime(DateTimeHelper.makeDateTime(result[1]));
DateTime maxPhenStart = DateTimeHelper.makeDateTime(result[2]);
DateTime maxPhenEnd = DateTimeHelper.makeDateTime(result[3]);
pte.setMaxTime(DateTimeHelper.max(maxPhenStart, maxPhenEnd));
}
return pte;
}
/**
* Query procedure time extrema for the provided procedure identifier
*
* @param session
* @param procedureIdentifier
* @return ProcedureTimeExtrema
* @throws CodedException
*/
public TimeExtrema getProcedureTimeExtrema(final Session session, String procedureIdentifier)
throws OwsExceptionReport {
Object[] result;
if (isProcedureTimeExtremaNamedQuerySupported(session)) {
return getProcedureTimeExtremaFromNamedQuery(session, procedureIdentifier);
}
AbstractObservationDAO observationDAO = DaoFactory.getInstance().getObservationDAO();
Criteria criteria = observationDAO.getDefaultObservationInfoCriteria(session);
if (observationDAO instanceof AbstractSeriesObservationDAO) {
criteria.createAlias(SeriesObservationInfo.SERIES, "s");
criteria.createAlias("s." + Series.PROCEDURE, "p");
} else {
criteria.createAlias(ObservationInfo.PROCEDURE, "p");
}
criteria.add(Restrictions.eq("p." + Procedure.IDENTIFIER, procedureIdentifier));
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.groupProperty("p." + Procedure.IDENTIFIER));
projectionList.add(Projections.min(AbstractObservation.PHENOMENON_TIME_START));
projectionList.add(Projections.max(AbstractObservation.PHENOMENON_TIME_START));
projectionList.add(Projections.max(AbstractObservation.PHENOMENON_TIME_END));
criteria.setProjection(projectionList);
LOGGER.debug("QUERY getProcedureTimeExtrema(procedureIdentifier): {}", HibernateHelper.getSqlString(criteria));
result = (Object[]) criteria.uniqueResult();
return parseProcedureTimeExtremaResult(result);
}
/**
* Get min time from observations for procedure
*
* @param procedure
* Procedure identifier
* @param session
* Hibernate session
* @return min time for procedure
* @throws CodedException
*/
public DateTime getMinDate4Procedure(final String procedure, final Session session) throws OwsExceptionReport {
Object min = null;
if (HibernateHelper.isNamedQuerySupported(SQL_QUERY_GET_MIN_DATE_FOR_PROCEDURE, session)) {
Query namedQuery = session.getNamedQuery(SQL_QUERY_GET_MIN_DATE_FOR_PROCEDURE);
namedQuery.setParameter(PROCEDURE, procedure);
LOGGER.debug("QUERY getMinDate4Procedure(procedure) with NamedQuery: {}",
SQL_QUERY_GET_MIN_DATE_FOR_PROCEDURE);
min = namedQuery.uniqueResult();
} else {
AbstractObservationDAO observationDAO = DaoFactory.getInstance().getObservationDAO();
Criteria criteria = observationDAO.getDefaultObservationInfoCriteria(session);
if (observationDAO instanceof SeriesObservationDAO) {
addProcedureRestrictionForSeries(criteria, procedure);
} else {
addProcedureRestrictionForObservation(criteria, procedure);
}
addMinMaxProjection(criteria, MinMax.MIN, AbstractObservation.PHENOMENON_TIME_START);
LOGGER.debug("QUERY getMinDate4Procedure(procedure): {}", HibernateHelper.getSqlString(criteria));
min = criteria.uniqueResult();
}
if (min != null) {
return new DateTime(min, DateTimeZone.UTC);
}
return null;
}
/**
* Get max time from observations for procedure
*
* @param procedure
* Procedure identifier
* @param session
* Hibernate session
* @return max time for procedure
* @throws CodedException
*/
public DateTime getMaxDate4Procedure(final String procedure, final Session session) throws OwsExceptionReport {
Object maxStart = null;
Object maxEnd = null;
if (HibernateHelper.isNamedQuerySupported(SQL_QUERY_GET_MAX_DATE_FOR_PROCEDURE, session)) {
Query namedQuery = session.getNamedQuery(SQL_QUERY_GET_MAX_DATE_FOR_PROCEDURE);
namedQuery.setParameter(PROCEDURE, procedure);
LOGGER.debug("QUERY getMaxDate4Procedure(procedure) with NamedQuery: {}",
SQL_QUERY_GET_MAX_DATE_FOR_PROCEDURE);
maxStart = namedQuery.uniqueResult();
maxEnd = maxStart;
} else {
AbstractObservationDAO observationDAO = DaoFactory.getInstance().getObservationDAO();
Criteria cstart = observationDAO.getDefaultObservationInfoCriteria(session);
Criteria cend = observationDAO.getDefaultObservationInfoCriteria(session);
if (observationDAO instanceof SeriesObservationDAO) {
addProcedureRestrictionForSeries(cstart, procedure);
addProcedureRestrictionForSeries(cend, procedure);
} else {
addProcedureRestrictionForObservation(cstart, procedure);
addProcedureRestrictionForObservation(cend, procedure);
}
addMinMaxProjection(cstart, MinMax.MAX, AbstractObservation.PHENOMENON_TIME_START);
addMinMaxProjection(cend, MinMax.MAX, AbstractObservation.PHENOMENON_TIME_END);
LOGGER.debug("QUERY getMaxDate4Procedure(procedure) start: {}", HibernateHelper.getSqlString(cstart));
LOGGER.debug("QUERY getMaxDate4Procedure(procedure) end: {}", HibernateHelper.getSqlString(cend));
if (HibernateHelper.getSqlString(cstart).endsWith(HibernateHelper.getSqlString(cend))) {
maxStart = cstart.uniqueResult();
maxEnd = maxStart;
LOGGER.debug("Max time start and end query are identically, only one query is executed!");
} else {
maxStart = cstart.uniqueResult();
maxEnd = cend.uniqueResult();
}
}
if (maxStart == null && maxEnd == null) {
return null;
} else {
final DateTime start = new DateTime(maxStart, DateTimeZone.UTC);
if (maxEnd != null) {
final DateTime end = new DateTime(maxEnd, DateTimeZone.UTC);
if (end.isAfter(start)) {
return end;
}
}
return start;
}
}
/**
* Insert and get procedure object
*
* @param identifier
* Procedure identifier
* @param procedureDecriptionFormat
* Procedure description format object
* @param parentProcedures
* Parent procedure identifiers
* @param session
* Hibernate session
* @return Procedure object
*/
public Procedure getOrInsertProcedure(final String identifier,
final ProcedureDescriptionFormat procedureDecriptionFormat, final Collection<String> parentProcedures,
final Session session) {
Procedure procedure = getProcedureForIdentifierIncludeDeleted(identifier, session);
if (procedure == null) {
final TProcedure tProcedure = new TProcedure();
tProcedure.setProcedureDescriptionFormat(procedureDecriptionFormat);
tProcedure.setIdentifier(identifier);
if (CollectionHelper.isNotEmpty(parentProcedures)) {
tProcedure.setParents(Sets.newHashSet(getProceduresForIdentifiers(parentProcedures, session)));
}
procedure = tProcedure;
}
procedure.setDeleted(false);
session.saveOrUpdate(procedure);
session.flush();
session.refresh(procedure);
return procedure;
}
/**
* Get Hibernate Detached Criteria for class Series and featureOfInterest
* identifier
*
* @param featureOfInterest
* FeatureOfInterest identifier parameter
* @param session
* Hibernate session
* @return Hiberante Detached Criteria with Procedure entities
* @throws CodedException
*/
private DetachedCriteria getDetachedCriteriaProceduresForFeatureOfInterestFromSeries(
FeatureOfInterest featureOfInterest, Session session) throws CodedException {
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(DaoFactory.getInstance().getSeriesDAO().getClass());
detachedCriteria.add(Restrictions.eq(Series.DELETED, false));
detachedCriteria.add(Restrictions.eq(Series.FEATURE_OF_INTEREST, featureOfInterest));
detachedCriteria.setProjection(Projections.distinct(Projections.property(Series.PROCEDURE)));
return detachedCriteria;
}
/**
* Get Hibernate Detached Criteria for class ObservationConstellation and
* observableProperty identifier
*
* @param observablePropertyIdentifier
* ObservableProperty identifier parameter
* @param session
* Hibernate session
* @return Hiberante Detached Criteria with Procedure entities
*/
private DetachedCriteria getDetachedCriteriaProceduresForObservablePropertyFromObservationConstellation(
String observablePropertyIdentifier, Session session) {
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ObservationConstellation.class);
detachedCriteria.add(Restrictions.eq(ObservationConstellation.DELETED, false));
detachedCriteria.createCriteria(ObservationConstellation.OBSERVABLE_PROPERTY).add(
Restrictions.eq(ObservableProperty.IDENTIFIER, observablePropertyIdentifier));
detachedCriteria.setProjection(Projections.distinct(Projections.property(ObservationConstellation.PROCEDURE)));
return detachedCriteria;
}
/**
* Get Hibernate Detached Criteria for class Series and observableProperty
* identifier
*
* @param observablePropertyIdentifier
* ObservableProperty identifier parameter
* @param session
* Hibernate session
* @return Hiberante Detached Criteria with Procedure entities
* @throws CodedException
*/
private DetachedCriteria getDetachedCriteriaProceduresForObservablePropertyFromSeries(
String observablePropertyIdentifier, Session session) throws CodedException {
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(DaoFactory.getInstance().getSeriesDAO().getClass());
detachedCriteria.add(Restrictions.eq(Series.DELETED, false));
detachedCriteria.createCriteria(Series.OBSERVABLE_PROPERTY).add(
Restrictions.eq(ObservableProperty.IDENTIFIER, observablePropertyIdentifier));
detachedCriteria.setProjection(Projections.distinct(Projections.property(Series.PROCEDURE)));
return detachedCriteria;
}
/**
* Get Hibernate Detached Criteria for class ObservationConstellation and
* offering identifier
*
* @param offeringIdentifier
* Offering identifier parameter
* @param session
* Hibernate session
* @return Detached Criteria with Procedure entities
*/
private DetachedCriteria getDetachedCriteriaProceduresForOfferingFromObservationConstellation(
String offeringIdentifier, Session session) {
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ObservationConstellation.class);
detachedCriteria.add(Restrictions.eq(ObservationConstellation.DELETED, false));
detachedCriteria.createCriteria(ObservationConstellation.OFFERING).add(
Restrictions.eq(Offering.IDENTIFIER, offeringIdentifier));
detachedCriteria.setProjection(Projections.distinct(Projections.property(ObservationConstellation.PROCEDURE)));
return detachedCriteria;
}
/**
* Add procedure identifier restriction to Hibernate Criteria for series
*
* @param criteria
* Hibernate Criteria for series to add restriction
* @param procedure
* Procedure identifier
*/
private void addProcedureRestrictionForSeries(Criteria criteria, String procedure) {
Criteria seriesCriteria = criteria.createCriteria(SeriesObservationInfo.SERIES);
seriesCriteria.createCriteria(SeriesObservationInfo.PROCEDURE).add(
Restrictions.eq(Procedure.IDENTIFIER, procedure));
}
/**
* Add procedure identifier restriction to Hibernate Criteria
*
* @param criteria
* Hibernate Criteria to add restriction
* @param procedure
* Procedure identifier
*/
private void addProcedureRestrictionForObservation(Criteria criteria, String procedure) {
criteria.createCriteria(ObservationInfo.PROCEDURE).add(Restrictions.eq(Procedure.IDENTIFIER, procedure));
}
@SuppressWarnings("unchecked")
protected Set<String> getObservationIdentifiers(Session session, String procedureIdentifier) {
if (EntitiyHelper.getInstance().isSeriesObservationInfoSupported()) {
Criteria criteria =
session.createCriteria(EntitiyHelper.getInstance().getObservationInfoEntityClass())
.setProjection(
Projections.distinct(Projections.property(SeriesObservationInfo.IDENTIFIER)))
.add(Restrictions.isNotNull(SeriesObservationInfo.IDENTIFIER))
.add(Restrictions.eq(SeriesObservationInfo.DELETED, false));
Criteria seriesCriteria = criteria.createCriteria(SeriesObservationInfo.SERIES);
seriesCriteria.createCriteria(Series.PROCEDURE).add(
Restrictions.eq(Procedure.IDENTIFIER, procedureIdentifier));
LOGGER.debug("QUERY getObservationIdentifiers(procedureIdentifier): {}",
HibernateHelper.getSqlString(criteria));
return Sets.newHashSet(criteria.list());
} else {
Criteria criteria =
session.createCriteria(EntitiyHelper.getInstance().getObservationInfoEntityClass())
.setProjection(Projections.distinct(Projections.property(ObservationInfo.IDENTIFIER)))
.add(Restrictions.isNotNull(ObservationInfo.IDENTIFIER))
.add(Restrictions.eq(ObservationInfo.DELETED, false));
criteria.createCriteria(ObservationInfo.PROCEDURE).add(
Restrictions.eq(Procedure.IDENTIFIER, procedureIdentifier));
LOGGER.debug("QUERY getObservationIdentifiers(procedureIdentifier): {}",
HibernateHelper.getSqlString(criteria));
return Sets.newHashSet(criteria.list());
}
}
public Map<String,String> getProcedureFormatMap(Session session) {
if (HibernateHelper.isEntitySupported(TProcedure.class)) {
//get the latest validProcedureTimes' procedureDescriptionFormats
return new ValidProcedureTimeDAO().getTProcedureFormatMap(session);
} else {
Criteria criteria = getDefaultCriteria(session);
criteria.createAlias(Procedure.PROCEDURE_DESCRIPTION_FORMAT, "pdf");
criteria.setProjection(Projections.projectionList()
.add(Projections.property(Procedure.IDENTIFIER))
.add(Projections.property("pdf." + ProcedureDescriptionFormat.PROCEDURE_DESCRIPTION_FORMAT)));
criteria.addOrder(Order.asc(Procedure.IDENTIFIER));
LOGGER.debug("QUERY getProcedureFormatMap(): {}", HibernateHelper.getSqlString(criteria));
@SuppressWarnings("unchecked")
List<Object[]> results = criteria.list();
Map<String,String> procedureFormatMap = Maps.newTreeMap();
for (Object[] result : results) {
String procedureIdentifier = (String) result[0];
String format = (String) result[1];
procedureFormatMap.put(procedureIdentifier, format);
}
return procedureFormatMap;
}
}
@SuppressWarnings("unchecked")
public List<Procedure> getPublishedProcedure(Session session) throws CodedException {
if (HibernateHelper.isEntitySupported(Series.class)) {
Criteria c = session.createCriteria(Procedure.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.add(Subqueries.propertyIn(Procedure.ID, getDetachedCriteriaSeries(session)));
return c.list();
}
return getProcedureObjects(session);
}
private DetachedCriteria getDetachedCriteriaSeries(Session session) throws CodedException {
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(DaoFactory.getInstance().getSeriesDAO().getSeriesClass());
detachedCriteria.add(Restrictions.eq(Series.DELETED, false)).add(Restrictions.eq(Series.PUBLISHED, true));
detachedCriteria.setProjection(Projections.distinct(Projections.property(Series.PROCEDURE)));
return detachedCriteria;
}
}