/** * 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; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.criterion.Disjunction; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.spatial.criterion.SpatialProjections; import org.n52.sos.config.annotation.Configurable; import org.n52.sos.ds.FeatureQueryHandler; import org.n52.sos.ds.FeatureQueryHandlerQueryObject; import org.n52.sos.ds.HibernateDatasourceConstants; import org.n52.sos.ds.I18NDAO; import org.n52.sos.ds.hibernate.dao.DaoFactory; import org.n52.sos.ds.hibernate.dao.FeatureOfInterestDAO; import org.n52.sos.ds.hibernate.dao.FeatureOfInterestTypeDAO; import org.n52.sos.ds.hibernate.dao.HibernateSqlQueryConstants; import org.n52.sos.ds.hibernate.entities.FeatureOfInterest; import org.n52.sos.ds.hibernate.entities.TFeatureOfInterest; import org.n52.sos.ds.hibernate.util.HibernateConstants; import org.n52.sos.ds.hibernate.util.HibernateGeometryCreator; import org.n52.sos.ds.hibernate.util.HibernateHelper; import org.n52.sos.ds.hibernate.util.SpatialRestrictions; import org.n52.sos.exception.ows.NoApplicableCodeException; import org.n52.sos.exception.ows.concrete.NotYetSupportedException; import org.n52.sos.i18n.I18NDAORepository; import org.n52.sos.i18n.LocalizedString; import org.n52.sos.i18n.metadata.I18NFeatureMetadata; import org.n52.sos.ogc.OGCConstants; import org.n52.sos.ogc.filter.SpatialFilter; import org.n52.sos.ogc.gml.AbstractFeature; import org.n52.sos.ogc.gml.CodeWithAuthority; import org.n52.sos.ogc.om.features.samplingFeatures.SamplingFeature; import org.n52.sos.ogc.ows.OwsExceptionReport; import org.n52.sos.ogc.sos.SosConstants; import org.n52.sos.ogc.sos.SosEnvelope; import org.n52.sos.service.ServiceConfiguration; import org.n52.sos.util.CollectionHelper; import org.n52.sos.util.GeometryHandler; import org.n52.sos.util.JavaHelper; import org.n52.sos.util.SosHelper; import org.n52.sos.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; @Configurable public class HibernateFeatureQueryHandler implements FeatureQueryHandler, HibernateSqlQueryConstants { private static final Logger LOGGER = LoggerFactory.getLogger(HibernateFeatureQueryHandler.class); @Deprecated @Override public AbstractFeature getFeatureByID(String featureID, Object connection, String version) throws OwsExceptionReport { FeatureQueryHandlerQueryObject queryObject = new FeatureQueryHandlerQueryObject(); queryObject.setConnection(connection); queryObject.addFeatureIdentifier(featureID); queryObject.setVersion(version); return getFeatureByID(queryObject); } @Override public AbstractFeature getFeatureByID(FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { final Session session = HibernateSessionHolder.getSession(queryObject.getConnection()); try { final Criteria q = session.createCriteria(FeatureOfInterest.class).add( Restrictions.eq(FeatureOfInterest.IDENTIFIER, queryObject.getFeatureIdentifier())); return createSosAbstractFeature((FeatureOfInterest) q.uniqueResult(), queryObject); } catch (final HibernateException he) { throw new NoApplicableCodeException().causedBy(he).withMessage( "An error occurred while querying feature data for a featureOfInterest identifier!"); } } @Deprecated @Override @SuppressWarnings("unchecked") public Collection<String> getFeatureIDs(final SpatialFilter filter, final Object connection) throws OwsExceptionReport { final Session session = HibernateSessionHolder.getSession(connection); try { if (getGeometryHandler().isSpatialDatasource()) { final Criteria c = session.createCriteria(FeatureOfInterest.class).setProjection( Projections.distinct(Projections.property(FeatureOfInterest.IDENTIFIER))); if (filter != null) { c.add(SpatialRestrictions.filter(FeatureOfInterest.GEOMETRY, filter.getOperator(), getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(filter.getGeometry()))); } return c.list(); } else { final List<String> identifiers = new LinkedList<String>(); final List<FeatureOfInterest> features = session.createCriteria(FeatureOfInterest.class).list(); if (filter != null) { final Geometry envelope = getGeometryHandler().getFilterForNonSpatialDatasource(filter); for (final FeatureOfInterest feature : features) { final Geometry geom = getGeomtery(feature, session); if (geom != null && envelope.contains(geom)) { identifiers.add(feature.getIdentifier()); } } } return identifiers; } } catch (final HibernateException he) { throw new NoApplicableCodeException().causedBy(he).withMessage( "An error occurred while querying feature identifiers for spatial filter!"); } } @Override public Collection<String> getFeatureIDs(FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { return getFeatureIDs(queryObject.getSpatialFitler(), queryObject.getConnection()); } @Deprecated @Override public Map<String, AbstractFeature> getFeatures(Collection<String> featureIDs, List<SpatialFilter> spatialFilters, Object connection, String version) throws OwsExceptionReport { FeatureQueryHandlerQueryObject queryObject = new FeatureQueryHandlerQueryObject(); queryObject.setFeatureIdentifiers(featureIDs); queryObject.setSpatialFilters(spatialFilters); queryObject.setConnection(connection); queryObject.setVersion(version); return getFeatures(queryObject); } @Override public Map<String, AbstractFeature> getFeatures(FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { try { if (getGeometryHandler().isSpatialDatasource()) { return getFeaturesForSpatialDatasource(queryObject); } else { return getFeaturesForNonSpatialDatasource(queryObject); } } catch (final HibernateException he) { throw new NoApplicableCodeException().causedBy(he).withMessage( "Error while querying features from data source!"); } } @Deprecated @Override public SosEnvelope getEnvelopeForFeatureIDs(Collection<String> featureIDs, Object connection) throws OwsExceptionReport { return getEnvelopeForFeatureIDs(new FeatureQueryHandlerQueryObject().setFeatureIdentifiers(featureIDs) .setConnection(connection)); } @Override public SosEnvelope getEnvelopeForFeatureIDs(FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { final Session session = HibernateSessionHolder.getSession(queryObject.getConnection()); if (queryObject.isSetFeatureIdentifiers()) { try { // XXX workaround for Hibernate Spatial's lack of support for // GeoDB's extent aggregate // see // http://www.hibernatespatial.org/pipermail/hibernatespatial-users/2013-August/000876.html Dialect dialect = ((SessionFactoryImplementor) session.getSessionFactory()).getDialect(); if (getGeometryHandler().isSpatialDatasource() && HibernateHelper.supportsFunction(dialect, HibernateConstants.FUNC_EXTENT)) { // Criteria featureExtentCriteria = // session.createCriteria(FeatureOfInterest.class) // .add(Restrictions.in(FeatureOfInterest.IDENTIFIER, // featureIDs)) // .setProjection(SpatialProjections.extent(FeatureOfInterest.GEOMETRY)); // LOGGER.debug("QUERY getEnvelopeForFeatureIDs(featureIDs): {}", // HibernateHelper.getSqlString(featureExtentCriteria)); // Geometry geom = (Geometry) // featureExtentCriteria.uniqueResult(); Geometry geom = (Geometry) session .createCriteria(FeatureOfInterest.class) .add(Restrictions.in(FeatureOfInterest.IDENTIFIER, queryObject.getFeatureIdentifiers())) .setProjection(SpatialProjections.extent(FeatureOfInterest.GEOMETRY)) .uniqueResult(); if (geom != null) { int srid = geom.getSRID() > 0 ? geom.getSRID() : getStorageEPSG(); geom.setSRID(srid); geom = getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(geom); return new SosEnvelope(geom.getEnvelopeInternal(), srid); } } else { final Envelope envelope = new Envelope(); final List<FeatureOfInterest> featuresOfInterest = new FeatureOfInterestDAO().getFeatureOfInterestObject(queryObject.getFeatureIdentifiers(), session); for (final FeatureOfInterest feature : featuresOfInterest) { try { // TODO Check if prepareGeometryForResponse required // transform/switch // final Geometry geom = // getGeometryHandler().prepareGeometryForResponse(getGeomtery(feature), // queryObject.getRequestedSrid()); final Geometry geom = getGeomtery(feature, session); if (geom != null) { envelope.expandToInclude(geom.getEnvelopeInternal()); } } catch (final OwsExceptionReport owse) { LOGGER.warn( String.format("Error while adding '%s' to envelope!", feature.getFeatureOfInterestId()), owse); } } if (!envelope.isNull()) { return new SosEnvelope(envelope, getDefaultEPSG()); } } } catch (final HibernateException he) { throw new NoApplicableCodeException().causedBy(he).withMessage( "Exception thrown while requesting global feature envelope"); } } return null; } /* * (non-Javadoc) * * @see * org.n52.sos.ds.FeatureQueryHandler#insertFeature(org.n52.sos.ogc.om.features * .samplingFeatures.SamplingFeature, java.lang.Object) * * FIXME check semantics of this method in respect to its name and the * documentation in the super class */ @Override public String insertFeature(final SamplingFeature samplingFeature, final Object connection) throws OwsExceptionReport { if (StringHelper.isNotEmpty(samplingFeature.getUrl())) { if (samplingFeature.isSetIdentifier()) { return samplingFeature.getIdentifierCodeWithAuthority().getValue(); } else { return samplingFeature.getUrl(); } } else { final Session session = HibernateSessionHolder.getSession(connection); String featureIdentifier; if (!samplingFeature.isSetIdentifier()) { featureIdentifier = SosConstants.GENERATED_IDENTIFIER_PREFIX + JavaHelper.generateID(samplingFeature.getXmlDescription()); samplingFeature.setIdentifier(new CodeWithAuthority(featureIdentifier)); } return insertFeatureOfInterest(samplingFeature, session).getIdentifier(); } } @Deprecated @Override public int getDefaultEPSG() { return getStorageEPSG(); } @Deprecated @Override public int getDefault3DEPSG() { return getStorage3DEPSG(); } @Override public int getStorageEPSG() { return getGeometryHandler().getStorageEPSG(); } @Override public int getStorage3DEPSG() { return getGeometryHandler().getStorage3DEPSG(); } @Override public int getDefaultResponseEPSG() { return getGeometryHandler().getDefaultResponseEPSG(); } @Override public int getDefaultResponse3DEPSG() { return getGeometryHandler().getDefaultResponse3DEPSG(); } protected GeometryHandler getGeometryHandler() { return GeometryHandler.getInstance(); } private boolean isFeatureReferenced(final SamplingFeature samplingFeature) { return StringHelper.isNotEmpty(samplingFeature.getUrl()); } /** * Creates a map with FOI identifier and SOS feature * <p/> * * @param features * FeatureOfInterest objects * @param queryObject * SOS version * <p/> * @return Map with FOI identifier and SOS feature * <p/> * @throws OwsExceptionReport * * If feature type is not supported */ protected Map<String, AbstractFeature> createSosFeatures(final List<FeatureOfInterest> features, final FeatureQueryHandlerQueryObject queryObject, Session session) throws OwsExceptionReport { final Map<String, AbstractFeature> sosAbstractFois = new HashMap<String, AbstractFeature>(); for (final FeatureOfInterest feature : features) { final AbstractFeature sosFeature = createSosAbstractFeature(feature, queryObject, session); sosAbstractFois.put(feature.getIdentifier(), sosFeature); } // TODO if sampledFeatures are also in sosAbstractFois, reference them. return sosAbstractFois; } protected FeatureOfInterest getFeatureOfInterest(final String identifier, final Geometry geometry, final Session session) throws OwsExceptionReport { if (!identifier.startsWith(SosConstants.GENERATED_IDENTIFIER_PREFIX)) { return (FeatureOfInterest) session.createCriteria(FeatureOfInterest.class) .add(Restrictions.eq(FeatureOfInterest.IDENTIFIER, identifier)).uniqueResult(); } else { return (FeatureOfInterest) session.createCriteria(FeatureOfInterest.class) .add(SpatialRestrictions.eq(FeatureOfInterest.GEOMETRY, getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(geometry))) .uniqueResult(); } } protected AbstractFeature createSosAbstractFeature(final FeatureOfInterest feature, final FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { final Session session = HibernateSessionHolder.getSession(queryObject.getConnection()); return createSosAbstractFeature(feature, queryObject, session); } /** * Creates a SOS feature from the FeatureOfInterest object * * @param feature * FeatureOfInterest object * @param version * SOS version * @return SOS feature * @throws OwsExceptionReport */ protected AbstractFeature createSosAbstractFeature(final FeatureOfInterest feature, final FeatureQueryHandlerQueryObject queryObject, Session session) throws OwsExceptionReport { if (feature == null) { return null; } FeatureOfInterestDAO featureOfInterestDAO = new FeatureOfInterestDAO(); final CodeWithAuthority identifier = featureOfInterestDAO.getIdentifier(feature); if (!SosHelper.checkFeatureOfInterestIdentifierForSosV2(feature.getIdentifier(), queryObject.getVersion())) { identifier.setValue(null); } final SamplingFeature sampFeat = new SamplingFeature(identifier); addNameAndDescription(queryObject, feature, sampFeat, featureOfInterestDAO); sampFeat.setGeometry(getGeomtery(feature, session)); sampFeat.setFeatureType(feature.getFeatureOfInterestType().getFeatureOfInterestType()); sampFeat.setUrl(feature.getUrl()); if (feature.isSetDescriptionXml()) { sampFeat.setXmlDescription(feature.getDescriptionXml()); } if (feature instanceof TFeatureOfInterest) { final Set<FeatureOfInterest> parentFeatures = ((TFeatureOfInterest) feature).getParents(); if (parentFeatures != null && !parentFeatures.isEmpty()) { final List<AbstractFeature> sampledFeatures = new ArrayList<AbstractFeature>(parentFeatures.size()); for (final FeatureOfInterest parentFeature : parentFeatures) { sampledFeatures.add(createSosAbstractFeature(parentFeature, queryObject, session)); } sampFeat.setSampledFeatures(sampledFeatures); } } return sampFeat; } private void addNameAndDescription(FeatureQueryHandlerQueryObject query, FeatureOfInterest feature, SamplingFeature samplingFeature, FeatureOfInterestDAO featureDAO) throws OwsExceptionReport { I18NDAO<I18NFeatureMetadata> i18nDAO = I18NDAORepository.getInstance().getDAO(I18NFeatureMetadata.class); Locale requestedLocale = query.getI18N(); // set name as human readable identifier if set if (feature.isSetName()) { samplingFeature.setHumanReadableIdentifier(feature.getName()); } if (i18nDAO == null) { // no i18n support samplingFeature.addName(featureDAO.getName(feature)); samplingFeature.setDescription(featureDAO.getDescription(feature)); } else { I18NFeatureMetadata i18n = i18nDAO.getMetadata(feature.getIdentifier()); if (requestedLocale != null) { // specific locale was requested Optional<LocalizedString> name = i18n.getName().getLocalizationOrDefault(requestedLocale); if (name.isPresent()) { samplingFeature.addName(name.get().asCodeType()); } Optional<LocalizedString> description = i18n.getDescription().getLocalizationOrDefault(requestedLocale); if (description.isPresent()) { samplingFeature.setDescription(description.get().getText()); } } else { if (ServiceConfiguration.getInstance().isShowAllLanguageValues()) { for (LocalizedString name : i18n.getName()) { samplingFeature.addName(name.asCodeType()); } } else { Optional<LocalizedString> name = i18n.getName().getDefaultLocalization(); if (name.isPresent()) { samplingFeature.addName(name.get().asCodeType()); } } // choose always the description in the default locale Optional<LocalizedString> description = i18n.getDescription().getDefaultLocalization(); if (description.isPresent()) { samplingFeature.setDescription(description.get().getText()); } } } } protected FeatureOfInterest insertFeatureOfInterest(final SamplingFeature samplingFeature, final Session session) throws OwsExceptionReport { if (!getGeometryHandler().isSpatialDatasource()) { throw new NotYetSupportedException("Insertion of full encoded features for non spatial datasources"); } FeatureOfInterestDAO featureOfInterestDAO = new FeatureOfInterestDAO(); final String newId = samplingFeature.getIdentifierCodeWithAuthority().getValue(); FeatureOfInterest feature = getFeatureOfInterest(newId, samplingFeature.getGeometry(), session); if (feature == null) { feature = new TFeatureOfInterest(); featureOfInterestDAO.addIdentifierNameDescription(samplingFeature, feature, session); processGeometryPreSave(samplingFeature, feature, session); if (samplingFeature.isSetXmlDescription()) { feature.setDescriptionXml(samplingFeature.getXmlDescription()); } if (samplingFeature.isSetFeatureType()) { feature.setFeatureOfInterestType(new FeatureOfInterestTypeDAO().getOrInsertFeatureOfInterestType( samplingFeature.getFeatureType(), session)); } if (samplingFeature.isSetSampledFeatures()) { Set<FeatureOfInterest> parents = Sets.newHashSetWithExpectedSize(samplingFeature.getSampledFeatures().size()); for (AbstractFeature sampledFeature : samplingFeature.getSampledFeatures()) { if (!OGCConstants.UNKNOWN.equals(sampledFeature.getIdentifierCodeWithAuthority().getValue())) { if (sampledFeature instanceof SamplingFeature) { parents.add(insertFeatureOfInterest((SamplingFeature) sampledFeature, session)); } else { parents.add(insertFeatureOfInterest(new SamplingFeature(sampledFeature.getIdentifierCodeWithAuthority()), session)); } } } ((TFeatureOfInterest) feature).setParents(parents); } session.save(feature); session.flush(); session.refresh(feature); featureOfInterestDAO.insertNameAndDescription(feature, samplingFeature, session); // return newId; // } else { // return feature.getIdentifier(); } return feature; } protected void processGeometryPreSave(final SamplingFeature ssf, final FeatureOfInterest f, Session session) throws OwsExceptionReport { f.setGeom(getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(ssf.getGeometry())); } /** * Get the geometry from featureOfInterest object. * * @param feature * @return geometry * @throws OwsExceptionReport */ protected Geometry getGeomtery(final FeatureOfInterest feature, Session session) throws OwsExceptionReport { if (feature.isSetGeometry()) { return getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(feature.getGeom()); } else if (feature.isSetLongLat()) { return getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded( new HibernateGeometryCreator(getStorageEPSG(), getStorage3DEPSG()).createGeometry(feature)); // int epsg = getStorageEPSG(); // if (feature.isSetSrid()) { // epsg = feature.getSrid(); // } // final String wktString = // getGeometryHandler().getWktString(feature.getLongitude(), feature.getLatitude(), epsg); // final Geometry geom = JTSHelper.createGeometryFromWKT(wktString, epsg); // if (feature.isSetAltitude()) { // geom.getCoordinate().z = JavaHelper.asDouble(feature.getAltitude()); // if (geom.getSRID() == getStorage3DEPSG()) { // geom.setSRID(getStorage3DEPSG()); // } // } // return geom; // return // getGeometryHandler().switchCoordinateAxisOrderIfNeeded(geom); } else { if (session != null) { int srid = getGeometryHandler().getStorageEPSG(); if (DaoFactory.getInstance().getObservationDAO().getSamplingGeometriesCount(feature.getIdentifier(), session).longValue() > 100) { Envelope envelope = DaoFactory.getInstance().getObservationDAO().getBboxFromSamplingGeometries(feature.getIdentifier(), session); if (envelope != null) { Geometry geometry = new GeometryFactory().toGeometry(envelope); geometry.setSRID(srid); geometry = getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(geometry); } } else { List<Geometry> geometries = DaoFactory.getInstance().getObservationDAO().getSamplingGeometries(feature.getIdentifier(), session); if (!CollectionHelper.nullEmptyOrContainsOnlyNulls(geometries)) { List<Coordinate> coordinates = Lists.newLinkedList(); Geometry lastGeoemtry = null; for (Geometry geometry : geometries) { if (geometry != null && (lastGeoemtry == null || !geometry.equalsTopo(lastGeoemtry))) { coordinates.add(getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(geometry).getCoordinate()); lastGeoemtry = geometry; if (geometry.getSRID() != srid) { srid = geometry.getSRID(); } } if (geometry.getSRID() != srid) { srid = geometry.getSRID(); } if (!geometry.equalsTopo(lastGeoemtry)) { coordinates.add(getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(geometry).getCoordinate()); lastGeoemtry = geometry; } } Geometry geom = null; if (coordinates.size() == 1) { geom = new GeometryFactory().createPoint(coordinates.iterator().next()); } else { geom = new GeometryFactory().createLineString(coordinates.toArray(new Coordinate[coordinates.size()])); } geom.setSRID(srid); return geom; } } } } return null; } protected Map<String, AbstractFeature> getFeaturesForNonSpatialDatasource( FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { final Session session = HibernateSessionHolder.getSession(queryObject.getConnection()); final Map<String, AbstractFeature> featureMap = new HashMap<String, AbstractFeature>(0); List<Geometry> envelopes = null; boolean hasSpatialFilter = false; if (queryObject.isSetSpatialFilters()) { hasSpatialFilter = true; envelopes = new ArrayList<Geometry>(queryObject.getSpatialFilters().size()); for (final SpatialFilter filter : queryObject.getSpatialFilters()) { envelopes.add(getGeometryHandler().getFilterForNonSpatialDatasource(filter)); } } final List<FeatureOfInterest> featuresOfInterest = new FeatureOfInterestDAO().getFeatureOfInterestObject(queryObject.getFeatureIdentifiers(), session); for (final FeatureOfInterest feature : featuresOfInterest) { final SamplingFeature sosAbstractFeature = (SamplingFeature) createSosAbstractFeature(feature, queryObject); if (!hasSpatialFilter) { featureMap.put(sosAbstractFeature.getIdentifierCodeWithAuthority().getValue(), sosAbstractFeature); } else { if (getGeometryHandler().featureIsInFilter(sosAbstractFeature.getGeometry(), envelopes)) { featureMap.put(sosAbstractFeature.getIdentifierCodeWithAuthority().getValue(), sosAbstractFeature); } } } return featureMap; } @SuppressWarnings("unchecked") protected Map<String, AbstractFeature> getFeaturesForSpatialDatasource(FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { final Session session = HibernateSessionHolder.getSession(queryObject.getConnection()); final Criteria c = session.createCriteria(FeatureOfInterest.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); boolean filtered = false; if (queryObject.isSetFeatureIdentifiers()) { c.add(Restrictions.in(FeatureOfInterest.IDENTIFIER, queryObject.getFeatureIdentifiers())); filtered = true; } if (queryObject.isSetSpatialFilters()) { final Disjunction disjunction = Restrictions.disjunction(); for (final SpatialFilter filter : queryObject.getSpatialFilters()) { disjunction.add(SpatialRestrictions.filter(FeatureOfInterest.GEOMETRY, filter.getOperator(), getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(filter.getGeometry()))); } c.add(disjunction); filtered = true; } if (filtered) { return createSosFeatures(c.list(), queryObject, session); } else { return Collections.emptyMap(); } } @Override public String getDatasourceDaoIdentifier() { return HibernateDatasourceConstants.ORM_DATASOURCE_DAO_IDENTIFIER; } }