diff --git a/.travis.yml b/.travis.yml index 8e362a3aff..33f9491aa1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,10 @@ language: java jdk: - - oraclejdk8 -before_install: - - sudo hostname "$(hostname | cut -c1-63)" - - sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts + - oraclejdk8 +addons: + hosts: + - myshorthost + hostname: myshorthost install: true script: mvn -U -B clean install cache: diff --git a/NOTICE b/NOTICE index 436e3818ea..34dac28d18 100644 --- a/NOTICE +++ b/NOTICE @@ -288,6 +288,7 @@ This project includes: OGC WaterML schema (spec. v2.0) under The Apache Software License, Version 2.0 ojdbc6 under Oracle Technology Network Development and Distribution License, http://www.oracle.com/technetwork/licenses/distribution-license-152002.html Open GIS Interfaces under GNU Lesser General Public License (LGPL) version 2.1 + org.locationtech.jts:jts-core under Eclipse Publish License, Version 1.0 or Eclipse Distribution License - v 1.0 Portele Schape Change schema (spec. v3.0) under The Apache Software License, Version 2.0 Postgis JDBC Driver under GNU Lesser General Public License PostgreSQL JDBC Driver - JDBC 4.1 under The PostgreSQL License diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 71483af4a9..8dd4d3ff35 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -6,25 +6,36 @@ RELEASE NOTES SensorML instance document), and information about the sensor mounting platform (SensorML as well). - Release 52n-sensorweb-sos-4.4.x + Release 52n-sensorweb-sos-4.4.2 ==================================== --- New features --- * Result filtering for GetObservation and GetDataAvailability * Spatial filtering for GetDataAvailability + * Insertion of static reference values (stored as own procedure and series) --- Changes --- - * + * Move REST-API and Helgoland Client to webapp module (included by default) --- Fixed issues --- * Issue #212: Allow sort by status in 52n-sos-webapp/admin/operations + * Issue #555:Wrong error code when sending plain SensorML and not a request * Issue #572: Fix NPE in InsertSensor when procedure description has invalid namespace declaration * Issue #574: Capabilities shows metadata and test client provides examples for not supported operations * Issue #575: HibernateMetadataCache not updated after resetting the SOS * Issue #581: Cache: loosing spatial information after manually triggered update + * Issue #584: responseFormat-Parameter "uvf" results in Java Exception + * Issue #590: Creating a permlink is not working for +2000 chars + * Issue #592: SQL Server datasource does not add null constraint to series.identifier + * Issue #596: InsertSensor does not check if offering is already related to another procedure + * Set vertical datum name from datasource entity (#585) + * Encode description element (#585) + * Fix issue when the cache thread cound is equal or greater than the max connection count + * Fix CRS and EPSG code settings (#579) + * Creation of LineString WKT in GmlDecoderv321 Release 52n-sensorweb-sos-4.4.1 ==================================== diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/OfferingDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/OfferingDAO.java index 31fede28a7..b843109cb0 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/OfferingDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/OfferingDAO.java @@ -473,6 +473,34 @@ public Map getTemporalBoundingBoxesForOfferings(final Sessio return new HashMap<>(0); } + /** + * Insert or update and get offering + * + * @param offeringIdentifier + * Offering identifier + * @param offeringName + * Offering name + * @param relatedFeatures + * Related feature objects + * @param observationTypes + * Allowed observation type objects + * @param featureOfInterestTypes + * Allowed featureOfInterest type objects + * @param session + * Hibernate session + * @return Offering object + * + * @deprecated + * use {@link #getAndUpdateOrInsertNewOffering(SosOffering, List, List, List, Session)} + */ + @Deprecated + public Offering getAndUpdateOrInsertNewOffering(final String offeringIdentifier, final String offeringName, + final List relatedFeatures, final List observationTypes, + final List featureOfInterestTypes, final Session session) { + return getAndUpdateOrInsertNewOffering(new SosOffering(offeringIdentifier, offeringName), relatedFeatures, + observationTypes, featureOfInterestTypes, session); + } + /** * Insert or update and get offering * diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/ProcedureDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/ProcedureDAO.java index 5559fd2c19..ca8e206e45 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/ProcedureDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/ProcedureDAO.java @@ -353,7 +353,7 @@ public List getProceduresForAbstractFeatureEntity(final Session session, getDetachedCriteriaProceduresForAbstractFeatureEntityFromSeries(feature, session))); c.setProjection(Projections.distinct(Projections.property(ProcedureEntity.IDENTIFIER))); LOGGER.debug("QUERY getProceduresForAbstractFeatureEntity(feature): {}", HibernateHelper.getSqlString(c)); - return (List) c.list(); + return c.list(); } } @@ -745,6 +745,31 @@ public DateTime getMaxDate4Procedure(final String procedure, final Session sessi * ProcedureEntity identifier * @param procedureDescriptionFormat * ProcedureEntity description format object + * @param parentProcedures + * Parent procedure identifiers + * @param session + * Hibernate session + * @return Procedure object + * + * @deprecated use + * {@link #getOrInsertProcedure(String, ProcedureDescriptionFormat, SosProcedureDescription, boolean, Session)} + */ + @Deprecated + public Procedure getOrInsertProcedure(final String identifier, + final ProcedureDescriptionFormat procedureDescriptionFormat, final Collection parentProcedures, + final Session session) { + SosProcedureDescription procedure = new SosProcedureDescriptionUnknowType(identifier, + procedureDescriptionFormat.getProcedureDescriptionFormat(), "").setParentProcedures(parentProcedures); + return getOrInsertProcedure(identifier, procedureDescriptionFormat, procedure, false, session); + } + + /** + * Insert and get procedure object + * + * @param identifier + * Procedure identifier + * @param procedureDescriptionFormat + * Procedure description format object * @param procedureDescription * {@link SosProcedureDescription} to insert * @param isType @@ -791,6 +816,11 @@ public ProcedureEntity getOrInsertProcedure(String identifier, FormatEntity proc procedure.setInsitu(sml.getInsitu()); } } + if (procedureDescription.isSetInsitu()) { + tProcedure.setInsitu(procedureDescription.getInsitu()); + } + tProcedure.setReference(procedureDescription.isReference()); + procedure = tProcedure; } procedure.setDeleted(false); session.saveOrUpdate(procedure); diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractObservationDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractObservationDAO.java index bb0265e1fc..3597162656 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractObservationDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractObservationDAO.java @@ -30,7 +30,6 @@ import java.math.BigDecimal; import java.sql.Timestamp; -import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; @@ -38,7 +37,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.TreeSet; import org.hibernate.Criteria; import org.hibernate.HibernateException; @@ -141,6 +139,7 @@ import org.n52.sos.ds.hibernate.util.ParameterFactory; import org.n52.sos.ds.hibernate.util.ResultFilterClasses; import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions.SubQueryIdentifier; import org.n52.sos.ds.hibernate.util.ScrollableIterable; import org.n52.sos.ds.hibernate.util.SosTemporalRestrictions; import org.n52.sos.ds.hibernate.util.SpatialRestrictions; @@ -1313,7 +1312,8 @@ protected void checkAndAddSpatialFilteringProfileCriterion(Criteria c, GetObserv } protected void checkAndAddResultFilterCriterion(Criteria c, GetObservationRequest request, - Session session) throws OwsExceptionReport { + SubQueryIdentifier identifier, Session session) + throws OwsExceptionReport { if (request.hasResultFilter() && request.getResultFilter() instanceof ComparisonFilter) { ComparisonFilter resultFilter = (ComparisonFilter) request.getResultFilter(); Criterion resultFilterExpression = ResultFilterRestrictions.getResultFilterExpression(resultFilter, getResultFilterClasses(), DataEntity.PROPERTY_ID); @@ -1506,665 +1506,6 @@ public ParameterFactory getParameterFactory() { return ParameterFactory.getInstance(); } - /** - * Check if the observation table contains samplingGeometries with values - * - * @param session - * Hibernate session - * @return true, if the observation table contains - * samplingGeometries with values - */ - public boolean containsSamplingGeometries(Session session) { - Criteria criteria = getDefaultObservationInfoCriteria(session); - criteria.setProjection(Projections.rowCount()); - if (HibernateHelper.isNamedQuerySupported(SQL_QUERY_CHECK_SAMPLING_GEOMETRIES, session)) { - Query namedQuery = session.getNamedQuery(SQL_QUERY_CHECK_SAMPLING_GEOMETRIES); - LOGGER.debug("QUERY containsSamplingGeometries() with NamedQuery: {}", - SQL_QUERY_CHECK_SAMPLING_GEOMETRIES); - return (boolean) namedQuery.uniqueResult(); - } else if (HibernateHelper.isColumnSupported(getObservationFactory().contextualReferencedClass(), - GeometryEntity.PROPERTY_GEOMETRY)) { - criteria.add(Restrictions.isNotNull(GeometryEntity.PROPERTY_GEOMETRY)); - LOGGER.debug("QUERY containsSamplingGeometries(): {}", HibernateHelper.getSqlString(criteria)); - return (Long) criteria.uniqueResult() > 0; - } else if (HibernateHelper.isColumnSupported(getObservationFactory().contextualReferencedClass(), - GeometryEntity.PROPERTY_LON) - && HibernateHelper.isColumnSupported(getObservationFactory().contextualReferencedClass(), - GeometryEntity.PROPERTY_LAT)) { - criteria.add(Restrictions.and(Restrictions.isNotNull(GeometryEntity.PROPERTY_LON), - Restrictions.isNotNull(GeometryEntity.PROPERTY_LAT))); - LOGGER.debug("QUERY containsSamplingGeometries(): {}", HibernateHelper.getSqlString(criteria)); - return (Long) criteria.uniqueResult() > 0; - } - return false; - } - - public TimeExtrema getObservationTimeExtrema(Session session) throws OwsExceptionReport { - if (HibernateHelper.isNamedQuerySupported(SQL_QUERY_OBSERVATION_TIME_EXTREMA, session)) { - Query namedQuery = session.getNamedQuery(SQL_QUERY_OBSERVATION_TIME_EXTREMA); - LOGGER.debug("QUERY getObservationTimeExtrema() with NamedQuery: {}", SQL_QUERY_OBSERVATION_TIME_EXTREMA); - namedQuery.setResultTransformer(new ObservationTimeTransformer()); - return (TimeExtrema) namedQuery.uniqueResult(); - } else { - Criteria c = getDefaultObservationTimeCriteria(session).setProjection( - Projections.projectionList().add(Projections.min(DataEntity.PROPERTY_SAMPLING_TIME_START)) - .add(Projections.max(DataEntity.PROPERTY_SAMPLING_TIME_END)) - .add(Projections.min(DataEntity.PROPERTY_RESULT_TIME)) - .add(Projections.max(DataEntity.PROPERTY_RESULT_TIME))); - c.setResultTransformer(new ObservationTimeTransformer()); - return (TimeExtrema) c.uniqueResult(); - } - } - - protected boolean isIncludeChildObservableProperties() { - return ObservationSettingProvider.getInstance().isIncludeChildObservableProperties(); - } - - private GeometryHandler getGeometryHandler() { - return GeometryHandler.getInstance(); - } - - private static class ObservationPersister - implements ValueVisitor, OwsExceptionReport>, ProfileLevelVisitor> { -// private static final ObservationVisitor SERIES_TYPE_VISITOR = new SeriesTypeVisitor(); - - private final Set datasets; - - private final AbstractFeatureEntity featureOfInterest; - - private final Caches caches; - - private final Session session; - - private final Geometry samplingGeometry; - - private final DAOs daos; - - private final ObservationFactory observationFactory; - - private final OmObservation omObservation; - - private final boolean childObservation; - - private final Set offerings; - - private GeometryHandler geometryHandler; - - ObservationPersister( - GeometryHandler geometryHandler, AbstractObservationDAO observationDao, DaoFactory daoFactory, - OmObservation sosObservation, Set hDatasets, - AbstractFeatureEntity hFeature, Map codespaceCache, Map unitCache, - Set hOfferings, Session session) throws OwsExceptionReport { - this(geometryHandler, new DAOs(observationDao, daoFactory), new Caches(codespaceCache, unitCache), - sosObservation, hDatasets, hFeature, null, hOfferings, session, false); - } - - private ObservationPersister( - GeometryHandler geometryHandler, DAOs daos, Caches caches, OmObservation observation, - Set hDatasets, AbstractFeatureEntity hFeature, - Geometry samplingGeometry, Set hOfferings, Session session, boolean childObservation) - throws OwsExceptionReport { - this.datasets = hDatasets; - this.featureOfInterest = hFeature; - this.caches = caches; - this.omObservation = observation; - this.samplingGeometry = samplingGeometry != null ? samplingGeometry : getSamplingGeometry(omObservation); - this.session = session; - this.daos = daos; - this.observationFactory = daos.observation().getObservationFactory(); - this.childObservation = childObservation; - this.offerings = hOfferings; - this.geometryHandler = geometryHandler; - checkForDuplicity(); - } - - private void checkForDuplicity() throws OwsExceptionReport { - /* - * TODO check if observation exists in database for - series, - * phenTimeStart, phenTimeEnd, resultTime - series, phenTimeStart, - * phenTimeEnd, resultTime, depth/height parameter (same observation - * different depth/height) - */ - daos.observation.checkForDuplicatedObservations(omObservation, datasets.iterator().next(), session); - - } - - @Override - public Data visit(BooleanValue value) throws OwsExceptionReport { - return setUnitAndPersist(observationFactory.truth(), value); - } - - @Override - public Data visit(CategoryValue value) throws OwsExceptionReport { - return setUnitAndPersist(observationFactory.category(), value); - } - - @Override - public Data visit(CountValue value) throws OwsExceptionReport { - return setUnitAndPersist(observationFactory.count(), value); - } - - @Override - public Data visit(GeometryValue value) throws OwsExceptionReport { -// return setUnitAndPersist(observationFactory.geometry(), new OldGeometryValue(value)); - // TODO - return null; - } - - @Override - public Data visit(QuantityValue value) throws OwsExceptionReport { - return setUnitAndPersist(observationFactory.numeric(), value); - } - - @Override - public Data visit(QuantityRangeValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(TextValue value) - throws OwsExceptionReport { - return setUnitAndPersist(observationFactory.text(), value); - } - - @Override - public Data visit(UnknownValue value) throws OwsExceptionReport { - return setUnitAndPersist(observationFactory.blob(), value); - } - - @Override - public Data visit(SweDataArrayValue value) throws OwsExceptionReport { -// return persist(observationFactory.sweDataArray(), value.getValue()); - // TODO - return null; - } - - @Override - public Data visit(ComplexValue value) throws OwsExceptionReport { - ComplexData complex = observationFactory.complex(); - complex.setParent(true); - return persist((Data)complex, persistChildren(value.getValue())); - } - - @Override - public Data visit(HrefAttributeValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(NilTemplateValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(ReferenceValue value) throws OwsExceptionReport { - ReferencedData reference = observationFactory.reference(); - reference.setName(value.getValue().getTitle()); - return persist(reference, value.getValue().getHref()); - } - - @Override - public Data visit(TVPValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(TLVTValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(CvDiscretePointCoverage value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(MultiPointCoverage value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(RectifiedGridCoverage value) throws OwsExceptionReport { - throw notSupported(value); - } - - @Override - public Data visit(ProfileValue value) throws OwsExceptionReport { - ProfileData profile = observationFactory.profile(); - profile.setParent(true); - omObservation.getValue().setPhenomenonTime(value.getPhenomenonTime()); - return persist((Data)profile, persistChildren(value.getValue())); - } - - @Override - public Collection> visit(ProfileLevel value) throws OwsExceptionReport { - List> childObservations = new ArrayList<>(); - if (value.isSetValue()) { - for (Value v : value.getValue()) { - childObservations.add(v.accept(this)); - } - } - return childObservations; - } - - @Override - public Data visit(XmlValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - - - @Override - public Data visit(TimeRangeValue value) throws OwsExceptionReport { - throw notSupported(value); - } - - private Set> persistChildren(SweAbstractDataRecord dataRecord) - throws HibernateException, OwsExceptionReport { - Set> children = new TreeSet<>(); - for (SweField field : dataRecord.getFields()) { - PhenomenonEntity observableProperty = getObservablePropertyForField(field); - ObservationPersister childPersister = createChildPersister(observableProperty); - children.add(field.accept(ValueCreatingSweDataComponentVisitor.getInstance()).accept(childPersister)); - } - session.flush(); - return children; - } - - private Set> persistChildren(List values) throws OwsExceptionReport { - Set> children = new TreeSet<>(); - for (ProfileLevel level : values) { - if (level.isSetValue()) { - for (Value v : level.getValue()) { - if (v instanceof SweAbstractDataComponent - && ((SweAbstractDataComponent) v).isSetDefinition()) { - children.add(v.accept( - createChildPersister(level, ((SweAbstractDataComponent) v).getDefinition()))); - } else { - children.add(v.accept(createChildPersister(level))); - } - } - } - } - session.flush(); - return children; - } - - private OmObservation getObservationWithLevelParameter(ProfileLevel level) { - OmObservation o = new OmObservation(); - omObservation.copyTo(o); - o.setParameter(level.getLevelStartEndAsParameter()); - if (level.isSetPhenomenonTime()) { - o.setValue(new SingleObservationValue<>()); - o.getValue().setPhenomenonTime(level.getPhenomenonTime()); - } - return o; - } - - private ObservationPersister createChildPersister(ProfileLevel level, String observableProperty) - throws OwsExceptionReport { - return new ObservationPersister(geometryHandler, daos, caches, getObservationWithLevelParameter(level), - getObservationConstellation(getObservableProperty(observableProperty)), featureOfInterest, - getSamplingGeometryFromLevel(level), offerings, session, true); - } - - private ObservationPersister createChildPersister(ProfileLevel level) throws OwsExceptionReport { - return new ObservationPersister(geometryHandler, daos, caches, getObservationWithLevelParameter(level), - datasets, featureOfInterest, getSamplingGeometryFromLevel(level), offerings, - session, true); - - } - - private ObservationPersister createChildPersister(PhenomenonEntity observableProperty) - throws OwsExceptionReport { - return new ObservationPersister(geometryHandler, daos, caches, omObservation, - getObservationConstellation(observableProperty), featureOfInterest, samplingGeometry, offerings, - session, true); - } - - private Set getObservationConstellation(PhenomenonEntity observableProperty) { - Set newObservationConstellations = new HashSet<>(datasets.size()); - for (DatasetEntity constellation : datasets) { - newObservationConstellations.add(daos.dataset().checkOrInsertSeries( - constellation.getProcedure(), observableProperty, constellation.getOffering(), true, session)); - } - return newObservationConstellations; - - } - - private OwsExceptionReport notSupported(Value value) throws OwsExceptionReport { - throw new NoApplicableCodeException().withMessage("Unsupported observation value %s", - value.getClass().getCanonicalName()); - } - - private PhenomenonEntity getObservablePropertyForField(SweField field) { - String definition = field.getElement().getDefinition(); - return getObservableProperty(definition); - } - - private PhenomenonEntity getObservableProperty(String observableProperty) { - return daos.observableProperty().getObservablePropertyForIdentifier(observableProperty, session); - } - - private > T setUnitAndPersist(T observation, Value value) - throws OwsExceptionReport { - return persist(observation, value.getValue()); - } - - private > T persist(T observation, V value) throws OwsExceptionReport { - - observation.setDeleted(false); - - if (!childObservation) { - daos.observation().addIdentifier(omObservation, observation, session); - } else { - observation.setChild(true); - } - - daos.observation().addName(omObservation, observation, session); - daos.observation().addDescription(omObservation, observation); - daos.observation().addTime(omObservation, observation); - observation.setValue(value); - GeometryEntity geometryEntity = new GeometryEntity(); - geometryEntity.setGeometry(JTSConverter.convert(samplingGeometry)); - observation.setGeometryEntity(geometryEntity); - checkUpdateFeatureOfInterestGeometry(); - - ObservationContext observationContext = daos.observation().createObservationContext(); - - String observationType = ObservationTypeObservationVisitor.getInstance().visit((DataEntity)observation); - - for (DatasetEntity oc : datasets) { - if (!isProfileObservation(oc) || (isProfileObservation(oc) && !childObservation)) { - offerings.add(oc.getOffering()); - if (!daos.dataset().checkObservationType(oc, observationType, session)) { - throw new InvalidParameterValueException().withMessage( - "The requested observationType (%s) is invalid for procedure = %s, observedProperty = %s and offering = %s! The valid observationType is '%s'!", - observationType, observation.getDataset().getProcedure().getIdentifier(), - oc.getObservableProperty().getIdentifier(), oc.getOffering().getIdentifier(), - oc.getObservationType().getFormat()); - } - } - } - -// if (omObservation.isSetSeriesType()) { -// observationContext.setSeriesType(omObservation.getSeriesType()); -// } else { -// observationContext.setSeriesType(SERIES_TYPE_VISITOR.visit(observation)); -// } - - DatasetEntity first = Iterables.getFirst(datasets, null); - if (first != null) { - observationContext.setPhenomenon(first.getObservableProperty()); - observationContext.setProcedure(first.getProcedure()); - observationContext.setOffering(first.getOffering()); - } - - if (childObservation) { - observationContext.setHiddenChild(true); - } - observationContext.setFeatureOfInterest(featureOfInterest); - daos.observation().fillObservationContext(observationContext, omObservation, session); - daos.observation().addObservationContextToObservation(observationContext, observation, session); - if (omObservation.isSetParameter()) { - Set> insertParameter = daos.parameter().insertParameter(omObservation.getParameter(), - caches.units, session); - observation.setParameters(insertParameter); - } - session.saveOrUpdate(observation); - - return observation; - } - - private boolean isProfileObservation(DatasetEntity observationConstellation) { - return observationConstellation.isSetObservationType() && (OmConstants.OBS_TYPE_PROFILE_OBSERVATION - .equals(observationConstellation.getObservationType().getFormat()) - || GWMLConstants.OBS_TYPE_GEOLOGY_LOG - .equals(observationConstellation.getObservationType().getFormat()) - || GWMLConstants.OBS_TYPE_GEOLOGY_LOG_COVERAGE - .equals(observationConstellation.getObservationType().getFormat())); - } - - private Geometry getSamplingGeometryFromLevel(ProfileLevel level) throws OwsExceptionReport { - if (level.isSetLocation()) { - return geometryHandler.switchCoordinateAxisFromToDatasourceIfNeeded(level.getLocation()); - } - return null; - } - - private Geometry getSamplingGeometry(OmObservation sosObservation) throws OwsExceptionReport { - if (!sosObservation.isSetSpatialFilteringProfileParameter()) { - return null; - } - if (sosObservation.isSetValue() && sosObservation.getValue().isSetValue() - && sosObservation.getValue().getValue() instanceof ProfileValue - && ((ProfileValue) sosObservation.getValue().getValue()).isSetGeometry()) { - return geometryHandler.switchCoordinateAxisFromToDatasourceIfNeeded( - ((ProfileValue) sosObservation.getValue().getValue()).getGeometry()); - } - NamedValue spatialFilteringProfileParameter = - sosObservation.getSpatialFilteringProfileParameter(); - return geometryHandler.switchCoordinateAxisFromToDatasourceIfNeeded( - spatialFilteringProfileParameter.getValue().getValue()); - } - - private void checkUpdateFeatureOfInterestGeometry() throws CodedException { - // check if flag is set and if this observation is not a child - // observation - if (samplingGeometry != null && isUpdateFeatureGeometry() && !childObservation) { - daos.feature.updateFeatureOfInterestGeometry(featureOfInterest, samplingGeometry, session); - } - } - - private boolean isUpdateFeatureGeometry() { - // TODO - return true; - } - - private static class Caches { - private final Map codespaces; - - private final Map units; - - Caches(Map codespaces, Map units) { - this.codespaces = codespaces; - this.units = units; - } - - public Map codespaces() { - return codespaces; - } - - public Map units() { - return units; - } - } - - private static class DAOs { - private final ObservablePropertyDAO observableProperty; - - - private final AbstractObservationDAO observation; - - private final FormatDAO observationType; - - private final ParameterDAO parameter; - - private final FeatureOfInterestDAO feature; - - private final AbstractSeriesDAO dataset; - - DAOs(AbstractObservationDAO observationDao, DaoFactory daoFactory) { - this.observation = observationDao; - this.observableProperty = daoFactory.getObservablePropertyDAO(); - this.observationType = daoFactory.getObservationTypeDAO(); - this.parameter = daoFactory.getParameterDAO(); - this.feature = daoFactory.getFeatureOfInterestDAO(); - this.dataset = daoFactory.getSeriesDAO(); - } - - public ObservablePropertyDAO observableProperty() { - return this.observableProperty; - } - - public AbstractObservationDAO observation() { - return this.observation; - } - - public FormatDAO observationType() { - return this.observationType; - } - - public ParameterDAO parameter() { - return this.parameter; - } - - public FeatureOfInterestDAO feature() { - return this.feature; - } - - public AbstractSeriesDAO dataset() { - return this.dataset; - } - } - -// private static class SeriesTypeVisitor -// implements ObservationVisitor { -// -// @SuppressWarnings("unused") -// public String visit(Data o) { -// if (o instanceof QuantityData) { -// return visit((QuantityData)o); -// } else if (o instanceof BlobData) { -// return visit((BlobData)o); -// } else if (o instanceof BooleanData) { -// return visit((BooleanData)o); -// } else if (o instanceof CategoryData) { -// return visit((CategoryData)o); -// } else if (o instanceof ComplexData) { -// return visit((ComplexData)o); -// } else if (o instanceof CountData) { -// return visit((CountData)o); -// } else if (o instanceof GeometryData) { -// return visit((GeometryData)o); -// } else if (o instanceof TextData) { -// return visit((TextData)o); -// } else if (o instanceof ProfileData) { -// return visit((ProfileData)o); -// } else if (o instanceof ReferencedData) { -// return visit((ReferencedData)o); -// } -// return null; -// } -// -// @Override -// public String visit(QuantityData o) { -// return "quantity"; -// } -// -// @Override -// public String visit(BlobData o) { -// return "blob"; -// } -// -// @Override -// public String visit(BooleanData o) { -// return "boolean"; -// } -// -// @Override -// public String visit(CategoryData o) { -// return "category"; -// } -// -// @Override -// public String visit(ComplexData o) { -// return "complex"; -// } -// -// @Override -// public String visit(CountData o) { -// return "count"; -// } -// -// @Override -// public String visit(GeometryData o) { -// return "geometry"; -// } -// -// @Override -// public String visit(TextData o) { -// return "text"; -// } -// -// @Override -// public String visit(DataArrayData o) { -// return "swedataarray"; -// } -// -// @Override -// public String visit(ProfileData o) { -// return "profile"; -// } -// -// @Override -// public String visit(ReferencedData o) { -// return "reference"; -// } -// } - - - public class OldGeometryValue - extends GeometryEntity - implements - Value { - - private static final long serialVersionUID = 3172441992424788208L; - private com.vividsolutions.jts.geom.Geometry value; - private UoM unit; - - public OldGeometryValue(GeometryValue value) throws CodedException { - setValue(JTSConverter.convert(value.getGeometry())); - setUnit(value.getUnit()); - } - - @Override - public OldGeometryValue setValue(com.vividsolutions.jts.geom.Geometry value) { - this.value = value; - return this; - } - - @Override - public com.vividsolutions.jts.geom.Geometry getValue() { - return value; - } - - @Override - public void setUnit(String unit) { - setUnit(new UoM(unit)); - } - - @Override - public OldGeometryValue setUnit(UoM unit) { - this.unit = unit; - return this; - } - - @Override - public UoM getUnitObject() { - return unit; - } - - @Override - public String getUnit() { - return unit.getUom(); - } - - @Override - public X accept(ValueVisitor visitor) throws E { - return null; - } - } } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractValueDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractValueDAO.java index d271bd750f..d868acbd42 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractValueDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/AbstractValueDAO.java @@ -48,6 +48,7 @@ import org.n52.sos.ds.hibernate.util.ObservationSettingProvider; import org.n52.sos.ds.hibernate.util.ResultFilterClasses; import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions.SubQueryIdentifier; import org.n52.sos.ds.hibernate.util.SpatialRestrictions; import org.n52.sos.util.GeometryHandler; import org.slf4j.Logger; @@ -96,11 +97,11 @@ protected void checkAndAddSpatialFilteringProfileCriterion(Criteria c, GetObserv } } - protected void checkAndAddResultFilterCriterion(Criteria c, GetObservationRequest request, - Session session) throws OwsExceptionReport { + protected void checkAndAddResultFilterCriterion(Criteria c, GetObservationRequest request, SubQueryIdentifier identifier, Session session) + throws OwsExceptionReport { if (request.hasResultFilter() && request.getResultFilter() instanceof ComparisonFilter) { ComparisonFilter resultFilter = (ComparisonFilter) request.getResultFilter(); - Criterion resultFilterExpression = ResultFilterRestrictions.getResultFilterExpression(resultFilter, getResultFilterClasses(), DataEntity.PROPERTY_ID); + Criterion resultFilterExpression = ResultFilterRestrictions.getResultFilterExpression(resultFilter, getResultFilterClasses(), DataEntity.PROPERTY_ID, identifier); if (resultFilterExpression != null) { c.add(resultFilterExpression); } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationContext.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationContext.java index f75f7a2319..909d539dfc 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationContext.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationContext.java @@ -49,6 +49,7 @@ * observableProperty, procedure). * * @author Carsten Hollmann + * @author Jürrens, Eike Hinderk * @since 4.0.0 * */ @@ -58,45 +59,39 @@ public class ObservationContext { private ProcedureEntity procedure; private OfferingEntity offering; private boolean hiddenChild = false; + private boolean publish = true; /** - * @return the featureOfInterest + * Indicates that the series of the observation should be published */ + public boolean isPublish() { + return publish; + } + + public void setPublish(boolean publish) { + this.publish = publish; + } + public AbstractFeatureEntity getFeatureOfInterest() { return featureOfInterest; } - /** - * @param featureOfInterest - * the featureOfInterest to set - */ public void setFeatureOfInterest(AbstractFeatureEntity featureOfInterest) { this.featureOfInterest = featureOfInterest; } - /** - * @return the observableProperty - */ public PhenomenonEntity getPhenomenon() { return observableProperty; } - /** - * @param observableProperty - * the observableProperty to set - */ public void setPhenomenon(PhenomenonEntity observableProperty) { this.observableProperty = observableProperty; } - /** - * @return the procedure - */ public ProcedureEntity getProcedure() { return procedure; } - private String seriesType; /** * @param procedure @@ -125,9 +120,6 @@ public OfferingEntity getOffering() { return offering; } - /** - * @param offering the offering to set - */ public void setOffering(OfferingEntity offering) { this.offering = offering; } @@ -180,7 +172,7 @@ public void setSeriesType(String seriesType) { } public String getSeriesType() { - return this.seriesType; + return seriesType; } public boolean isSetSeriesType() { @@ -192,7 +184,7 @@ public void setHiddenChild(boolean hiddenChild) { } public boolean isHiddenChild() { - return this.hiddenChild; + return hiddenChild; } } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationPersister.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationPersister.java new file mode 100644 index 0000000000..42ae81edfa --- /dev/null +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ObservationPersister.java @@ -0,0 +1,614 @@ +/** + * Copyright (C) 2012-2018 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.observation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.n52.sos.ds.hibernate.dao.FeatureOfInterestDAO; +import org.n52.sos.ds.hibernate.dao.ObservablePropertyDAO; +import org.n52.sos.ds.hibernate.dao.ObservationConstellationDAO; +import org.n52.sos.ds.hibernate.dao.ObservationTypeDAO; +import org.n52.sos.ds.hibernate.dao.ParameterDAO; +import org.n52.sos.ds.hibernate.entities.Codespace; +import org.n52.sos.ds.hibernate.entities.ObservableProperty; +import org.n52.sos.ds.hibernate.entities.ObservationConstellation; +import org.n52.sos.ds.hibernate.entities.Offering; +import org.n52.sos.ds.hibernate.entities.Unit; +import org.n52.sos.ds.hibernate.entities.feature.AbstractFeatureOfInterest; +import org.n52.sos.ds.hibernate.entities.observation.Observation; +import org.n52.sos.ds.hibernate.entities.observation.ObservationVisitor; +import org.n52.sos.ds.hibernate.entities.observation.full.BlobObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.BooleanObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.CategoryObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.ComplexObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.CountObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.GeometryObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.NumericObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.ProfileObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.ReferenceObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.SweDataArrayObservation; +import org.n52.sos.ds.hibernate.entities.observation.full.TextObservation; +import org.n52.sos.exception.ows.InvalidParameterValueException; +import org.n52.sos.exception.ows.NoApplicableCodeException; +import org.n52.sos.ogc.UoM; +import org.n52.sos.ogc.gwml.GWMLConstants; +import org.n52.sos.ogc.om.NamedValue; +import org.n52.sos.ogc.om.OmConstants; +import org.n52.sos.ogc.om.OmObservation; +import org.n52.sos.ogc.om.SingleObservationValue; +import org.n52.sos.ogc.om.values.BooleanValue; +import org.n52.sos.ogc.om.values.CategoryValue; +import org.n52.sos.ogc.om.values.ComplexValue; +import org.n52.sos.ogc.om.values.CountValue; +import org.n52.sos.ogc.om.values.CvDiscretePointCoverage; +import org.n52.sos.ogc.om.values.GeometryValue; +import org.n52.sos.ogc.om.values.HrefAttributeValue; +import org.n52.sos.ogc.om.values.MultiPointCoverage; +import org.n52.sos.ogc.om.values.NilTemplateValue; +import org.n52.sos.ogc.om.values.ProfileLevel; +import org.n52.sos.ogc.om.values.ProfileLevelVisitor; +import org.n52.sos.ogc.om.values.ProfileValue; +import org.n52.sos.ogc.om.values.QuantityRangeValue; +import org.n52.sos.ogc.om.values.QuantityValue; +import org.n52.sos.ogc.om.values.RectifiedGridCoverage; +import org.n52.sos.ogc.om.values.ReferenceValue; +import org.n52.sos.ogc.om.values.SweDataArrayValue; +import org.n52.sos.ogc.om.values.TLVTValue; +import org.n52.sos.ogc.om.values.TVPValue; +import org.n52.sos.ogc.om.values.TextValue; +import org.n52.sos.ogc.om.values.UnknownValue; +import org.n52.sos.ogc.om.values.Value; +import org.n52.sos.ogc.om.values.XmlValue; +import org.n52.sos.ogc.om.values.visitor.ValueVisitor; +import org.n52.sos.ogc.ows.OwsExceptionReport; +import org.n52.sos.ogc.swe.SweAbstractDataComponent; +import org.n52.sos.ogc.swe.SweAbstractDataRecord; +import org.n52.sos.ogc.swe.SweField; +import org.n52.sos.service.ServiceConfiguration; +import org.n52.sos.util.GeometryHandler; + +import com.vividsolutions.jts.geom.Geometry; + +public class ObservationPersister implements ValueVisitor>, ProfileLevelVisitor> { + + private static final ObservationVisitor SERIES_TYPE_VISITOR = new SeriesTypeVisitor(); + private final ObservationConstellation observationConstellation; + private final AbstractFeatureOfInterest featureOfInterest; + private final ObservationPersister.Caches caches; + private final Session session; + private final Geometry samplingGeometry; + private final ObservationPersister.DAOs daos; + private final ObservationFactory observationFactory; + private final OmObservation sosObservation; + private final boolean childObservation; + private final Set offerings; + + public ObservationPersister( + AbstractObservationDAO observationDao, + OmObservation sosObservation, + ObservationConstellation hObservationConstellation, + AbstractFeatureOfInterest hFeature, + Map codespaceCache, + Map unitCache, + Set hOfferings, + Session session) + throws OwsExceptionReport { + this(new DAOs(observationDao), + new Caches(codespaceCache, unitCache), + sosObservation, + hObservationConstellation, + hFeature, + getSamplingGeometry(sosObservation), + hOfferings, + session, + false); + } + + private ObservationPersister( + ObservationPersister.DAOs daos, + ObservationPersister.Caches caches, + OmObservation observation, + ObservationConstellation hObservationConstellation, + AbstractFeatureOfInterest hFeature, + Geometry samplingGeometry, + Set hOfferings, + Session session, + boolean childObservation) + throws OwsExceptionReport { + observationConstellation = hObservationConstellation; + featureOfInterest = hFeature; + this.caches = caches; + sosObservation = observation; + this.samplingGeometry = samplingGeometry; + this.session = session; + this.daos = daos; + observationFactory = daos.observation().getObservationFactory(); + this.childObservation = childObservation; + offerings = hOfferings; + checkForDuplicity(); + } + + private void checkForDuplicity() throws OwsExceptionReport { + /* + * TODO check if observation exists in database for + * - series, phenTimeStart, phenTimeEnd, resultTime + * - series, phenTimeStart, phenTimeEnd, resultTime, depth/height parameter (same observation different depth/height) + */ + daos.observation.checkForDuplicatedObservations(sosObservation, observationConstellation, session); + + } + + @Override + public Observation visit(BooleanValue value) throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.truth(), value); + } + + @Override + public Observation visit(CategoryValue value) + throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.category(), value); + } + + @Override + public Observation visit(CountValue value) + throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.count(), value); + } + + @Override + public Observation visit(GeometryValue value) + throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.geometry(), value); + } + + @Override + public Observation visit(QuantityValue value) + throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.numeric(), value); + } + + + @Override + public Observation visit(QuantityRangeValue value) throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(TextValue value) + throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.text(), value); + } + + @Override + public Observation visit(UnknownValue value) + throws OwsExceptionReport { + return setUnitAndPersist(observationFactory.blob(), value); + } + + @Override + public Observation visit(SweDataArrayValue value) + throws OwsExceptionReport { + return persist(observationFactory.sweDataArray(), value.getValue().getXml()); + } + + @Override + public Observation visit(ComplexValue value) + throws OwsExceptionReport { + ComplexObservation complex = observationFactory.complex(); + complex.setParent(true); + return persist(complex, persistChildren(value.getValue())); + } + + @Override + public Observation visit(HrefAttributeValue value) + throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(NilTemplateValue value) + throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(ReferenceValue value) + throws OwsExceptionReport { + return persist(observationFactory.reference(), value.getValue()); + } + + @Override + public Observation visit(TVPValue value) + throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(TLVTValue value) + throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(CvDiscretePointCoverage value) throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(MultiPointCoverage value) throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(RectifiedGridCoverage value) throws OwsExceptionReport { + throw notSupported(value); + } + + @Override + public Observation visit(ProfileValue value) throws OwsExceptionReport { + ProfileObservation profile = observationFactory.profile(); + profile.setParent(true); + sosObservation.getValue().setPhenomenonTime(value.getPhenomenonTime()); + return persist(profile, persistChildren(value.getValue())); + } + + @Override + public Collection> visit(ProfileLevel value) throws OwsExceptionReport { + List> childObservations = new ArrayList<>(); + if (value.isSetValue()) { + for (Value v : value.getValue()) { + childObservations.add(v.accept(this)); + } + } + return childObservations; + } + + @Override + public Observation visit(XmlValue value) + throws OwsExceptionReport { + throw notSupported(value); + } + + + + private Set> persistChildren(SweAbstractDataRecord dataRecord) + throws HibernateException, OwsExceptionReport { + Set> children = new TreeSet<>(); + for (SweField field : dataRecord.getFields()) { + ObservableProperty observableProperty = getObservablePropertyForField(field); + ObservationPersister childPersister = createChildPersister(observableProperty); + children.add(field.accept(ValueCreatingSweDataComponentVisitor.getInstance()).accept(childPersister)); + } + session.flush(); + return children; + } + + private Set> persistChildren(List values) throws OwsExceptionReport { + Set> children = new TreeSet<>(); + for (ProfileLevel level : values) { + if (level.isSetValue()) { + for (Value v : level.getValue()) { + if (v instanceof SweAbstractDataComponent && ((SweAbstractDataComponent) v).isSetDefinition()) { + children.add(v.accept(createChildPersister(level, ((SweAbstractDataComponent) v).getDefinition()))); + } else { + children.add(v.accept(createChildPersister(level))); + } + } + } + } + session.flush(); + return children; + } + + private OmObservation getObservationWithLevelParameter(ProfileLevel level) { + OmObservation o = new OmObservation(); + sosObservation.copyTo(o); + o.setParameter(level.getLevelStartEndAsParameter()); + if (level.isSetPhenomenonTime()) { + o.setValue(new SingleObservationValue<>()); + o.getValue().setPhenomenonTime(level.getPhenomenonTime()); + } + return o; + } + + private ObservationPersister createChildPersister(ProfileLevel level, String observableProperty) throws OwsExceptionReport { + return new ObservationPersister(daos, caches, getObservationWithLevelParameter(level), + getObservationConstellation(getObservableProperty(observableProperty)), featureOfInterest, + getSamplingGeometryFromLevel(level), offerings, session, true); + } + + private ObservationPersister createChildPersister(ProfileLevel level) throws OwsExceptionReport { + return new ObservationPersister(daos, caches, getObservationWithLevelParameter(level), + observationConstellation, featureOfInterest, + getSamplingGeometryFromLevel(level), offerings, session, true); + + } + + private ObservationPersister createChildPersister(ObservableProperty observableProperty) throws OwsExceptionReport { + return new ObservationPersister(daos, caches, sosObservation, + getObservationConstellation(observableProperty), featureOfInterest, + samplingGeometry, offerings, session, true); + } + + private ObservationConstellation getObservationConstellation(ObservableProperty observableProperty) { + return daos.observationConstellation() + .checkOrInsertObservationConstellation( + observationConstellation.getProcedure(), + observableProperty, + observationConstellation.getOffering(), + true, + session); + + } + + private OwsExceptionReport notSupported(Value value) + throws OwsExceptionReport { + throw new NoApplicableCodeException() + .withMessage("Unsupported observation value %s", value + .getClass().getCanonicalName()); + } + + private ObservableProperty getObservablePropertyForField(SweField field) { + String definition = field.getElement().getDefinition(); + return getObservableProperty(definition); + } + + private ObservableProperty getObservableProperty(String observableProperty) { + return daos.observableProperty().getObservablePropertyForIdentifier(observableProperty, session); + } + + private > T setUnitAndPersist(T observation, Value value) throws OwsExceptionReport { + observation.setUnit(getUnit(value)); + return persist(observation, value.getValue()); + } + + private Unit getUnit(Value value) { + return value.isSetUnit() ? daos.observation().getUnit(value.getUnitObject(), caches.units(), session) : null; + } + + private > T persist(T observation, V value) throws OwsExceptionReport { + if (!observation.isSetUnit()) { + observation.setUnit(getUnit(sosObservation.getValue().getValue())); + } + observation.setDeleted(false); + + if (!childObservation) { + daos.observation().addIdentifier(sosObservation, observation, session); + } else { + observation.setChild(true); + } + + daos.observation().addName(sosObservation, observation, session); + daos.observation().addDescription(sosObservation, observation); + daos.observation().addTime(sosObservation, observation); + observation.setValue(value); + observation.setSamplingGeometry(samplingGeometry); + checkUpdateFeatureOfInterestGeometry(); + + ObservationContext observationContext = daos.observation().createObservationContext(); + + String observationType = observation.accept(ObservationTypeObservationVisitor.getInstance()); + if (!isProfileObservation() || isProfileObservation() && !childObservation) { + if (!daos.observationConstellation().checkObservationType(observationConstellation, observationType, session)) { + throw new InvalidParameterValueException() + .withMessage("The requested observationType (%s) is invalid for procedure = %s, observedProperty = %s and offering = %s! The valid observationType is '%s'!", + observationType, + observationConstellation.getProcedure().getIdentifier(), + observationConstellation.getObservableProperty().getIdentifier(), + observationConstellation.getOffering().getIdentifier(), + observationConstellation.getObservationType().getObservationType()); + } + if (sosObservation.isSetSeriesType()) { + observationContext.setSeriesType(sosObservation.getSeriesType()); + } else { + observationContext.setSeriesType(observation.accept(SERIES_TYPE_VISITOR)); + } + } + + if (observationConstellation != null) { + observationContext.setObservableProperty(observationConstellation.getObservableProperty()); + observationContext.setProcedure(observationConstellation.getProcedure()); + observationContext.setOffering(observationConstellation.getOffering()); + } + + if (childObservation) { + observationContext.setHiddenChild(true); + } + observationContext.setFeatureOfInterest(featureOfInterest); + observation.setOfferings(offerings); + daos.observation().fillObservationContext(observationContext, sosObservation, session); + daos.observation().addObservationContextToObservation(observationContext, observation, session); + + session.saveOrUpdate(observation); + + if (sosObservation.isSetParameter()) { + daos.parameter.insertParameter(sosObservation.getParameter(), observation.getObservationId(), caches.units, session); + } + return observation; + } + + private boolean isProfileObservation() { + return observationConstellation.isSetObservationType() + && (OmConstants.OBS_TYPE_PROFILE_OBSERVATION.equals(observationConstellation.getObservationType().getObservationType()) + || GWMLConstants.OBS_TYPE_GEOLOGY_LOG.equals(observationConstellation.getObservationType().getObservationType()) + || GWMLConstants.OBS_TYPE_GEOLOGY_LOG_COVERAGE.equals(observationConstellation.getObservationType().getObservationType())); + } + + private Geometry getSamplingGeometryFromLevel(ProfileLevel level) throws OwsExceptionReport { + if (level.isSetLocation()) { + return GeometryHandler.getInstance().switchCoordinateAxisFromToDatasourceIfNeeded(level.getLocation()); + } + return null; + } + + private static Geometry getSamplingGeometry(OmObservation sosObservation) throws OwsExceptionReport { + if (!sosObservation.isSetSpatialFilteringProfileParameter()) { + return null; + } + if (sosObservation.isSetValue() && sosObservation.getValue().isSetValue() && sosObservation.getValue().getValue() instanceof ProfileValue + && ((ProfileValue)sosObservation.getValue().getValue()).isSetGeometry()) { + return GeometryHandler.getInstance().switchCoordinateAxisFromToDatasourceIfNeeded(((ProfileValue)sosObservation.getValue().getValue()).getGeometry()); + } + NamedValue spatialFilteringProfileParameter = sosObservation.getSpatialFilteringProfileParameter(); + Geometry geometry = spatialFilteringProfileParameter.getValue().getValue(); + return GeometryHandler.getInstance().switchCoordinateAxisFromToDatasourceIfNeeded(geometry); + } + + private void checkUpdateFeatureOfInterestGeometry() { + // check if flag is set and if this observation is not a child observation + if (samplingGeometry != null && ServiceConfiguration.getInstance().isUpdateFeatureGeometry() && !childObservation) { + new FeatureOfInterestDAO().updateFeatureOfInterestGeometry(featureOfInterest, samplingGeometry, session); + } + } + + private static class Caches { + private final Map codespaces; + private final Map units; + + Caches(Map codespaces, Map units) { + this.codespaces = codespaces; + this.units = units; + } + + public Map codespaces() { + return codespaces; + } + + public Map units() { + return units; + } + } + + private static class DAOs { + private final ObservablePropertyDAO observableProperty; + private final ObservationConstellationDAO observationConstellation; + private final AbstractObservationDAO observation; + private final ObservationTypeDAO observationType; + private final ParameterDAO parameter; + + DAOs(AbstractObservationDAO observationDAO) { + observation = observationDAO; + observableProperty = new ObservablePropertyDAO(); + observationConstellation = new ObservationConstellationDAO(); + observationType = new ObservationTypeDAO(); + parameter = new ParameterDAO(); + } + + public ObservablePropertyDAO observableProperty() { + return observableProperty; + } + + public ObservationConstellationDAO observationConstellation() { + return observationConstellation; + } + + public AbstractObservationDAO observation() { + return observation; + } + + public ObservationTypeDAO observationType() { + return observationType; + } + + public ParameterDAO parameter() { + return parameter; + } + } + + private static class SeriesTypeVisitor implements ObservationVisitor { + + @Override + public String visit(NumericObservation o) throws OwsExceptionReport { + return "quantity"; + } + + @Override + public String visit(BlobObservation o) throws OwsExceptionReport { + return "blob"; + } + + @Override + public String visit(BooleanObservation o) throws OwsExceptionReport { + return "boolean"; + } + + @Override + public String visit(CategoryObservation o) throws OwsExceptionReport { + return "category"; + } + + @Override + public String visit(ComplexObservation o) throws OwsExceptionReport { + return "complex"; + } + + @Override + public String visit(CountObservation o) throws OwsExceptionReport { + return "count"; + } + + @Override + public String visit(GeometryObservation o) throws OwsExceptionReport { + return "geometry"; + } + + @Override + public String visit(TextObservation o) throws OwsExceptionReport { + return "text"; + } + + @Override + public String visit(SweDataArrayObservation o) throws OwsExceptionReport { + return "swedataarray"; + } + + @Override + public String visit(ProfileObservation o) throws OwsExceptionReport { + if (o.isSetValue()) { + for (Observation value : o.getValue()) { + return value.accept(this) + "-profile"; + } + } + return "profile"; + } + + @Override + public String visit(ReferenceObservation o) + throws OwsExceptionReport { + return "reference"; + } + } +} \ No newline at end of file diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingObservationDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingObservationDAO.java index dd8ac7eb9d..29e0504bd8 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingObservationDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingObservationDAO.java @@ -142,7 +142,6 @@ public List> getSeriesObservationsFor(GetObservationRequest reques return getSeriesObservationsFor(request, features, null, sosIndeterminateTime, session); } - @SuppressWarnings("unchecked") @Override protected List> getSeriesObservationsFor(GetObservationRequest request, Collection features, Criterion filterCriterion, @@ -152,20 +151,19 @@ protected List> getSeriesObservationsFor(GetObservationRequest req if (CollectionHelper.isNotEmpty(features)) { List> observations = new ArrayList<>(); for (List ids : QueryHelper.getListsForIdentifiers(features)) { - observations.addAll(getSeriesObservationCriteriaFor(request, ids, filterCriterion, sosIndeterminateTime, session).list()); + observations.addAll(getSeriesObservationCriteriaFor(request, ids, filterCriterion, sosIndeterminateTime, session)); } return observations; } else { - return getSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session).list(); + return getSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session); } } - @SuppressWarnings("unchecked") @Override public List> getSeriesObservationsFor(DatasetEntity series, GetObservationRequest request, IndeterminateValue sosIndeterminateTime, Session session) throws OwsExceptionReport { - return getSeriesObservationCriteriaFor(series, request, sosIndeterminateTime, session).list(); + return getSeriesObservationCriteriaFor(series, request, sosIndeterminateTime, session); } @Override diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingSeriesDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingSeriesDAO.java index 3a11ff6a17..bb0cd3635e 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingSeriesDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/ereporting/EReportingSeriesDAO.java @@ -80,9 +80,16 @@ public Class getSeriesClass() { } @Override - @SuppressWarnings("unchecked") public List getSeries(GetObservationRequest request, Collection features, Session session) throws OwsExceptionReport { - return getSeriesCriteria(request, features, session).list(); + List series = new ArrayList<>(); + if (CollectionHelper.isNotEmpty(features)) { + for (List ids : QueryHelper.getListsForIdentifiers(features)) { + series.addAll(getSeriesSet(request, ids, session)); + } + } else { + series.addAll(getSeriesSet(request, features, session)); + } + return series; } @SuppressWarnings("unchecked") @@ -91,11 +98,10 @@ public List getSeries(GetObservationByIdRequest request, Session return getSeriesCriteria(request, session).list(); } - @SuppressWarnings("unchecked") @Override public List getSeries(GetDataAvailabilityRequest request, Session session) throws OwsExceptionReport { - return getSeriesCriteria(request, session).list(); + return new ArrayList<>(getSeriesCriteria(request, session)); } @SuppressWarnings("unchecked") diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesDAO.java index d887c0ac13..9aca59f711 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesDAO.java @@ -84,6 +84,7 @@ import org.n52.sos.ds.hibernate.util.HibernateHelper; import org.n52.sos.ds.hibernate.util.ResultFilterClasses; import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions.SubQueryIdentifier; import org.n52.sos.ds.hibernate.util.SpatialRestrictions; import org.n52.sos.ds.hibernate.util.TimeExtrema; import org.n52.sos.util.GeometryHandler; @@ -267,16 +268,10 @@ protected DatasetEntity getOrInsert(ObservationContext ctx, final Session sessio series = getSeriesImpl(); ctx.addValuesToSeries(series); series.setDeleted(false); - series.setPublished(true); + series.setPublished(ctx.isPublish()); series.setHiddenChild(ctx.isHiddenChild()); - session.saveOrUpdate(series); - session.flush(); - session.refresh(series); } else if (series.isDeleted()) { series.setDeleted(false); - session.saveOrUpdate(series); - session.flush(); - session.refresh(series); // } else if (ctx.isSetSeriesType() && !series.isSetSeriesType()) { // ctx.addValuesToSeries(series); // session.saveOrUpdate(series); @@ -298,9 +293,9 @@ protected DatasetEntity getOrInsert(ObservationContext ctx, Data observation, series.setDeleted(false); series.setPublished(true); series.setHiddenChild(ctx.isHiddenChild()); - session.saveOrUpdate(series); - session.flush(); - session.refresh(series); + } else if (ctx.isPublish() && !series.isPublished()) { + series.setPublished(true); + } else if (series instanceof NotDefinedDatasetEntity) { Dataset visit = getDatasetFactory().visit(observation); visit.add(series); @@ -308,15 +303,14 @@ protected DatasetEntity getOrInsert(ObservationContext ctx, Data observation, series.setDeleted(false); series.setPublished(true); series.setHiddenChild(ctx.isHiddenChild()); - session.saveOrUpdate(series); - session.flush(); - session.refresh(series); } else if (series.isDeleted()) { series.setDeleted(false); - session.saveOrUpdate(series); - session.flush(); - session.refresh(series); + } else { + return series; } + session.saveOrUpdate(series); + session.flush(); + session.refresh(series); return series; } @@ -332,42 +326,64 @@ private DatasetEntity getSeriesImpl() throws OwsExceptionReport { public List getSeries(Session session) { return getDefaultSeriesCriteria(session).list(); } + @SuppressWarnings("unchecked") + public Set getSeriesSet(GetObservationRequest request, Collection features, + Session session) + throws OwsExceptionReport { + Set set = new LinkedHashSet<>(); + if (request.hasResultFilter()) { + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + final Criteria c = createCriteriaFor(request.getProcedures(), request.getObservedProperties(), + features, request.getOfferings(), session); + addSpecificRestrictions(c, request); + checkAndAddResultFilterCriterion(c, request, identifier, session); + checkAndAddSpatialFilterCriterion(c, request, session); + LOGGER.debug("QUERY getSeries(request, features) and result filter sub query '{}': {}", + identifier.name(), HibernateHelper.getSqlString(c)); + set.addAll(c.list()); + } + } else { + final Criteria c = createCriteriaFor(request.getProcedures(), request.getObservedProperties(), features, + request.getOfferings(), session); + addSpecificRestrictions(c, request); + checkAndAddSpatialFilterCriterion(c, request, session); + LOGGER.debug("QUERY getSeries(request, features): {}", HibernateHelper.getSqlString(c)); + set.addAll(c.list()); + } + return set; + } - public Criteria getSeriesCriteria(GetObservationRequest request, Collection features, Session session) + @SuppressWarnings("unchecked") + protected Set getSeriesCriteria(GetDataAvailabilityRequest request, Session session) throws OwsExceptionReport { - final Criteria c = createCriteriaFor(request.getProcedures(), request.getObservedProperties(), features, - request.getOfferings(), session); - addSpecificRestrictions(c, request); - checkAndAddResultFilterCriterion(c, request, session); - checkAndAddSpatialFilterCriterion(c, request, session); - LOGGER.debug("QUERY getSeries(request, features): {}", HibernateHelper.getSqlString(c)); - return c; + Set set = new LinkedHashSet<>(); + if (request.hasResultFilter()) { + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getSeriesCriteria(request.getProcedures(), request.getObservedProperties(), + request.getFeaturesOfInterest(), request.getOfferings(), session); + checkAndAddResultFilterCriterion(c, request, identifier, session); + checkAndAddSpatialFilterCriterion(c, request, session); + LOGGER.debug("QUERY getSeriesCriteria(request) and result filter sub query '{}': {}", + identifier.name(), HibernateHelper.getSqlString(c)); + set.addAll(c.list()); + } + } else { + Criteria c = getSeriesCriteria(request.getProcedures(), request.getObservedProperties(), + request.getFeaturesOfInterest(), request.getOfferings(), session); + checkAndAddSpatialFilterCriterion(c, request, session); + LOGGER.debug("QUERY getSeriesCriteria(request): {}", HibernateHelper.getSqlString(c)); + set.addAll(c.list()); + } + return set; } - public Criteria getSeriesCriteria(GetObservationByIdRequest request, Session session) { + public Criteria getSeriesCriteria(GetObservationByIdRequest request, Session session) { final Criteria c = getDefaultSeriesCriteria(session); c.add(Restrictions.in(DatasetEntity.IDENTIFIER, request.getObservationIdentifier())); LOGGER.debug("QUERY getSeriesCriteria(request): {}", HibernateHelper.getSqlString(c)); return c; } - protected Criteria getSeriesCriteria(GetDataAvailabilityRequest request, Session session) throws OwsExceptionReport { - Criteria c = getSeriesCriteria(request.getProcedures(), request.getObservedProperties(), request.getFeaturesOfInterest(), request.getOfferings(), session); - checkAndAddResultFilterCriterion(c, request, session); - checkAndAddSpatialFilterCriterion(c, request, session); - LOGGER.debug("QUERY getSeriesCriteria(request): {}", HibernateHelper.getSqlString(c)); - return c; - } - - protected Criteria getSeriesCriteria(GetResultRequest request, Collection features, Session session) throws OwsExceptionReport { - final Criteria c = createCriteriaFor(request.getObservedProperty(), request.getOffering(), features, - session); -// checkAndAddResultFilterCriterion(c, request, session); -// checkAndAddSpatialFilterCriterion(c, request, session); - LOGGER.debug("QUERY getSeriesCriteria(request): {}", HibernateHelper.getSqlString(c)); - return c; - } - public Criteria getSeriesCriteria(Collection procedures, Collection observedProperties, Collection features, Session session) { final Criteria c = createCriteriaFor(procedures, observedProperties, features, session); @@ -826,23 +842,24 @@ private Criteria createCriteriaFor(String observedProperty, String offering, Col return c; } - protected void checkAndAddResultFilterCriterion(Criteria c, GetDataAvailabilityRequest request, Session session) + + protected void checkAndAddResultFilterCriterion(Criteria c, GetDataAvailabilityRequest request, SubQueryIdentifier identifier, Session session) throws OwsExceptionReport { if (request.hasResultFilter()) { - addResultfilter(c, request.getResultFilter()); + addResultfilter(c, request.getResultFilter(), identifier); } } - protected void checkAndAddResultFilterCriterion(Criteria c, GetObservationRequest request, Session session) + protected void checkAndAddResultFilterCriterion(Criteria c, GetObservationRequest request, SubQueryIdentifier identifier, Session session) throws OwsExceptionReport { if (request.hasResultFilter() && request.getResultFilter() instanceof ComparisonFilter) { - addResultfilter(c, (ComparisonFilter) request.getResultFilter()); + addResultfilter(c, request.getResultFilter(), identifier); } } - private void addResultfilter(Criteria c, ComparisonFilter resultFilter) throws CodedException { + private void addResultfilter(Criteria c, ComparisonFilter resultFilter, SubQueryIdentifier identifier) throws CodedException { Criterion resultFilterExpression = ResultFilterRestrictions.getResultFilterExpression(resultFilter, - getResultFilterClasses(), DatasetEntity.PROPERTY_ID, DataEntity.PROPERTY_DATASET); + getResultFilterClasses(), DatasetEntity.PROPERTY_ID, DataEntity.PROPERTY_DATASET, identifier); if (resultFilterExpression != null) { c.add(resultFilterExpression); } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesObservationDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesObservationDAO.java index 3563bf548b..99c59be936 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesObservationDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesObservationDAO.java @@ -71,6 +71,8 @@ import org.n52.sos.ds.hibernate.dao.observation.ObservationContext; import org.n52.sos.ds.hibernate.util.HibernateConstants; import org.n52.sos.ds.hibernate.util.HibernateHelper; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions.SubQueryIdentifier; import org.n52.sos.ds.hibernate.util.ScrollableIterable; import org.n52.sos.ds.hibernate.util.observation.ExtensionFesFilterCriteriaAdder; import org.n52.sos.util.GeometryHandler; @@ -489,7 +491,7 @@ public Criteria getOfferingMinMaxTimeCriteriaForSeriesObservation(DatasetEntity public ScrollableResults getSeriesNotMatchingSeries(Set seriesIDs, GetObservationRequest request, Set features, Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { - Criteria c = getSeriesObservationCriteriaFor(request, features, temporalFilterCriterion, null, session); + Criteria c = getScrollableSeriesObservationCriteriaFor(request, features, temporalFilterCriterion, null, session); c.createCriteria(DataEntity.PROPERTY_DATASET) .add(Restrictions.not(Restrictions.in(DatasetEntity.PROPERTY_ID, seriesIDs))); c.setProjection(Projections.property(DataEntity.PROPERTY_DATASET)); @@ -522,14 +524,29 @@ public ScrollableResults getSeriesNotMatchingSeries(Set seriesIDs, GetObse * @return Series observations {@link Criteria} * @throws OwsExceptionReport */ - protected Criteria getSeriesObservationCriteriaFor(GetObservationRequest request, Collection features, + protected List> getSeriesObservationCriteriaFor(GetObservationRequest request, Collection features, Criterion filterCriterion, IndeterminateValue sosIndeterminateTime, Session session) throws OwsExceptionReport { - final Criteria observationCriteria = getDefaultObservationCriteria(session); + + if (request.hasResultFilter()) { + List> list = new LinkedList<>(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getDefaultSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session); + checkAndAddResultFilterCriterion(c, request, identifier, session); + list.addAll(c.list()); + } + return list; + } + return getDefaultSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session).list(); + } + + private Criteria getDefaultSeriesObservationCriteriaFor(GetObservationRequest request, Collection features, + Criterion filterCriterion, SosIndeterminateTime sosIndeterminateTime, Session session) + throws OwsExceptionReport { + final Criteria observationCriteria = getDefaultObservationCriteria(session); Criteria seriesCriteria = observationCriteria.createCriteria(DataEntity.PROPERTY_DATASET); checkAndAddSpatialFilteringProfileCriterion(observationCriteria, request, session); - checkAndAddResultFilterCriterion(observationCriteria, request, session); addSpecificRestrictions(seriesCriteria, request); if (CollectionHelper.isNotEmpty(request.getProcedures())) { @@ -568,7 +585,54 @@ protected Criteria getSeriesObservationCriteriaFor(GetObservationRequest request HibernateHelper.getSqlString(observationCriteria)); return observationCriteria; } + + protected Criteria getScrollableSeriesObservationCriteriaFor(GetObservationRequest request, Collection features, + Criterion filterCriterion, SosIndeterminateTime sosIndeterminateTime, Session session) + throws OwsExceptionReport { + final Criteria observationCriteria = getDefaultObservationCriteria(session); + + Criteria seriesCriteria = observationCriteria.createCriteria(DataEntity.SERIES); + + checkAndAddSpatialFilteringProfileCriterion(observationCriteria, request, session); + checkAndAddResultFilterCriterion(observationCriteria, request, null, session); + + addSpecificRestrictions(seriesCriteria, request); + if (CollectionHelper.isNotEmpty(request.getProcedures())) { + seriesCriteria.createCriteria(Series.PROCEDURE) + .add(Restrictions.in(Procedure.IDENTIFIER, request.getProcedures())); + } + + if (CollectionHelper.isNotEmpty(request.getObservedProperties())) { + seriesCriteria.createCriteria(Series.OBSERVABLE_PROPERTY) + .add(Restrictions.in(ObservableProperty.IDENTIFIER, request.getObservedProperties())); + } + + if (CollectionHelper.isNotEmpty(features)) { + seriesCriteria.createCriteria(Series.FEATURE_OF_INTEREST) + .add(Restrictions.in(FeatureOfInterest.IDENTIFIER, features)); + } + + if (CollectionHelper.isNotEmpty(request.getOfferings())) { + observationCriteria.createCriteria(AbstractSeriesObservation.OFFERINGS) + .add(Restrictions.in(Offering.IDENTIFIER, request.getOfferings())); + } + String logArgs = "request, features, offerings"; + if (filterCriterion != null) { + logArgs += ", filterCriterion"; + observationCriteria.add(filterCriterion); + } + if (sosIndeterminateTime != null) { + logArgs += ", sosIndeterminateTime"; + addIndeterminateTimeRestriction(observationCriteria, sosIndeterminateTime); + } + if (request.isSetFesFilterExtension()) { + new ExtensionFesFilterCriteriaAdder(observationCriteria, request.getFesFilterExtensions()).add(); + } + LOGGER.debug("QUERY getSeriesObservationFor({}): {}", logArgs, + HibernateHelper.getSqlString(observationCriteria)); + return observationCriteria; + } private String createSeriesAliasAndRestrictions(Criteria c) { String alias = "s"; @@ -638,9 +702,11 @@ public ScrollableResults getStreamingSeriesObservationsFor(GetObservationRequest * @return {@link ScrollableResults} of Series observations that fits * @throws OwsExceptionReport */ - protected ScrollableResults getStreamingSeriesObservationsFor(GetObservationRequest request, Collection features, - Criterion filterCriterion, IndeterminateValue sosIndeterminateTime, Session session) throws OwsExceptionReport { - return getSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session).setReadOnly(true).scroll(ScrollMode.FORWARD_ONLY); + protected ScrollableResults getStreamingSeriesObservationsFor(GetObservationRequest request, + Collection features, Criterion filterCriterion, SosIndeterminateTime sosIndeterminateTime, + Session session) throws OwsExceptionReport { + return getScrollableSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session) + .setReadOnly(true).scroll(ScrollMode.FORWARD_ONLY); } /** @@ -817,13 +883,39 @@ public DateTime getMaxSeriesObservationTime(DatasetEntity series, Session sessio protected abstract void addSpecificRestrictions(Criteria c, GetObservationRequest request) throws OwsExceptionReport; - protected Criteria getSeriesObservationCriteriaFor(DatasetEntity series, GetObservationRequest request, - IndeterminateValue sosIndeterminateTime, Session session) throws OwsExceptionReport { + protected List> getSeriesObservationCriteriaFor(Series series, GetObservationRequest request, + SosIndeterminateTime sosIndeterminateTime, Session session) throws OwsExceptionReport { + if (request.hasResultFilter()) { + List> list = new LinkedList<>(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + final Criteria c = + getDefaultObservationCriteria(session).add( + Restrictions.eq(AbstractSeriesObservation.SERIES, series)); + checkAndAddSpatialFilteringProfileCriterion(c, request, session); + checkAndAddResultFilterCriterion(c, request, identifier, session); + + if (request.isSetOffering()) { + c.createCriteria(AbstractSeriesObservation.OFFERINGS).add( + Restrictions.in(Offering.IDENTIFIER, request.getOfferings())); + } + String logArgs = "request, features, offerings"; + logArgs += ", sosIndeterminateTime"; + if (series.isSetFirstTimeStamp() && sosIndeterminateTime.equals(SosIndeterminateTime.first)) { + addIndeterminateTimeRestriction(c, sosIndeterminateTime, series.getFirstTimeStamp()); + } else if (series.isSetLastTimeStamp() && sosIndeterminateTime.equals(SosIndeterminateTime.latest)) { + addIndeterminateTimeRestriction(c, sosIndeterminateTime, series.getLastTimeStamp()); + } else { + addIndeterminateTimeRestriction(c, sosIndeterminateTime); + } + LOGGER.debug("QUERY getSeriesObservationFor({}) and result filter sub query '{}': {}", logArgs, identifier.name(), HibernateHelper.getSqlString(c)); + list.addAll(c.list()); + } + return list; + } final Criteria c = getDefaultObservationCriteria(session).add( Restrictions.eq(DataEntity.PROPERTY_DATASET, series)); checkAndAddSpatialFilteringProfileCriterion(c, request, session); - checkAndAddResultFilterCriterion(c, request, session); if (request.isSetOffering()) { c.createCriteria(DatasetEntity.PROPERTY_OFFERING).add( @@ -839,7 +931,7 @@ protected Criteria getSeriesObservationCriteriaFor(DatasetEntity series, GetObse addIndeterminateTimeRestriction(c, sosIndeterminateTime); } LOGGER.debug("QUERY getSeriesObservationFor({}): {}", logArgs, HibernateHelper.getSqlString(c)); - return c; + return c.list(); } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueDAO.java index f1f80d6eb3..cea4e2be66 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueDAO.java @@ -28,6 +28,7 @@ */ package org.n52.sos.ds.hibernate.dao.observation.series; +import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -48,7 +49,8 @@ import org.n52.shetland.ogc.sos.request.GetObservationRequest; import org.n52.sos.ds.hibernate.dao.observation.AbstractValueDAO; import org.n52.sos.ds.hibernate.util.HibernateHelper; -import org.n52.sos.ds.hibernate.util.observation.ExtensionFesFilterCriteriaAdder; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions; +import org.n52.sos.ds.hibernate.util.ResultFilterRestrictions.SubQueryIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,13 +86,13 @@ public abstract class AbstractSeriesValueDAO extends AbstractValueDAO { */ public ScrollableResults getStreamingSeriesValuesFor(AbstractObservationRequest request, long series, Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { - return getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session).scroll( + return getScrollableSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session).scroll( ScrollMode.FORWARD_ONLY); } public ScrollableResults getStreamingSeriesValuesFor(AbstractObservationRequest request, Set series, Criterion temporalFilterCriterion, Session session) throws HibernateException, OwsExceptionReport { - return getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session).scroll( + return getScrollableSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session).scroll( ScrollMode.FORWARD_ONLY); } @@ -109,12 +111,12 @@ public ScrollableResults getStreamingSeriesValuesFor(AbstractObservationRequest */ public ScrollableResults getStreamingSeriesValuesFor(AbstractObservationRequest request, long series, Session session) throws OwsExceptionReport { - return getSeriesValueCriteriaFor(request, series, null, session).scroll(ScrollMode.FORWARD_ONLY); + return getScrollableSeriesValueCriteriaFor(request, series, null, session).scroll(ScrollMode.FORWARD_ONLY); } public ScrollableResults getStreamingSeriesValuesFor(AbstractObservationRequest request, Set series, Session session) throws HibernateException, OwsExceptionReport { - return getSeriesValueCriteriaFor(request, series, null, session).scroll(ScrollMode.FORWARD_ONLY); + return getScrollableSeriesValueCriteriaFor(request, series, null, session).scroll(ScrollMode.FORWARD_ONLY); } /** @@ -168,9 +170,20 @@ public List> getStreamingSeriesValuesFor(AbstractObservationReques public List> getStreamingSeriesValuesFor(AbstractObservationRequest request, Set series, Criterion temporalFilterCriterion, int chunkSize, int currentRow, Session session) throws OwsExceptionReport { - Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session); - addChunkValuesToCriteria(c, chunkSize, currentRow, request); - return (List>) c.list(); + if (request instanceof GetObservationRequest && ((GetObservationRequest) request).hasResultFilter()) { + List> list = new LinkedList<>(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session); + addChunkValuesToCriteria(c, chunkSize, currentRow, request); + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, identifier, session); + list.addAll(c.list()); + } + return list; + } else { + Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, session); + addChunkValuesToCriteria(c, chunkSize, currentRow, request); + return (List>) c.list(); + } } /** @@ -193,9 +206,20 @@ public List> getStreamingSeriesValuesFor(AbstractObservationReques @SuppressWarnings("unchecked") public List> getStreamingSeriesValuesFor(AbstractObservationRequest request, Set series, int chunkSize, int currentRow, Session session) throws OwsExceptionReport { - Criteria c = getSeriesValueCriteriaFor(request, series, null, session); - addChunkValuesToCriteria(c, chunkSize, currentRow, request); - return (List>) c.list(); + if (request instanceof GetObservationRequest && ((GetObservationRequest) request).hasResultFilter()) { + List> list = new LinkedList<>(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getSeriesValueCriteriaFor(request, series, null, session); + addChunkValuesToCriteria(c, chunkSize, currentRow, request); + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, identifier, session); + list.addAll(c.list()); + } + return list; + } else { + Criteria c = getSeriesValueCriteriaFor(request, series, null, session); + addChunkValuesToCriteria(c, chunkSize, currentRow, request); + return (List>) c.list(); + } } /** @@ -218,9 +242,20 @@ public List> getStreamingSeriesValuesFor(AbstractObservationReques @SuppressWarnings("unchecked") public List> getStreamingSeriesValuesFor(AbstractObservationRequest request, long series, int chunkSize, int currentRow, Session session) throws OwsExceptionReport { - Criteria c = getSeriesValueCriteriaFor(request, series, null, session); - addChunkValuesToCriteria(c, chunkSize, currentRow, request); - return (List>) c.list(); + if (request instanceof GetObservationRequest && ((GetObservationRequest) request).hasResultFilter()) { + List> list = new LinkedList<>(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getSeriesValueCriteriaFor(request, series, null, session); + addChunkValuesToCriteria(c, chunkSize, currentRow, request); + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, identifier, session); + list.addAll(c.list()); + } + return list; + } else { + Criteria c = getSeriesValueCriteriaFor(request, series, null, session); + addChunkValuesToCriteria(c, chunkSize, currentRow, request); + return (List>) c.list(); + } } /** @@ -241,26 +276,57 @@ public List> getStreamingSeriesValuesFor(AbstractObservationReques */ private Criteria getSeriesValueCriteriaFor(AbstractObservationRequest request, long series, Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { - final Criteria c = getDefaultObservationCriteria(session).createAlias(DataEntity.PROPERTY_DATASET, "s"); - c.addOrder(Order.asc(getOrderColumn(request))); + final Criteria c = getDefaultSeriesValueCriteriaFor(request, temporalFilterCriterion, session); c.add(Restrictions.eq("s." + DatasetEntity.PROPERTY_ID, series)); - String logArgs = "request, series"; + return c.setReadOnly(true); + } + + /** + * Get {@link Criteria} for parameter + * + * @param request + * {@link AbstractObservationRequest} + * @param series + * Datasource series ids + * @param temporalFilterCriterion + * Temporal filter {@link Criterion} + * @param session + * Hibernate Session + * @return Resulting {@link Criteria} + * @throws OwsExceptionReport + * If an error occurs when adding Spatial Filtering Profile + * restrictions + */ + private Criteria getSeriesValueCriteriaFor(AbstractObservationRequest request, Set series, + Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { + final Criteria c = getDefaultSeriesValueCriteriaFor(request, temporalFilterCriterion, session); + c.add(Restrictions.in("s." + Series.ID, series)); + return c.setReadOnly(true); + } + + /** + * Get {@link Criteria} for parameter + * + * @param request + * {@link AbstractObservationRequest} + * @param series + * Datasource series id + * @param temporalFilterCriterion + * Temporal filter {@link Criterion} + * @param session + * Hibernate Session + * @return Resulting {@link Criteria} + * @throws OwsExceptionReport + * If an error occurs when adding Spatial Filtering Profile + * restrictions + */ + private Criteria getScrollableSeriesValueCriteriaFor(AbstractObservationRequest request, long series, + Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { + final Criteria c = getDefaultSeriesValueCriteriaFor(request, temporalFilterCriterion, session); + c.add(Restrictions.eq("s." + Series.ID, series)); if (request instanceof GetObservationRequest) { - GetObservationRequest getObsReq = (GetObservationRequest)request; - checkAndAddSpatialFilteringProfileCriterion(c, getObsReq, session); - checkAndAddResultFilterCriterion(c, getObsReq, session); - - logArgs += ", offerings"; - if (temporalFilterCriterion != null) { - logArgs += ", filterCriterion"; - c.add(temporalFilterCriterion); - } - addSpecificRestrictions(c, getObsReq); - if (getObsReq.isSetFesFilterExtension()) { - new ExtensionFesFilterCriteriaAdder(c, getObsReq.getFesFilterExtensions()).add(); - } + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, null, session); } - LOGGER.debug("QUERY getStreamingSeriesValuesFor({}): {}", logArgs, HibernateHelper.getSqlString(c)); return c.setReadOnly(true); } @@ -280,29 +346,25 @@ private Criteria getSeriesValueCriteriaFor(AbstractObservationRequest request, l * If an error occurs when adding Spatial Filtering Profile * restrictions */ - private Criteria getSeriesValueCriteriaFor(AbstractObservationRequest request, Set series, + private Criteria getScrollableSeriesValueCriteriaFor(AbstractObservationRequest request, Set series, + Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { + final Criteria c = getDefaultSeriesValueCriteriaFor(request, temporalFilterCriterion, session); + c.add(Restrictions.in("s." + Series.ID, series)); + if (request instanceof GetObservationRequest) { + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, null, session); + } + return c.setReadOnly(true); + } + + private Criteria getDefaultSeriesValueCriteriaFor(AbstractObservationRequest request, Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { - final Criteria c = getDefaultObservationCriteria(session).createAlias(DataEntity.PROPERTY_DATASET, "s"); + final Criteria c = getDefaultObservationCriteria(session).createAlias(AbstractValuedSeriesObservation.SERIES, "s"); c.addOrder(Order.asc(getOrderColumn(request))); c.add(Restrictions.in("s." + DatasetEntity.PROPERTY_ID, series)); String logArgs = "request, series"; -// -// HibernateHelper.getSqlString(DetachedCriteria.forClass(ProfileValuedSeriesObservation.class) -// .createCriteria("value", "v").add(Subqueries.in("v.observationId", DetachedCriteria.forClass(NumericValuedSeriesObservation.class).add(Restrictions.eq("child", true)))) -// .getExecutableCriteria(session)); -// -// HibernateHelper.getSqlString(DetachedCriteria.forClass(ProfileValuedSeriesObservation.class) -// .createCriteria("value", "v").add(Restrictions.eq("child", true)).add(Restrictions.eq("class", NumericValuedSeriesObservation.class)) -// .getExecutableCriteria(session)); -// -// HibernateHelper.getSqlString(DetachedCriteria.forClass(ProfileValuedSeriesObservation.class) -// .createCriteria("value", "v").add(Restrictions.eq("class", NumericValuedSeriesObservation.class)) -// .getExecutableCriteria(session)); - if (request instanceof GetObservationRequest) { GetObservationRequest getObsReq = (GetObservationRequest)request; checkAndAddSpatialFilteringProfileCriterion(c, getObsReq, session); - checkAndAddResultFilterCriterion(c, getObsReq, session); if (temporalFilterCriterion != null) { logArgs += ", filterCriterion"; diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueTimeDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueTimeDAO.java index 9d5eddccf3..bfeb71ce63 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueTimeDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/AbstractSeriesValueTimeDAO.java @@ -88,12 +88,22 @@ public abstract class AbstractSeriesValueTimeDAO extends AbstractValueTimeDAO { */ public ObservationTimeExtrema getTimeExtremaForSeries(AbstractObservationRequest request, long series, Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { - Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, null, session); - addMinMaxTimeProjection(c); - LOGGER.debug("QUERY getTimeExtremaForSeries(request, series, temporalFilter): {}", - HibernateHelper.getSqlString(c)); - return parseMinMaxTime((Object[]) c.uniqueResult()); - + if (request instanceof GetObservationRequest && ((GetObservationRequest) request).hasResultFilter()) { + ObservationTimeExtrema ote = new ObservationTimeExtrema(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, null, session); + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, identifier, session); + addMinMaxTimeProjection(c); + ote.expand(parseMinMaxTime((Object[]) c.uniqueResult())); + } + return ote; + } else { + Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, null, session); + addMinMaxTimeProjection(c); + LOGGER.debug("QUERY getTimeExtremaForSeries(request, series, temporalFilter): {}", + HibernateHelper.getSqlString(c)); + return parseMinMaxTime((Object[]) c.uniqueResult()); + } } /** @@ -114,12 +124,22 @@ public ObservationTimeExtrema getTimeExtremaForSeries(AbstractObservationRequest */ public ObservationTimeExtrema getTimeExtremaForSeries(AbstractObservationRequest request, Set series, Criterion temporalFilterCriterion, Session session) throws OwsExceptionReport { - Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, null, session); - addMinMaxTimeProjection(c); - LOGGER.debug("QUERY getTimeExtremaForSeries(request, series, temporalFilter): {}", - HibernateHelper.getSqlString(c)); - return parseMinMaxTime((Object[]) c.uniqueResult()); - + if (request instanceof GetObservationRequest && ((GetObservationRequest) request).hasResultFilter()) { + ObservationTimeExtrema ote = new ObservationTimeExtrema(); + for (SubQueryIdentifier identifier : ResultFilterRestrictions.SubQueryIdentifier.values()) { + Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, null, session); + checkAndAddResultFilterCriterion(c, (GetObservationRequest) request, identifier, session); + addMinMaxTimeProjection(c); + ote.expand(parseMinMaxTime((Object[]) c.uniqueResult())); + } + return ote; + } else { + Criteria c = getSeriesValueCriteriaFor(request, series, temporalFilterCriterion, null, session); + addMinMaxTimeProjection(c); + LOGGER.debug("QUERY getTimeExtremaForSeries(request, series, temporalFilter): {}", + HibernateHelper.getSqlString(c)); + return parseMinMaxTime((Object[]) c.uniqueResult()); + } } /** @@ -324,7 +344,7 @@ private Criteria getSeriesValueCriteriaFor(AbstractObservationRequest request, l if (request instanceof GetObservationRequest) { GetObservationRequest getObsReq = (GetObservationRequest)request; checkAndAddSpatialFilteringProfileCriterion(c, getObsReq, session); - checkAndAddResultFilterCriterion(c, getObsReq, session); + checkAndAddResultFilterCriterion(c, getObsReq, null, session); if (temporalFilterCriterion != null) { logArgs += ", filterCriterion"; c.add(temporalFilterCriterion); @@ -347,7 +367,6 @@ private Criteria getSeriesValueCriteriaFor(AbstractObservationRequest request, S if (request instanceof GetObservationRequest) { GetObservationRequest getObsReq = (GetObservationRequest)request; checkAndAddSpatialFilteringProfileCriterion(c, getObsReq, session); - checkAndAddResultFilterCriterion(c, getObsReq, session); if (temporalFilterCriterion != null) { logArgs += ", filterCriterion"; diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesDAO.java index cb90ac7e47..4b0419bdcb 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesDAO.java @@ -72,18 +72,19 @@ public SeriesDAO(DaoFactory daoFactory) { } @Override - @SuppressWarnings("unchecked") public List getSeries(GetObservationRequest request, Collection features, Session session) throws OwsExceptionReport { + List series = new ArrayList<>(); if (CollectionHelper.isNotEmpty(features)) { List series = new ArrayList<>(); for (List ids : QueryHelper.getListsForIdentifiers(features)) { - series.addAll(getSeriesCriteria(request, ids, session).list()); + series.addAll(getSeriesSet(request, ids, session)); } - return series; + } else { - return getSeriesCriteria(request, features, session).list(); + series.addAll(getSeriesSet(request, features, session)); } + return series; } @SuppressWarnings("unchecked") @@ -92,11 +93,10 @@ public List getSeries(GetObservationByIdRequest request, Session return getSeriesCriteria(request, session).list(); } - @SuppressWarnings("unchecked") @Override public List getSeries(GetDataAvailabilityRequest request, Session session) throws OwsExceptionReport { - return getSeriesCriteria(request, session).list(); + return new ArrayList<>(getSeriesCriteria(request, session)); } @SuppressWarnings("unchecked") @@ -170,6 +170,9 @@ public DatasetEntity getSeriesFor(String procedure, String observableProperty, S } @Override + public DatasetEntity getOrInsertSeries(ObservationContext ctx, final Session session) throws CodedException { + return getOrInsert(ctx, session); + public List getSeries(String procedure, String observableProperty, Session session) { return (List) getSeriesCriteriaFor(procedure, observableProperty, session).list(); } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesObservationDAO.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesObservationDAO.java index 76f2ec5be3..4a8f11e71a 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesObservationDAO.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/dao/observation/series/SeriesObservationDAO.java @@ -191,27 +191,25 @@ public List> getSeriesObservationsFor(GetObservationRequest reques * @return Series observations that fit * @throws OwsExceptionReport */ - @SuppressWarnings("unchecked") @Override protected List> getSeriesObservationsFor(GetObservationRequest request, Collection features, Criterion filterCriterion, IndeterminateValue sosIndeterminateTime, Session session) throws OwsExceptionReport { if (CollectionHelper.isNotEmpty(features)) { List> observations = new ArrayList<>(); for (List ids : QueryHelper.getListsForIdentifiers(features)) { - observations.addAll(getSeriesObservationCriteriaFor(request, ids, filterCriterion, sosIndeterminateTime, session).list()); + observations.addAll(getSeriesObservationCriteriaFor(request, ids, filterCriterion, sosIndeterminateTime, session)); } return observations; } else { - return getSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session).list(); + return getSeriesObservationCriteriaFor(request, features, filterCriterion, sosIndeterminateTime, session); } } - @SuppressWarnings("unchecked") @Override public List> getSeriesObservationsFor(DatasetEntity series, GetObservationRequest request, IndeterminateValue sosIndeterminateTime, Session session) throws OwsExceptionReport { - return getSeriesObservationCriteriaFor(series, request, sosIndeterminateTime, session).list(); + return getSeriesObservationCriteriaFor(series, request, sosIndeterminateTime, session); } @Override diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ObservationTimeExtrema.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ObservationTimeExtrema.java index f21b2cdcef..d86a8ef7bd 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ObservationTimeExtrema.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ObservationTimeExtrema.java @@ -81,4 +81,22 @@ public boolean isEmpty() { return !isSetPhenomenonTimes() && !isSetResultTimes() && !isSetValidTime(); } + public void expand(ObservationTimeExtrema ote) { + if (isEmpty() && !ote.isEmpty()) { + setMinPhenomenonTime(ote.getMinPhenomenonTime()); + setMaxPhenomenonTime(ote.getMaxPhenomenonTime()); + setMinResultTime(ote.getMinResultTime()); + setMaxResultTime(ote.getMaxResultTime()); + setMinValidTime(ote.getMinValidTime()); + setMaxValidTime(ote.getMaxValidTime()); + } else { + setMinPhenomenonTime(getMinPhenomenonTime().isAfter(ote.getMinPhenomenonTime()) ? ote.getMinPhenomenonTime() : getMinPhenomenonTime()); + setMaxPhenomenonTime(getMaxPhenomenonTime().isBefore(ote.getMaxPhenomenonTime()) ? ote.getMaxPhenomenonTime() : getMaxPhenomenonTime()); + setMinResultTime(getMinResultTime().isAfter(ote.getMinResultTime()) ? ote.getMinResultTime() : getMinResultTime()); + setMaxResultTime(getMaxResultTime().isBefore(ote.getMaxResultTime()) ? ote.getMaxResultTime() : getMaxResultTime()); + setMinValidTime(getMinValidTime().isAfter(ote.getMinValidTime()) ? ote.getMinValidTime() : getMinValidTime()); + setMaxValidTime(getMaxValidTime().isBefore(ote.getMaxValidTime()) ? ote.getMaxValidTime() : getMaxValidTime()); + } + } + } diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ResultFilterRestrictions.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ResultFilterRestrictions.java index 27a9812080..be16b3b0e3 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ResultFilterRestrictions.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/ResultFilterRestrictions.java @@ -55,28 +55,37 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, ResultFilterClasses resultFilterClasses, String subqueryColumn, String column) throws CodedException { + return getResultFilterExpression(resultFilter, resultFilterClasses, subqueryColumn, column, null); + } + + public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, ResultFilterClasses resultFilterClasses, String column, SubQueryIdentifier identifier) throws CodedException { + return getResultFilterExpression(resultFilter, resultFilterClasses, column, column, identifier); + } + + public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, + ResultFilterClasses resultFilterClasses, String subqueryColumn, String column, SubQueryIdentifier identifier) throws NoApplicableCodeException, InvalidParameterValueException { List list = new LinkedList<>(); - List complexLlist = new LinkedList<>(); + List complexList = new LinkedList<>(); switch (resultFilter.getOperator()) { case PropertyIsEqualTo: if (isNumeric(resultFilter.getValue())) { list.add(createEqDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), column)); - complexLlist.add(createEqDC(createDC(resultFilterClasses.getNumeric()), + complexList.add(createEqDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), DataEntity.PROPERTY_ID)); } if (isCount(resultFilter.getValue())) { list.add(createEqDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), column)); - complexLlist.add(createEqDC(createDC(resultFilterClasses.getCount()), + complexList.add(createEqDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (!isNumeric(resultFilter.getValue()) && !isCount(resultFilter.getValue())) { list.add(createEqDC(createDC(resultFilterClasses.getCategory()), resultFilter.getValue(), column)); list.add(createEqDC(createDC(resultFilterClasses.getText()), resultFilter.getValue(), column)); - complexLlist.add(createEqDC(createDC(resultFilterClasses.getCategory()), resultFilter.getValue(), + complexList.add(createEqDC(createDC(resultFilterClasses.getCategory()), resultFilter.getValue(), DataEntity.PROPERTY_ID)); - complexLlist.add(createEqDC(createDC(resultFilterClasses.getText()), resultFilter.getValue(), + complexList.add(createEqDC(createDC(resultFilterClasses.getText()), resultFilter.getValue(), DataEntity.PROPERTY_ID)); } break; @@ -85,7 +94,7 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, list.add(createBetweenDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), Integer.parseInt(resultFilter.getValueUpper()), column)); - complexLlist.add(createBetweenDC(createDC(resultFilterClasses.getCount()), + complexList.add(createBetweenDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), Integer.parseInt(resultFilter.getValueUpper()), DataEntity.PROPERTY_ID)); } @@ -93,7 +102,7 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, list.add(createBetweenDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), Double.parseDouble(resultFilter.getValueUpper()), column)); - complexLlist.add(createBetweenDC(createDC(resultFilterClasses.getNumeric()), + complexList.add(createBetweenDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), Double.parseDouble(resultFilter.getValueUpper()),DataEntity.PROPERTY_ID)); } @@ -105,13 +114,13 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, if (isCount(resultFilter.getValue())) { list.add(createGtDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), column)); - complexLlist.add(createGtDC(createDC(resultFilterClasses.getCount()), + complexList.add(createGtDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (isNumeric(resultFilter.getValue())) { list.add(createGtDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), column)); - complexLlist.add(createGtDC(createDC(resultFilterClasses.getNumeric()), + complexList.add(createGtDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (!isNumeric(resultFilter.getValue()) && !isCount(resultFilter.getValue())) { @@ -122,13 +131,13 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, if (isCount(resultFilter.getValue())) { list.add(createGeDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), column)); - complexLlist.add(createGeDC(createDC(resultFilterClasses.getCount()), + complexList.add(createGeDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (isNumeric(resultFilter.getValue())) { list.add(createGeDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), column)); - complexLlist.add(createGeDC(createDC(resultFilterClasses.getNumeric()), + complexList.add(createGeDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (!isNumeric(resultFilter.getValue()) && !isCount(resultFilter.getValue())) { @@ -139,13 +148,13 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, if (isCount(resultFilter.getValue())) { list.add(createLtDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), column)); - complexLlist.add(createLtDC(createDC(resultFilterClasses.getCount()), + complexList.add(createLtDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (isNumeric(resultFilter.getValue())) { list.add(createLtDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), column)); - complexLlist.add(createLtDC(createDC(resultFilterClasses.getNumeric()), + complexList.add(createLtDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (!isNumeric(resultFilter.getValue()) && !isCount(resultFilter.getValue())) { @@ -156,13 +165,13 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, if (isCount(resultFilter.getValue())) { list.add(createLeDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()), column)); - complexLlist.add(createLeDC(createDC(resultFilterClasses.getCount()), + complexList.add(createLeDC(createDC(resultFilterClasses.getCount()), Integer.parseInt(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (isNumeric(resultFilter.getValue())) { list.add(createLeDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()), column)); - complexLlist.add(createLeDC(createDC(resultFilterClasses.getNumeric()), + complexList.add(createLeDC(createDC(resultFilterClasses.getNumeric()), Double.parseDouble(resultFilter.getValue()),DataEntity.PROPERTY_ID)); } if (!isNumeric(resultFilter.getValue()) && !isCount(resultFilter.getValue())) { @@ -172,18 +181,30 @@ public static Criterion getResultFilterExpression(ComparisonFilter resultFilter, case PropertyIsLike: list.add(createLikeDC(createDC(resultFilterClasses.getCategory()), resultFilter, column)); list.add(createLikeDC(createDC(resultFilterClasses.getText()), resultFilter, column)); - complexLlist.add(createLikeDC(createDC(resultFilterClasses.getCategory()), resultFilter, + complexList.add(createLikeDC(createDC(resultFilterClasses.getCategory()), resultFilter, DataEntity.PROPERTY_ID)); - complexLlist.add( + complexList.add( createLikeDC(createDC(resultFilterClasses.getText()), resultFilter,DataEntity.PROPERTY_ID)); break; default: throw new InvalidParameterValueException(ResultFilterConstants.RESULT_FILTER + ".operator", resultFilter.getOperator().toString()); } - if (!complexLlist.isEmpty()) { - list.add(createProfileDC(createDC(resultFilterClasses.getProfile(), "po"), complexLlist, column)); - list.add(createComplexDC(createDC(resultFilterClasses.getComplex(), "co"), complexLlist, column)); + if (!complexList.isEmpty()) { + if (identifier == null) { + if (HibernateHelper.isEntitySupported(resultFilterClasses.getProfile())) { + list.add(createProfileDC(createDC(resultFilterClasses.getProfile(), "po"), complexList, column)); + } + if (HibernateHelper.isEntitySupported(resultFilterClasses.getComplex())) { + list.add(createComplexDC(createDC(resultFilterClasses.getComplex(), "co"), complexList, column)); + } + } else if (identifier.equals(SubQueryIdentifier.Profile) && HibernateHelper.isEntitySupported(resultFilterClasses.getProfile())) { + list.clear(); + list.add(createProfileDC(createDC(resultFilterClasses.getProfile(), "po"), complexList, column)); + } else if (identifier.equals(SubQueryIdentifier.Complex) && HibernateHelper.isEntitySupported(resultFilterClasses.getComplex())) { + list.clear(); + list.add(createComplexDC(createDC(resultFilterClasses.getComplex(), "co"), complexList, column)); + } } if (!list.isEmpty()) { if (list.size() > 1) { @@ -293,4 +314,8 @@ private static DetachedCriteria createDC(DetachedCriteria dc, List hObservation, OmObservation sosObservation) throws CodedException { diff --git a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/observation/ObservationConstellationOmObservationCreator.java b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/observation/ObservationConstellationOmObservationCreator.java index 1ab99f949d..0beaa79692 100644 --- a/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/observation/ObservationConstellationOmObservationCreator.java +++ b/hibernate/common/src/main/java/org/n52/sos/ds/hibernate/util/observation/ObservationConstellationOmObservationCreator.java @@ -46,6 +46,7 @@ import org.n52.shetland.ogc.sos.SosProcedureDescription; import org.n52.shetland.ogc.sos.request.AbstractObservationRequest; import org.n52.sos.ds.hibernate.dao.FeatureOfInterestDAO; +import org.n52.sos.ds.hibernate.entities.Procedure; import org.n52.sos.ds.hibernate.util.HibernateHelper; import org.n52.sos.ds.hibernate.util.procedure.generator.AbstractHibernateProcedureDescriptionGeneratorSml; import org.slf4j.Logger; diff --git a/hibernate/common/src/test/java/org/n52/sos/ds/hibernate/dao/AbstractObservationDAOTest.java b/hibernate/common/src/test/java/org/n52/sos/ds/hibernate/dao/AbstractObservationDAOTest.java index 55e5262602..e6018ffa58 100644 --- a/hibernate/common/src/test/java/org/n52/sos/ds/hibernate/dao/AbstractObservationDAOTest.java +++ b/hibernate/common/src/test/java/org/n52/sos/ds/hibernate/dao/AbstractObservationDAOTest.java @@ -177,103 +177,87 @@ public TestObservationDAO(DaoFactory daoFactory) { @Override protected void addObservationContextToObservation(ObservationContext ctx, Data observation, Session session) throws CodedException { - // TODO Auto-generated method stub } @Override public Criteria getObservationInfoCriteriaForFeatureOfInterestAndProcedure(String feature, String procedure, Session session) { - // TODO Auto-generated method stub return null; } @Override public Criteria getObservationInfoCriteriaForFeatureOfInterestAndOffering(String feature, String offering, Session session) { - // TODO Auto-generated method stub return null; } @Override public Criteria getObservationCriteriaForProcedure(String procedure, Session session) throws CodedException { - // TODO Auto-generated method stub return null; } @Override public Criteria getObservationCriteriaForObservableProperty(String observableProperty, Session session) throws CodedException { - // TODO Auto-generated method stub return null; } @Override public Criteria getObservationCriteriaForFeatureOfInterest(String featureOfInterest, Session session) throws CodedException { - // TODO Auto-generated method stub return null; } @Override public Criteria getObservationCriteriaFor(String procedure, String observableProperty, Session session) throws CodedException { - // TODO Auto-generated method stub return null; } @Override public Criteria getObservationCriteriaFor(String procedure, String observableProperty, String featureOfInterest, Session session) throws CodedException { - // TODO Auto-generated method stub return null; } @Override public Collection getObservationIdentifiers(String procedureIdentifier, Session session) { - // TODO Auto-generated method stub return null; } @Override public List getSamplingGeometries(String feature, Session session) throws OwsExceptionReport { - // TODO Auto-generated method stub return null; } @Override public Long getSamplingGeometriesCount(String feature, Session session) throws OwsExceptionReport { - // TODO Auto-generated method stub return null; } @Override public Envelope getBboxFromSamplingGeometries(String feature, Session session) throws OwsExceptionReport { - // TODO Auto-generated method stub return null; } @Override public Criteria getTemoralReferencedObservationCriteriaFor(OmObservation observation, DatasetEntity observationConstellation, Session session) throws CodedException { - // TODO Auto-generated method stub return null; } @Override public ObservationFactory getObservationFactory() { - // TODO Auto-generated method stub return null; } @Override public String addProcedureAlias(Criteria criteria) { - // TODO Auto-generated method stub return null; } @Override protected Criteria addAdditionalObservationIdentification(Criteria c, OmObservation sosObservation) { - // TODO Auto-generated method stub return null; } diff --git a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetFeatureOfInterestDAO.java b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetFeatureOfInterestDAO.java index aa4c31ceab..10de254691 100644 --- a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetFeatureOfInterestDAO.java +++ b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetFeatureOfInterestDAO.java @@ -261,24 +261,17 @@ private FeatureCollection getFeatures(final GetFeatureOfInterestRequest request, /** * Adds the identifiers from featureIdentifiers to the - * foiIDs if the feature is an relatedFeature and a child is - * already contained in foiIDs + * foiIDs if the feature is an relatedFeature * * @param foiIDs * Feature identifiers - * @param featureIdentifiers + * @param requestedfeatures * Feature identifiers to add */ - private void addRequestedRelatedFeatures(final Set foiIDs, final List featureIdentifiers) { - requestedFeatures: for (final String requestedFeature : featureIdentifiers) { + private void addRequestedRelatedFeatures(final Set foiIDs, final List requestedfeatures) { + for (final String requestedFeature : requestedfeatures) { if (isRelatedFeature(requestedFeature)) { - final Set childFeatures = getCache().getChildFeatures(requestedFeature, true, false); - for (final String featureWithObservation : foiIDs) { - if (childFeatures.contains(featureWithObservation)) { - foiIDs.add(requestedFeature); - continue requestedFeatures; - } - } + foiIDs.addAll(getCache().getChildFeatures(requestedFeature, true, false)); } } } diff --git a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetObservationDAO.java b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetObservationDAO.java index 7b188c9a87..ffc9635293 100644 --- a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetObservationDAO.java +++ b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/GetObservationDAO.java @@ -256,9 +256,6 @@ public boolean isSupported() { protected ObservationStream queryObservation(final GetObservationRequest request, LegacyObservationDAO observationDAO, final Session session) throws OwsExceptionReport, ConverterException { - if (request.isSetResultFilter()) { - throw new NotYetSupportedException("result filtering"); - } final long start = System.currentTimeMillis(); // get valid featureOfInterest identifier @@ -341,10 +338,6 @@ else if (CollectionHelper.isNotEmpty(sosIndeterminateTimeFilters)) { protected ObservationStream querySeriesObservation(GetObservationRequest request, AbstractSeriesObservationDAO observationDAO, Session session) throws OwsExceptionReport, ConverterException { - if (request.isSetResultFilter()) { - throw new NotYetSupportedException("result filtering"); - } - final long start = System.currentTimeMillis(); // get valid featureOfInterest identifier final Set features = getFeatures(request, session); diff --git a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertObservationDAO.java b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertObservationDAO.java index f729f7fed3..fdd08fb6dd 100644 --- a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertObservationDAO.java +++ b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertObservationDAO.java @@ -197,9 +197,7 @@ private void insertObservation(OmObservation sosObservation, checkSpatialFilteringProfile(sosObservation); OmObservationConstellation sosObsConst = sosObservation.getObservationConstellation(); - Set offerings = getParentProcedureOfferings(sosObsConst); - sosObsConst.setOfferings(offerings); - cache.addOfferings(offerings); + cache.addOfferings(sosObsConst.getOfferings()); Set hObservationConstellations = new HashSet<>(); AbstractFeatureOfInterest hFeature = null; @@ -344,45 +342,6 @@ private AbstractFeatureOfInterest getFeature(AbstractFeature abstractFeature, } return hFeature; } - - /** - * Get parent offerings for requested procedure and observable property - * - * @param sosObsConst - * Requested observation constellation - * @return Requested offering and valid parent procedure offerings. - */ - private Set getParentProcedureOfferings(OmObservationConstellation sosObsConst) { - Set offerings = Sets.newHashSet(sosObsConst.getOfferings()); - // getFeature parent procedures - Set parentProcedures = getCache().getParentProcedures(sosObsConst.getProcedure().getIdentifier(), true, false); - if (CollectionHelper.isNotEmpty(parentProcedures)) { - for (String parentProcedure : parentProcedures) { - // getFeature offerings for parent procdure - Set offeringsForParentProcedure = getCache().getOfferingsForProcedure(parentProcedure); - if (CollectionHelper.isNotEmpty(offeringsForParentProcedure)) { - for (String offering : offeringsForParentProcedure) { - /* - * getFeature observable properties for offering and checkConstellation if - * observable property is contained in request and if - * parent procedure offering is contained in procedure - * offerings. If true, add offering to set. - */ - Set observablePropertiesForOffering = - getCache().getObservablePropertiesForOffering(offering); - Set offeringsForProcedure = - getCache().getOfferingsForProcedure(sosObsConst.getProcedure().getIdentifier()); - if (CollectionHelper.isNotEmpty(observablePropertiesForOffering) - && observablePropertiesForOffering.contains(sosObsConst.getObservableProperty() - .getIdentifier()) && offeringsForProcedure.contains(offering)) { - offerings.add(offering); - } - } - } - } - } - return offerings; - } @Override public boolean isSupported() { diff --git a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertSensorDAO.java b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertSensorDAO.java index 568ee7892c..ca0cb5798e 100644 --- a/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertSensorDAO.java +++ b/hibernate/dao/src/main/java/org/n52/sos/ds/hibernate/InsertSensorDAO.java @@ -29,11 +29,10 @@ package org.n52.sos.ds.hibernate; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Set; -import java.util.Map.Entry; - +import java.util.Map; import javax.inject.Inject; import org.hibernate.HibernateException; @@ -57,6 +56,7 @@ import org.n52.shetland.ogc.swes.SwesFeatureRelationship; import org.n52.sos.ds.AbstractInsertSensorHandler; 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.ObservablePropertyDAO; import org.n52.sos.ds.hibernate.dao.ObservationConstellationDAO; @@ -67,8 +67,14 @@ import org.n52.sos.ds.hibernate.dao.RelatedFeatureDAO; import org.n52.sos.ds.hibernate.dao.RelatedFeatureRoleDAO; import org.n52.sos.ds.hibernate.dao.ValidProcedureTimeDAO; +import org.n52.sos.ds.hibernate.dao.observation.ObservationContext; +import org.n52.sos.ds.hibernate.dao.observation.ObservationPersister; +import org.n52.sos.ds.hibernate.dao.observation.series.SeriesDAO; +import org.n52.sos.ds.hibernate.dao.observation.series.SeriesObservationDAO; +import org.n52.sos.ds.hibernate.entities.Codespace; import org.n52.sos.ds.hibernate.entities.FeatureOfInterestType; import org.n52.sos.ds.hibernate.entities.ObservableProperty; +import org.n52.sos.ds.hibernate.entities.ObservationConstellation; import org.n52.sos.ds.hibernate.entities.ObservationType; import org.n52.sos.ds.hibernate.entities.Offering; import org.n52.sos.ds.hibernate.entities.Procedure; @@ -76,11 +82,14 @@ import org.n52.sos.ds.hibernate.entities.RelatedFeature; import org.n52.sos.ds.hibernate.entities.RelatedFeatureRole; import org.n52.sos.ds.hibernate.entities.ResultTemplate; +import org.n52.sos.ds.hibernate.entities.Unit; import org.n52.sos.ds.hibernate.entities.ValidProcedureTime; +import org.n52.sos.ds.hibernate.entities.feature.AbstractFeatureOfInterest; +import org.n52.sos.ds.hibernate.entities.observation.series.Series; import org.n52.sos.ds.hibernate.util.HibernateHelper; +import com.google.common.base.Predicate; import com.google.common.base.Strings; -import com.google.common.collect.Sets; /** * Implementation of the abstract class AbstractInsertSensorHandler @@ -93,6 +102,12 @@ public class InsertSensorDAO extends AbstractInsertSensorHandler { private HibernateSessionHolder sessionHolder; private DaoFactory daoFactory; + public static final Predicate REFERENCE_VALUES_PREDICATE = + SmlCapabilitiesPredicates.name(SensorMLConstants.ELEMENT_NAME_REFERENCE_VALUES); + + /** + * constructor + */ public InsertSensorDAO() { super(SosConstants.SOS); } @@ -128,56 +143,134 @@ public synchronized InsertSensorResponse insertSensor(final InsertSensorRequest if (procedureDescriptionFormat != null) { final Procedure hProcedure = new ProcedureDAO(daoFactory).getOrInsertProcedure(assignedProcedureID, procedureDescriptionFormat, - request.getProcedureDescription(), request.isType(),session); + request.getProcedureDescription(), request.isType(), session); // TODO: set correct validTime, new ValidProcedureTimeDAO(daoFactory).insertValidProcedureTime( hProcedure, procedureDescriptionFormat, getSensorDescriptionFromProcedureDescription(request.getProcedureDescription()), new DateTime(DateTimeZone.UTC), session); if (!request.isType()) { - final List observationTypes = - new ObservationTypeDAO().getOrInsertObservationTypes(request.getMetadata().getObservationTypes(), + final List observationTypes = new ObservationTypeDAO() + .getOrInsertObservationTypes(request.getMetadata().getObservationTypes(), session); + final List featureOfInterestTypes = new FeatureOfInterestTypeDAO() + .getOrInsertFeatureOfInterestTypes(request.getMetadata().getFeatureOfInterestTypes(), session); - final List featureOfInterestTypes = - new FeatureOfInterestTypeDAO().getOrInsertFeatureOfInterestTypes(request.getMetadata() - .getFeatureOfInterestTypes(), session); if (observationTypes != null && featureOfInterestTypes != null) { final List hObservableProperties = - getOrInsertNewObservableProperties(request.getObservableProperty(), request.getProcedureDescription(), session); - final ObservationConstellationDAO observationConstellationDAO = daoFactory.getObservationConstellationDAO(); - final OfferingDAO offeringDAO = daoFactory.getOfferingDAO(); + getOrInsertNewObservableProperties(request.getObservableProperty(), + request.getProcedureDescription(), session); + final ObservationConstellationDAO observationConstellationDAO = + new ObservationConstellationDAO(); + final OfferingDAO offeringDAO = new OfferingDAO(); for (final SosOffering assignedOffering : request.getAssignedOfferings()) { final List hRelatedFeatures = new LinkedList<>(); if (request.getRelatedFeatures() != null && !request.getRelatedFeatures().isEmpty()) { final RelatedFeatureDAO relatedFeatureDAO = new RelatedFeatureDAO(daoFactory); final RelatedFeatureRoleDAO relatedFeatureRoleDAO = new RelatedFeatureRoleDAO(); for (final SwesFeatureRelationship relatedFeature : request.getRelatedFeatures()) { - final List relatedFeatureRoles = - relatedFeatureRoleDAO.getOrInsertRelatedFeatureRole(relatedFeature.getRole(), - session); + final List relatedFeatureRoles = relatedFeatureRoleDAO + .getOrInsertRelatedFeatureRole(relatedFeature.getRole(), session); hRelatedFeatures.addAll(relatedFeatureDAO.getOrInsertRelatedFeature( relatedFeature.getFeature(), relatedFeatureRoles, session)); } } final Offering hOffering = - offeringDAO.getAndUpdateOrInsertNewOffering(assignedOffering, hRelatedFeatures, observationTypes, - featureOfInterestTypes, session); + offeringDAO.getAndUpdateOrInsertNewOffering(assignedOffering, hRelatedFeatures, + observationTypes, featureOfInterestTypes, session); for (final ObservableProperty hObservableProperty : hObservableProperties) { - observationConstellationDAO.checkOrInsertObservationConstellation(hProcedure, - hObservableProperty, hOffering, assignedOffering.isParentOffering(), session); + ObservationConstellation hObservationConstellation = observationConstellationDAO + .checkOrInsertObservationConstellation(hProcedure, hObservableProperty, + hOffering, assignedOffering.isParentOffering(), session); + if (checkPreconditionsOfStaticReferenceValues(request)) { + AbstractFeature sosFeatureOfInterest = request.getProcedureDescription().getFeaturesOfInterestMap().entrySet().iterator().next().getValue(); + AbstractFeatureOfInterest hFeature = new FeatureOfInterestDAO().checkOrInsertFeatureOfInterest( + sosFeatureOfInterest, session); + for (SmlCapability referenceValue : ((AbstractSensorML) request.getProcedureDescription()).findCapabilities(REFERENCE_VALUES_PREDICATE).get().getCapabilities()) { + if (!(referenceValue.getAbstractDataComponent() instanceof SweQuantity)) { + throw new NoApplicableCodeException().withMessage( + "ReferenceValue of Type '%s' is not supported -> Aborting InsertSensor Operation!", + referenceValue.getAbstractDataComponent().getDataComponentType()); + } + SweQuantity referenceValueValue = (SweQuantity) referenceValue.getAbstractDataComponent(); + String identifier = hProcedure.getIdentifier() + "_referencevalue"; + SosProcedureDescription procedureReferenceSeries = new SosProcedureDescriptionUnknowType(identifier, + procedureDescriptionFormat.getProcedureDescriptionFormat(), ""); + procedureReferenceSeries.setReference(true); + procedureReferenceSeries.setName(new CodeType(referenceValue.getName())); + Procedure hProcedureReferenceSeries = new ProcedureDAO().getOrInsertProcedure( + identifier, + procedureDescriptionFormat, + procedureReferenceSeries, + false, + session); + Offering hOfferingReferenceSeries = new OfferingDAO().getAndUpdateOrInsertNewOffering( + new SosOffering( + hOffering.getIdentifier() + "_referencevalue", + hOffering.getName() + "_referencevalue"), + hRelatedFeatures, + observationTypes, + featureOfInterestTypes, + session); + TimeInstant time = new TimeInstant(new DateTime(0)); + SingleObservationValue sosValue = new SingleObservationValue<>(new QuantityValue(referenceValueValue.getValue(), referenceValueValue.getUom())); + + OmObservation sosObservation = new OmObservation(); + sosValue.setPhenomenonTime(time); + sosObservation.setResultTime(time); + sosObservation.setValue(sosValue); + sosObservation.setObservationConstellation(new OmObservationConstellation(procedureReferenceSeries, + new OmObservableProperty(hObservableProperty.getIdentifier()), + sosFeatureOfInterest)); + + ObservationConstellation hObservationConstellationReferenceSeries = new ObservationConstellation(); + hObservationConstellationReferenceSeries.setObservableProperty(hObservableProperty); + hObservationConstellationReferenceSeries.setOffering(hOfferingReferenceSeries); + hObservationConstellationReferenceSeries.setProcedure(hProcedureReferenceSeries); + Map codespaceCache = CollectionHelper.synchronizedMap(); + Map unitCache = CollectionHelper.synchronizedMap(); + ObservationPersister persister = new ObservationPersister( + new SeriesObservationDAO(), + sosObservation, + hObservationConstellationReferenceSeries, + hFeature, + codespaceCache, + unitCache, + Collections.singleton(hOfferingReferenceSeries), + session + ); + sosValue.getValue().accept(persister); + SeriesDAO seriesDAO = new SeriesDAO(); + Series hReferenceSeries = seriesDAO.getSeries(hProcedureReferenceSeries.getIdentifier(), + hObservableProperty.getIdentifier(), + hOfferingReferenceSeries.getIdentifier(), + Collections.singleton(hFeature.getIdentifier()), + session).get(0); + hReferenceSeries.setPublished(false); + session.update(hReferenceSeries); + ObservationContext ctx = new ObservationContext(); + ctx.setObservableProperty(hObservableProperty); + ctx.setFeatureOfInterest(hFeature); + ctx.setProcedure(hProcedure); + ctx.setOffering(hOffering); + ctx.setPublish(false); + Series hSeries = seriesDAO.getOrInsertSeries(ctx, session); + hSeries.setReferenceValues(Collections.singletonList(hReferenceSeries)); + session.update(hSeries); + } + } } } // TODO: parent and child procedures -// response.setAssignedProcedure(assignedProcedureID); -// response.setAssignedOffering(firstAssignedOffering.getIdentifier()); } else { - throw new NoApplicableCodeException().withMessage("Error while inserting InsertSensor into database!"); + throw new NoApplicableCodeException() + .withMessage("Error while inserting InsertSensor into database!"); } } response.setAssignedProcedure(assignedProcedureID); response.setAssignedOffering(firstAssignedOffering.getIdentifier()); } else { - throw new InvalidParameterValueException(Sos2Constants.InsertSensorParams.procedureDescriptionFormat, request.getProcedureDescriptionFormat()); + throw new InvalidParameterValueException(Sos2Constants.InsertSensorParams.procedureDescriptionFormat, + request.getProcedureDescriptionFormat()); } session.flush(); transaction.commit(); @@ -193,9 +286,13 @@ public synchronized InsertSensorResponse insertSensor(final InsertSensorRequest return response; } - @Override - public boolean isSupported() { - return HibernateHelper.isEntitySupported(ValidProcedureTime.class); + private boolean checkPreconditionsOfStaticReferenceValues(final InsertSensorRequest request) { + return request.getProcedureDescription() instanceof AbstractProcessV20 && + ((AbstractProcessV20) request.getProcedureDescription()).isSetSmlFeatureOfInterest() && + ((AbstractSensorML) request.getProcedureDescription()).findCapabilities(REFERENCE_VALUES_PREDICATE) + .isPresent() && + !request.getProcedureDescription().getFeaturesOfInterestMap().isEmpty() && + request.getProcedureDescription().getFeaturesOfInterestMap().size() == 1; } /** @@ -204,7 +301,7 @@ public boolean isSupported() { * * @param obsProps * observableProperty identifiers - * @param sosProcedureDescription + * @param sosProcedureDescription * @param session * Hibernate Session * @return ObservableProperty entities @@ -261,7 +358,7 @@ private void checkForTransactionalEntity() throws CodedException { throw new NoApplicableCodeException().withMessage("The transactional database profile is not activated!"); } } - + @Override public CapabilitiesExtension getExtension() { final SosInsertionCapabilities insertionCapabilities = new SosInsertionCapabilities(); @@ -286,7 +383,7 @@ public boolean hasRelatedOperation() { public String getRelatedOperation() { return getOperationName(); } - + @Override public boolean isSupported() { return HibernateHelper.isEntitySupported(ValidProcedureTime.class); diff --git a/hibernate/dao/src/test/java/org/n52/sos/ds/hibernate/InsertDAOTest.java b/hibernate/dao/src/test/java/org/n52/sos/ds/hibernate/InsertDAOTest.java index d56077ab2a..3ef7a8a953 100644 --- a/hibernate/dao/src/test/java/org/n52/sos/ds/hibernate/InsertDAOTest.java +++ b/hibernate/dao/src/test/java/org/n52/sos/ds/hibernate/InsertDAOTest.java @@ -642,7 +642,7 @@ public void testInsertObservationWithSamplingGeometry() throws OwsExceptionRepor InsertObservationResponse resp = insertObservationDAO.insertObservation(req); this.serviceEventBus.submit(new ObservationInsertion(req, resp)); assertInsertionAftermathBeforeAndAfterCacheReload(); - checkSamplingGeometry(OFFERING1, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_SP); + checkSamplingGeometry(OFFERING3, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_SP); } private NamedValue createSamplingGeometry() { @@ -694,7 +694,7 @@ public void testInsertObservationWithOmParameter() throws OwsExceptionReport, Co InsertObservationResponse resp = insertObservationDAO.insertObservation(req); this.serviceEventBus.submit(new ObservationInsertion(req, resp)); assertInsertionAftermathBeforeAndAfterCacheReload(); - checkOmParameter(OFFERING1, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_PARAM); + checkOmParameter(OFFERING3, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_PARAM); } private void addParameter(OmObservation obs) { @@ -759,7 +759,7 @@ public void testInsertObservationWithHeightParameter() throws OwsExceptionReport InsertObservationResponse resp = insertObservationDAO.insertObservation(req); this.serviceEventBus.submit(new ObservationInsertion(req, resp)); assertInsertionAftermathBeforeAndAfterCacheReload(); - checkHeightParameter(OFFERING1, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_HEIGHT); + checkHeightParameter(OFFERING3, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_HEIGHT); } private void checkHeightParameter(String offering, String procedure, String obsprop, String feature, DateTime time) throws OwsExceptionReport { @@ -801,7 +801,7 @@ public void testInsertObservationWithDepthParameter() throws OwsExceptionReport, InsertObservationResponse resp = insertObservationDAO.insertObservation(req); this.serviceEventBus.submit(new ObservationInsertion(req, resp)); assertInsertionAftermathBeforeAndAfterCacheReload(); - checkDepthParameter(OFFERING1, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_DEPTH); + checkDepthParameter(OFFERING3, PROCEDURE3, OBSPROP3, FEATURE3, OBS_TIME_DEPTH); } private void checkDepthParameter(String offering, String procedure, String obsprop, String feature, DateTime time) throws OwsExceptionReport { diff --git a/hibernate/datasource/sqlserver/src/main/java/org/n52/sos/ds/datasource/SqlServerDatasource.java b/hibernate/datasource/sqlserver/src/main/java/org/n52/sos/ds/datasource/SqlServerDatasource.java index 1b2b7626e4..ca845c7c48 100644 --- a/hibernate/datasource/sqlserver/src/main/java/org/n52/sos/ds/datasource/SqlServerDatasource.java +++ b/hibernate/datasource/sqlserver/src/main/java/org/n52/sos/ds/datasource/SqlServerDatasource.java @@ -50,6 +50,8 @@ public class SqlServerDatasource extends AbstractSqlServerDatasource { private static final String TN_FEATURE_OF_INTEREST = "featureOfInterest"; private static final String TN_OBSERVATION = "observation"; + + private static final String TN_SERIES = "series"; private static final String TN_SERIES = "series"; @@ -78,7 +80,7 @@ public boolean isPostCreateSchema() { @Override public void executePostCreateSchema(Map databaseSettings) { List statements = new ArrayList<>(); - for (TableColumn tableColumn : getTableColumns()) { + for (TableColumn tableColumn : getTableColumns(databaseSettings)) { statements.add(getGetAndDropConstraint(tableColumn.getTable(), tableColumn.getColumn(), databaseSettings)); statements .add(getCreateUniqueConstraint(databaseSettings, tableColumn.getTable(), tableColumn.getColumn())); @@ -95,7 +97,7 @@ private String getGetAndDropConstraint(String table, String column, Map getTableColumns() { + private Set getTableColumns(Map s) { Set tableColumns = new HashSet<>(); tableColumns.add(new TableColumn(TN_FEATURE_OF_INTEREST, CN_IDENTIFIER)); tableColumns.add(new TableColumn(TN_FEATURE_OF_INTEREST, CN_URL)); diff --git a/hibernate/feature/src/main/java/org/n52/sos/ds/hibernate/HibernateFeatureQueryHandler.java b/hibernate/feature/src/main/java/org/n52/sos/ds/hibernate/HibernateFeatureQueryHandler.java index 7cea0fe91e..8842790e26 100644 --- a/hibernate/feature/src/main/java/org/n52/sos/ds/hibernate/HibernateFeatureQueryHandler.java +++ b/hibernate/feature/src/main/java/org/n52/sos/ds/hibernate/HibernateFeatureQueryHandler.java @@ -125,6 +125,19 @@ public void setDaoFactory(DaoFactory daoFactory) { public void setI18NDAORepository(I18NDAORepository i18NDAORepository) { this.i18NDAORepository = i18NDAORepository; } + @Override + public AbstractFeature getFeatureByID(FeatureQueryHandlerQueryObject queryObject) throws OwsExceptionReport { + final Session session = HibernateSessionHolder.getSession(queryObject.getConnection()); + try { + if (queryObject.isSetFeature() && queryObject.getFeature() instanceof AbstractFeatureOfInterest) { + return createSosAbstractFeature((AbstractFeatureOfInterest) queryObject.getFeature(), queryObject); + } + AbstractFeatureOfInterest feature = getFeatureDAO().getFeature(queryObject.getFeatureIdentifier(), session); + return createSosAbstractFeature(feature, queryObject); + } catch (final HibernateException he) { + throw new NoApplicableCodeException().causedBy(he).withMessage( + "An error occurred while querying feature data for a featureOfInterest identifier!"); + } @Inject public void setGeometryHandler(GeometryHandler geometryHandler) { diff --git a/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesMetadata.hbm.xml b/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesMetadata.hbm.xml index d946db083c..f9b38ccdcd 100644 --- a/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesMetadata.hbm.xml +++ b/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesMetadata.hbm.xml @@ -13,7 +13,7 @@ metadataId_seq - + Foreign Key (FK) to the related series. Contains "series".seriesId diff --git a/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesParameter.hbm.xml b/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesParameter.hbm.xml index 9f7277f099..ded1986ed2 100644 --- a/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesParameter.hbm.xml +++ b/hibernate/mappings/src/main/resources/mapping/metadata/series/SeriesParameter.hbm.xml @@ -28,7 +28,7 @@ check="value in ('T','F')"> Value table for boolean parameter - + Foreign Key (FK) to the related parameter from the series parameter table. Contains seriesparameter.parameterid @@ -44,7 +44,7 @@ table="categoryseriesparamvalue"> Value table for category parameter - + Foreign Key (FK) to the related parameter from the series parameter table. Contains seriesparameter.parameterid @@ -67,7 +67,7 @@ table="countseriesparamvalue"> Value table for count parameter - + Foreign Key (FK) to the related parameter from the series parameter table. Contains seriesparameter.parameterid @@ -83,7 +83,7 @@ table="numericseriesparamvalue"> Value table for numeric/Measurment parameter - + Foreign Key (FK) to the related parameter from the series parameter table. Contains seriesparameter.parameterid @@ -107,7 +107,7 @@ table="textseriesparamvalue"> Value table for text parameter - + Foreign Key (FK) to the related parameter from the series parameter table. Contains seriesparameter.parameterid @@ -123,7 +123,7 @@ table="xmlseriesparamvalue"> Value table for XML parameter - + Foreign Key (FK) to the related parameter from the series parameter table. Contains seriesparameter.parameterid diff --git a/hibernate/mappings/src/main/resources/mapping/parameter/observation/ParameterValues.hbm.xml b/hibernate/mappings/src/main/resources/mapping/parameter/observation/ParameterValues.hbm.xml index 22d4e48680..0576988004 100644 --- a/hibernate/mappings/src/main/resources/mapping/parameter/observation/ParameterValues.hbm.xml +++ b/hibernate/mappings/src/main/resources/mapping/parameter/observation/ParameterValues.hbm.xml @@ -9,7 +9,7 @@ table="booleanparametervalue" check="value in ('T','F')"> Value table for boolean parameter - + Foreign Key (FK) to the related parameter from the parameter table. Contains "parameter".parameterid @@ -27,7 +27,7 @@ table="categoryparametervalue"> Value table for category parameter - + Foreign Key (FK) to the related parameter from the parameter table. Contains "parameter".parameterid @@ -52,7 +52,7 @@ table="countparametervalue"> Value table for count parameter - + Foreign Key (FK) to the related parameter from the parameter table. Contains "parameter".parameterid @@ -70,7 +70,7 @@ table="numericparametervalue"> Value table for numeric/Measurment parameter - + Foreign Key (FK) to the related parameter from the parameter table. Contains "parameter".parameterid @@ -95,7 +95,7 @@ table="textparametervalue"> Value table for text parameter - + Foreign Key (FK) to the related parameter from the parameter table. Contains "parameter".parameterid @@ -113,7 +113,7 @@ table="xmlparametervalue"> Value table for XML parameter - + Foreign Key (FK) to the related parameter from the parameter table. Contains "parameter".parameterid diff --git a/hibernate/mappings/src/main/resources/mapping/series/base/RelatedObservations.hbm.xml b/hibernate/mappings/src/main/resources/mapping/series/base/RelatedObservations.hbm.xml index a8081357b0..871948540b 100644 --- a/hibernate/mappings/src/main/resources/mapping/series/base/RelatedObservations.hbm.xml +++ b/hibernate/mappings/src/main/resources/mapping/series/base/RelatedObservations.hbm.xml @@ -15,13 +15,13 @@ + class="org.n52.sos.ds.hibernate.entities.observation.series.AbstractSeriesObservation" index="relobsobsididx"> Foreign Key (FK) to the observation. Contains "observation".observationId + class="org.n52.sos.ds.hibernate.entities.observation.series.AbstractSeriesObservation" index="relobsrelobsididx"> Relation/foreign key to the associated observation table. Contains "observation".observationId diff --git a/hibernate/session-factory/src/main/java/org/n52/sos/ds/hibernate/util/HibernateHelper.java b/hibernate/session-factory/src/main/java/org/n52/sos/ds/hibernate/util/HibernateHelper.java index 8e800c7141..920deafc0c 100644 --- a/hibernate/session-factory/src/main/java/org/n52/sos/ds/hibernate/util/HibernateHelper.java +++ b/hibernate/session-factory/src/main/java/org/n52/sos/ds/hibernate/util/HibernateHelper.java @@ -63,6 +63,7 @@ * */ public final class HibernateHelper { + /** * Private constructor */ @@ -167,8 +168,8 @@ public static List> getValidSizedLists(Collection queryIds) { int startIndex = 0; int endIndex = HibernateConstants.LIMIT_EXPRESSION_DEPTH - 1; while (startIndex < queryIdsList.size() - 1) { - if (endIndex > (queryIdsList.size())) { - endIndex = (queryIdsList.size()); + if (endIndex > queryIdsList.size()) { + endIndex = queryIdsList.size(); } lists.add(queryIdsList.subList(startIndex, endIndex)); startIndex = endIndex; diff --git a/operations/transactional-v20/src/main/java/org/n52/sos/request/operator/SosInsertSensorOperatorV20.java b/operations/transactional-v20/src/main/java/org/n52/sos/request/operator/SosInsertSensorOperatorV20.java index e0a557e944..fea17e5c1e 100644 --- a/operations/transactional-v20/src/main/java/org/n52/sos/request/operator/SosInsertSensorOperatorV20.java +++ b/operations/transactional-v20/src/main/java/org/n52/sos/request/operator/SosInsertSensorOperatorV20.java @@ -407,7 +407,7 @@ private boolean checkOfferingsForOffering(Set sosOfferings, String private void checkProcedureAndOfferingCombination(InsertSensorRequest request) throws OwsExceptionReport { for (SosOffering offering : request.getAssignedOfferings()) { - if (!offering.isParentOffering() && getCache().getPublishedFeatureOfInterest().contains(offering.getIdentifier())) { + if (!offering.isParentOffering() && getCache().getPublishedOfferings().contains(offering.getIdentifier())) { throw new InvalidParameterValueException().at(Sos2Constants.InsertSensorParams.offeringIdentifier) .withMessage( "The offering with the identifier '%s' still exists in this service and it is not allowed to insert more than one procedure to an offering!", diff --git a/pom.xml b/pom.xml index 673785ad46..6ce2ba8fcb 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 @@ -66,7 +65,6 @@ spring statistics webapp - @@ -1706,14 +1704,19 @@ + install org.apache.maven.plugins maven-release-plugin + 2.5.3 - clean install + clean + true + v@{project.version} + oracle @@ -1977,12 +1980,6 @@ maven-surefire-plugin 2.20 - - maven-release-plugin - - scm:svn:https://svn.52north.org/svn/swe/main/SOS/Service/branches/52n-sos-400-refactored - - org.apache.maven.plugins maven-assembly-plugin @@ -2003,6 +2000,12 @@ + + https://github.com/52North/SOS + scm:git:https://github.com/52North/SOS.git + scm:git:https://github.com/52North/SOS.git + HEAD + n52-releases @@ -2020,7 +2023,6 @@ true - - - org.n52.series-api - io - ${rest.api.version} - runtime - - - org.geotools - gt-main - - - org.geotools - gt-epsg-hsql - - - org.geotools - gt-opengis - - - org.geotools - gt-metadata - - - c3p0 - c3p0 - - - com.mchange - c3p0 - - - - - org.n52.series-api - rest - ${rest.api.version} - runtime - - - org.geotools - gt-main - - - org.geotools - gt-epsg-hsql - - - org.geotools - gt-opengis - - - org.geotools - gt-metadata - - - c3p0 - c3p0 - - - com.mchange - c3p0 - - - - - org.n52.series-api - spi - ${rest.api.version} - runtime - - - org.geotools - gt-main - - - org.geotools - gt-epsg-hsql - - - org.geotools - gt-opengis - - - org.geotools - gt-metadata - - - c3p0 - c3p0 - - - com.mchange - c3p0 - - - - - org.n52.series-api.db - webapp - ${series.db.version} - war - - - org.n52.series-api.db - dao - ${series.db.version} - runtime - - - org.geotools - gt-main - - - org.geotools - gt-epsg-hsql - - - org.geotools - gt-opengis - - - org.geotools - gt-metadata - - - - - org.n52.series-api.db - mappings - ${series.db.version} - provided - - - org.geotools - gt-main - - - org.geotools - gt-epsg-hsql - - - org.geotools - gt-opengis - - - org.geotools - gt-metadata - - - - - org.n52.series-api.db - sos-integration - ${series.db.version} - runtime - - - org.geotools - gt-main - - - org.geotools - gt-epsg-hsql - - - org.geotools - gt-opengis - - - org.geotools - gt-metadata - - - - - org.geotools - gt-main - runtime - - - - - org.springframework - spring-oxm - runtime - - - org.springframework - spring-aop - runtime - - - org.springframework - spring-aspects - runtime - - - - org.aspectj - aspectjtools - runtime - - - - - ${project.groupId} - webapp - war - runtime - - - - - assembly - - - - org.apache.maven.plugins - maven-assembly-plugin - - - install - - single - - - 52n-sensorweb-sos-bundle-${project.version} - false - - - - - - - - - ${project.groupId} - hibernate-datasource-oracle - runtime - - - ${project.groupId} - hibernate-datasource-sqlserver - runtime - - - - - diff --git a/webapp-bundle/src/main/alternative/FeatureResource.hbm.xml b/webapp-bundle/src/main/alternative/FeatureResource.hbm.xml deleted file mode 100644 index 828067ef70..0000000000 --- a/webapp-bundle/src/main/alternative/FeatureResource.hbm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - diff --git a/webapp-bundle/src/main/alternative/README.md b/webapp-bundle/src/main/alternative/README.md deleted file mode 100644 index b1510d29c0..0000000000 --- a/webapp-bundle/src/main/alternative/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# E-Reporting Profile -Expects an extra `station` table instead of `featureofinterest` table only. - -Note that this profile can't be chosen with `series` profile in parallel. diff --git a/webapp-bundle/src/main/alternative/TimeseriesResource.hbm.xml b/webapp-bundle/src/main/alternative/TimeseriesResource.hbm.xml deleted file mode 100644 index 715b1f0410..0000000000 --- a/webapp-bundle/src/main/alternative/TimeseriesResource.hbm.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webapp-bundle/src/main/metadata/MetadataResource.hbm.xml b/webapp-bundle/src/main/metadata/MetadataResource.hbm.xml deleted file mode 100644 index e6b589099f..0000000000 --- a/webapp-bundle/src/main/metadata/MetadataResource.hbm.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webapp-bundle/src/main/metadata/README.md b/webapp-bundle/src/main/metadata/README.md deleted file mode 100644 index 8ac915233b..0000000000 --- a/webapp-bundle/src/main/metadata/README.md +++ /dev/null @@ -1,42 +0,0 @@ -## Adding extra metadata fields - -Adding extra metadata to each series can be done by creating an extra metadata table. -Apply `src/extension/metadata/create_metadata_table.sql` and add some metadata to it. -Add `/hbm/sos/metadata` to the `seriesSessionFactory` bean in -`WEB-INF/spring/series-database-config.xml` like -``` - - - classpath:hbm/sos/v42/*.hbm.xml - classpath:hbm/sos/v42/series/*.hbm.xml - classpath:hbm/sos/metadata/*.hbm.xml - - -``` - -Now configure the metadata extension to the Web interface so the data can be accessed. -Open the `api_v1_mvc.xml` add the bean -`org.n52.io.extension.DatabaseMetadataExtension` to the `metadataExtensions` -property of a parameterController. - -For example -``` - - - - - - - - - - - - - -``` - -After restart you should be able to review the extra metadata available in the -`extras` property array of a timeseries. To access them just call -`api/v1/timeseries/:id/extras` and optionally filter by adding query parameter -`fields` (takes a comma-separated list of metadata names). diff --git a/webapp-bundle/src/main/metadata/create_metadata_table.sql b/webapp-bundle/src/main/metadata/create_metadata_table.sql deleted file mode 100644 index 193551dd26..0000000000 --- a/webapp-bundle/src/main/metadata/create_metadata_table.sql +++ /dev/null @@ -1,44 +0,0 @@ --- --- Copyright (C) 2012-2018 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. --- - -CREATE TABLE series_metadata -( - metadata_id bigint NOT NULL, - series_id bigint NOT NULL, - field_name character varying(255) NOT NULL, - field_type character varying(10) DEFAULT 'string', - field_value text, - last_update timestamp, - CONSTRAINT seriespk PRIMARY KEY (metadata_id), - CONSTRAINT seriesfk FOREIGN KEY (series_id) - REFERENCES series (seriesid) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION, - CONSTRAINT metadataidentity UNIQUE (series_id, field_name), - CONSTRAINT chk_type CHECK (field_type IN ('string','boolean','integer','double','text','json')) -) \ No newline at end of file diff --git a/webapp-bundle/src/main/metadata/insert_example_metadata.sql b/webapp-bundle/src/main/metadata/insert_example_metadata.sql deleted file mode 100644 index 496faedc34..0000000000 --- a/webapp-bundle/src/main/metadata/insert_example_metadata.sql +++ /dev/null @@ -1,34 +0,0 @@ --- --- Copyright (C) 2012-2018 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. --- - -INSERT INTO series_metadata VALUES (1, 1, 'integrationPeriod', 'string', 'PT1M') ; -INSERT INTO series_metadata VALUES (2, 1, 'booleanMetadataField', 'boolean','false'); -INSERT INTO series_metadata VALUES (3, 1, 'numericMetadataField', 'double', '42.17'); -INSERT INTO series_metadata VALUES (4, 1, 'timeseries_copyright', 'string', '(C) 2015'); -INSERT INTO series_metadata VALUES (5, 1, 'structured_metadata_example', 'json', '{"key":"value","object":{"key1":"string","key2":42}}'); \ No newline at end of file diff --git a/webapp-bundle/src/main/resources/meta.properties b/webapp-bundle/src/main/resources/meta.properties deleted file mode 100644 index dd32e7b216..0000000000 --- a/webapp-bundle/src/main/resources/meta.properties +++ /dev/null @@ -1,5 +0,0 @@ -VERSION=${version} -GIT_BRANCH=${git.branch} -GIT_COMMIT=${git.commit.id} -BUILD_DATE=${git.build.time} -INSTALL_DATE=${git.build.time} diff --git a/webapp-bundle/src/main/webapp/WEB-INF/spring/dispatcher-servlet.xml b/webapp-bundle/src/main/webapp/WEB-INF/spring/dispatcher-servlet.xml deleted file mode 100644 index 3153d0a969..0000000000 --- a/webapp-bundle/src/main/webapp/WEB-INF/spring/dispatcher-servlet.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webapp-bundle/src/main/webapp/WEB-INF/spring/series-database-config.xml b/webapp-bundle/src/main/webapp/WEB-INF/spring/series-database-config.xml deleted file mode 100644 index 2c28be9c26..0000000000 --- a/webapp-bundle/src/main/webapp/WEB-INF/spring/series-database-config.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - diff --git a/webapp-bundle/src/main/webapp/WEB-INF/web.xml b/webapp-bundle/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 9314d7cdd6..0000000000 --- a/webapp-bundle/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - ${project.parent.name}, Git-Branch '${git.branch}' with - state '${git.commit.id}' @ ${git.commit.time} - This is an OGC SOS with Sensor Web REST-API. - - - logDir - - ${conf.sos.logdir} - - - - contextConfigLocation - /WEB-INF/applicationContext.xml - - - - datasourceConfigLocation - /WEB-INF/datasource.properties - - - - se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor - - - - org.springframework.web.context.ContextLoaderListener - - - - org.n52.iceland.service.ServiceContextListener - - - - CORS - com.thetransactioncompany.cors.CORSFilter - - cors.allowOrigin - * - - - cors.allowGenericHttpRequests - true - - - cors.supportedMethods - GET, POST, HEAD, PUT, DELETE, OPTIONS - - - cors.supportedHeaders - * - - - - CORS - /* - - - encodingFilter - org.springframework.web.filter.CharacterEncodingFilter - - encoding - UTF-8 - - - forceEncoding - true - - - - encodingFilter - /* - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - springSecurityFilterChain - /* - - - - installFilter - org.n52.sos.web.install.InstallFilter - - - installFilter - /install/* - - - - dispatcher - org.springframework.web.servlet.DispatcherServlet - 1 - - contextConfigLocation - /WEB-INF/applicationContext.xml,/WEB-INF/dispatcher-servlet.xml - - - - rest-dispatcher - org.springframework.web.servlet.DispatcherServlet - -1 - - contextConfigLocation - /WEB-INF/spring/application-context.xml,/WEB-INF/spring/dispatcher-servlet.xml - - - - - - Admin - org.n52.iceland.service.admin.AdminService - - - - - Service - org.n52.iceland.service.Service - - - - - Admin - /admin - - - Service - /sos/* - - - Service - /service/* - - - dispatcher - / - - - rest-dispatcher - /api/* - - diff --git a/webapp-bundle/src/main/webapp/static/client/helgoland/settings.json b/webapp-bundle/src/main/webapp/static/client/helgoland/settings.json deleted file mode 100644 index 253dda5b56..0000000000 --- a/webapp-bundle/src/main/webapp/static/client/helgoland/settings.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "selectedLineWidth": 4, - "commonLineWidth": 1, - "undefinedUomString": "-", - "aggregateServices": true, - "saveStatus": true, - "restApiUrls": { - "http://localhost:8080/52n-sos-webapp/api/": "localhost" - }, - "defaultProvider": { - "serviceID": "1", - "apiUrl": "http://localhost:8080/52n-sos-webapp/api/" - }, - "chartOptions": { - "yaxis": { - "tickDecimals": 2 - } - }, - "supportedLanguages": [ - { - "code": "de", - "label": "Deutsch" - }, - { - "code": "en", - "label": "English" - } - ], - "selectColorFromList": true, - "colorList": [ - "#078D53", - "#00F3FF", - "#0043FF", - "#E22985", - "#8D00A9", - "#FF783D", - "#AD3500", - "#FFCB00", - "#927711", - "#53EA42" - ], - "refColorList": [ - "#668B7B", - "#A6D5D7", - "#7C90C8", - "#D48DB0", - "#84518E", - "#DA9B7F", - "#9D7D6F", - "#D7C57E", - "#BAA760", - "#A1BE9D" - ], - "baselayer": { - "osm": { - "name": "Open Street Map", - "type": "xyz", - "url": "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", - "layerOptions": { - "showOnSelector": true - } - }, - "cycle": { - "name": "OpenCycleMap", - "type": "xyz", - "url": "http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png", - "layerOptions": { - "subdomains": [ - "a", - "b", - "c" - ], - "attribution": "© OpenCycleMap contributors - © OpenStreetMap contributors", - "continuousWorld": true - } - } - }, - "overlays": { - "hillshade": { - "name": "Hillshade Europa", - "type": "wms", - "url": "http://129.206.228.72/cached/hillshade", - "visible": false, - "layerOptions": { - "layers": "europe_wms:hs_srtm_europa", - "format": "image/png", - "opacity": 0.25, - "attribution": "Hillshade layer by GIScience http://www.osm-wms.de" - }, - "group": "Raster" - } - }, - "showScale": true -} diff --git a/webapp-bundle/src/main/webapp/version-info.txt b/webapp-bundle/src/main/webapp/version-info.txt deleted file mode 100644 index bf0ba9fa77..0000000000 --- a/webapp-bundle/src/main/webapp/version-info.txt +++ /dev/null @@ -1,13 +0,0 @@ -General Infos: -============== -project = 52North SOS Reference Implementation (${artifactId}) -version = ${project.version} -builddate = ${git.build.time} - -Subversion Infos: -================= -repository = ${git.repository} -path = ${git.branch} -revision = ${git.commit.id} -lastCommitMessage = ${git.commit.message.short} -lastCommitDate = ${git.commit.time} \ No newline at end of file diff --git a/webapp/pom.xml b/webapp/pom.xml index 327112abe1..5ade90f88e 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -15,8 +15,8 @@ ${project.parent.basedir}/misc/conf/datasource.properties ${project.build.directory}/${project.build.finalName}/configuration.db - 2.0.0-SNAPSHOT - 2.0.0-SNAPSHOT + 2.0.0-alpha.6 + 2.0.0-alpha.3 1.0.0 9090 9091 @@ -135,6 +135,12 @@ src/main/webapp true + **/static/** + + + src/main/webapp + false + **/static/** src/main/resources diff --git a/webapp/src/main/webapp/static/client/helgoland/324b4fcaf164735c627269504b7bc28e.png b/webapp/src/main/webapp/static/client/helgoland/324b4fcaf164735c627269504b7bc28e.png new file mode 100644 index 0000000000..a2cf7f9efe Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/324b4fcaf164735c627269504b7bc28e.png differ diff --git a/webapp/src/main/webapp/static/client/helgoland/448c34a56d699c29117adc64c43affeb.woff2 b/webapp/src/main/webapp/static/client/helgoland/448c34a56d699c29117adc64c43affeb.woff2 new file mode 100644 index 0000000000..64539b54c3 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/448c34a56d699c29117adc64c43affeb.woff2 differ diff --git a/webapp/src/main/webapp/static/client/helgoland/674f50d287a8c48dc19ba404d20fe713.eot b/webapp/src/main/webapp/static/client/helgoland/674f50d287a8c48dc19ba404d20fe713.eot new file mode 100644 index 0000000000..e9f60ca953 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/674f50d287a8c48dc19ba404d20fe713.eot differ diff --git a/webapp/src/main/webapp/static/client/helgoland/7cb0d2482ecadc1b80eb0abe457371b6.png b/webapp/src/main/webapp/static/client/helgoland/7cb0d2482ecadc1b80eb0abe457371b6.png new file mode 100644 index 0000000000..bca0a0e429 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/7cb0d2482ecadc1b80eb0abe457371b6.png differ diff --git a/webapp/src/main/webapp/static/client/helgoland/89889688147bd7575d6327160d64e760.svg b/webapp/src/main/webapp/static/client/helgoland/89889688147bd7575d6327160d64e760.svg new file mode 100644 index 0000000000..94fb5490a2 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/89889688147bd7575d6327160d64e760.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/912ec66d7572ff821749319396470bde.svg b/webapp/src/main/webapp/static/client/helgoland/912ec66d7572ff821749319396470bde.svg new file mode 100644 index 0000000000..855c845e53 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/912ec66d7572ff821749319396470bde.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webapp/src/main/webapp/static/client/helgoland/af7ae505a9eed503f8b8e6982036873e.woff2 b/webapp/src/main/webapp/static/client/helgoland/af7ae505a9eed503f8b8e6982036873e.woff2 new file mode 100644 index 0000000000..4d13fc6040 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/af7ae505a9eed503f8b8e6982036873e.woff2 differ diff --git a/webapp/src/main/webapp/static/client/helgoland/b06871f281fee6b241d60582ae9369b9.ttf b/webapp/src/main/webapp/static/client/helgoland/b06871f281fee6b241d60582ae9369b9.ttf new file mode 100644 index 0000000000..35acda2fa1 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/b06871f281fee6b241d60582ae9369b9.ttf differ diff --git a/webapp/src/main/webapp/static/client/helgoland/e18bbf611f2a2e43afc071aa2f4e1512.ttf b/webapp/src/main/webapp/static/client/helgoland/e18bbf611f2a2e43afc071aa2f4e1512.ttf new file mode 100644 index 0000000000..1413fc609a Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/e18bbf611f2a2e43afc071aa2f4e1512.ttf differ diff --git a/webapp/src/main/webapp/static/client/helgoland/f4769f9bdb7466be65088239c12046d1.eot b/webapp/src/main/webapp/static/client/helgoland/f4769f9bdb7466be65088239c12046d1.eot new file mode 100644 index 0000000000..b93a4953ff Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/f4769f9bdb7466be65088239c12046d1.eot differ diff --git a/webapp/src/main/webapp/static/client/helgoland/f5b212817cdbcc5081276507371ce9a8.png b/webapp/src/main/webapp/static/client/helgoland/f5b212817cdbcc5081276507371ce9a8.png new file mode 100644 index 0000000000..da2bff7834 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/f5b212817cdbcc5081276507371ce9a8.png differ diff --git a/webapp/src/main/webapp/static/client/helgoland/fa2772327f55d8198301fdb8bcfc8158.woff b/webapp/src/main/webapp/static/client/helgoland/fa2772327f55d8198301fdb8bcfc8158.woff new file mode 100644 index 0000000000..9e612858f8 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/fa2772327f55d8198301fdb8bcfc8158.woff differ diff --git a/webapp/src/main/webapp/static/client/helgoland/fee66e712a8a08eef5805a46892932ad.woff b/webapp/src/main/webapp/static/client/helgoland/fee66e712a8a08eef5805a46892932ad.woff new file mode 100644 index 0000000000..400014a4b0 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/fee66e712a8a08eef5805a46892932ad.woff differ diff --git a/webapp/src/main/webapp/static/client/helgoland/i18n/de.json b/webapp/src/main/webapp/static/client/helgoland/i18n/de.json new file mode 100644 index 0000000000..497013d32e --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/i18n/de.json @@ -0,0 +1,288 @@ +{ + "fullName": "Deutsch", + "ok": "OK", + "main": { + "legend": "Legende", + "stationSelection": "Wähle eine Station aus", + "chartView": "Diagrammansicht", + "allPhenomena": "Alle Phänomene", + "phenomenon": "Phänomen", + "favoritesList": "Favoriten", + "importFavorites": "Importieren", + "exportFavorites": "Exportieren", + "importExportHelp": "Zum Import wählen sie eine zuvor exportierten JSON-Datei.", + "noFileSelected": "Keine Datei ausgewählt" + }, + "navigation": { + "diagram": "Diagramm", + "map": "Karte", + "favorite": "Favoriten", + "provider": "Anbieter", + "listSelection": "Listenauswahl", + "settings": "Einstellungen" + }, + "chart": { + "noTimeseriesSelected": "Sie haben keine Zeitreihe ausgewählt, die gewählten Zeitreihen haben keine Werte in dem derzeitigen Zeitraum oder die Zeitreihen sind unsichtbar.", + "outsideOfDataRange": "Außerhalb des Datenbereichs!", + "annotation": "Daten ohne Gewähr!", + "monthNames": { + "jan": "Jan", + "feb": "Feb", + "mar": "Mär", + "apr": "Apr", + "may": "Mai", + "jun": "Jun", + "jul": "Jul", + "aug": "Aug", + "sep": "Sep", + "oct": "Okt", + "nov": "Nov", + "dec": "Dez" + }, + "permalink": { + "useTimeParameter": "Derzeitigen gewählten Zeitraum im Permalink verwenden" + } + }, + "table": { + "time": "Zeit" + }, + "providerList": { + "provider": "Datenanbieter", + "serviceUrl": "Service-URL", + "stations": "Stationen", + "platforms": "Platformen", + "timeseries": "Zeitreihen", + "datasets": "Datensätze", + "phenomena": "Phänomene", + "selectAll": "Selektiere alle Anbieter" + }, + "map": { + "userLocation": "Hier ist ihr Standort", + "loading": "Stationen werden geladen", + "stationSelection": { + "station": "Station", + "selectAllTimeseries": "wähle alle Zeitreihen" + }, + "platformSelection": { + "platform": "Platform", + "datasetType": "Datentyp" + }, + "stationLocation": { + "station": "Station", + "timeseries": "Zeitreihe", + "provider": "Datenanbieter", + "jumpBackToChart": "zurück zum Diagramm" + }, + "search": { + "label": "suche Addresse ...", + "noResult": "Sorry, es konnte keine Adresse gefunden werden." + } + }, + "listSelection": { + "header": "Listenbasierte Zeitreihenauswahl", + "loading": "lade von {{countProvider}} Provider(n)...", + "headers": { + "category": "Kategorie", + "station": "Station", + "phenomenon": "Phänomen", + "procedure": "Sensor" + }, + "warning": { + "moreThanOneTimeseries": "Mehr als eine Zeitreihe gefunden" + } + }, + "legend": { + "entry": { + "noData": "keine Daten verfügbar", + "jumpToLastValue": "Springe zur letzten Messung", + "firstValueAt": "Erster Wert bei", + "lastValueAt": "Letzter Wert bei" + } + }, + "metadata": { + "procedure": { + "button": "Zeige Sensor-Metadaten", + "header": "Sensor-Metadaten" + } + }, + "export": { + "label": "Daten als CSV (Zip-Archiv)" + }, + "timeSelection": { + "header": "Zeitraum", + "presetsHeader": "Vordefiniert", + "presets": { + "lastHour": "letzte Stunde", + "today": "heute", + "yesterday": "gestern", + "todayYesterday": "heute & gestern", + "thisWeek": "diese Woche", + "lastWeek": "letzte Woche", + "thisMonth": "diesen Monat", + "lastMonth": "letzten Monat", + "thisYear": "dieses Jahr", + "lastYear": "letztes Jahr" + }, + "custom": { + "header": "Freidefiniert", + "start": "Startzeitpunkt", + "end": "Endzeitpunkt" + }, + "warning": { + "startBeforeEnd": "Der Startzeitpunkt darf nicht größer als der Endzeitpunkt sein", + "maxTimeRange": "Der ausgewählte Zeitraum darf nicht größer als ein Jahr sein" + } + }, + "styleChange": { + "header": "Ändern der Zeitreihengestaltung", + "currentColor": "Derzeitige Farbe", + "selectColor": "Wähle neue Farbe", + "selectBarInterval": "Wähle Balkeninterval", + "barChartInterval": { + "hour": "Stunde", + "day": "Tag", + "week": "Woche", + "month": "Monat" + }, + "zeroScaled": "Nullbasierte Y-Achse", + "groupedAxis": "gruppierte Achse" + }, + "settings": { + "header": "Einstellungen", + "chooseLanguage": "Sprache wechseln", + "requiresRestart": "Erfordert Neustart!", + "permalink": { + "create": "Erstelle Permalink", + "inWindow": "öffnen im neuen Fenster", + "inMail": "öffnen in leerer Mail", + "inClipboard": "Link für die Zwischenablage", + "clipboardInfo": "Bitte kopiere den folgenden Link selbstständig in die Zwischenablage:", + "inQrCode": "als QR-Code", + "favorite": "Arbeitsumgebung als Favorit speichern" + }, + "clusterMarker": "Marker gruppieren", + "markerWithLastInfo": { + "header": "Marker mit Wert der letzten Messung", + "label": "Achtung - dies kann bei einigen Providern zu langen Abfragen führen" + }, + "saveStatus": { + "header": "Arbeitsumgebung abspeichern", + "label": "Alle Zeitreihen, der ausgewählte Zeitraum und die Einstellungen werden kontinuierlich abgespeichert." + }, + "resetStatus": "Arbeitsumgebung zurücksetzen", + "generalizeData": "Daten generalisiert abfragen", + "imprint": { + "header": "Impressum", + "github": "Zur GitHub-Seite dieses Projekts", + "text": "

52°North GmbH ist für diese Website verantwortlich.

52°North Initiative for Geospatial Open Source Software GmbH
Martin-Luther-King-Weg 24
48155 Muenster, Deutschland

" + } + }, + "permalink": { + "noMatchingTimeseriesFound": "Keine passende Zeitreihe gefunden.", + "optionsHeader": "Permalink Optionen:" + }, + "guide": { + "start": { + "request": "Wenn du den Guide startest wird der aktuellen Zustand zurückgesetzt." + }, + "step1": { + "header": "JavaScript Client - Geführte Tour", + "text": "Die Tour gibt in ein paar Schritten einen Überblick über den Client. Zuerst fügen wir eine Zeitreihe von der Karte hinzu." + }, + "step2": { + "header": "Zur Karte", + "text": "Hier kann man zur Kartenansicht wechseln." + }, + "step3": { + "header": "Kartenansicht", + "text": "In der Karte siehst du die Stationen als Marker oder Markergruppen." + }, + "step4": { + "header": "Datenanbieter", + "text": "Hier kannst du aus einer Liste von Datenanbieter auswählen." + }, + "step5": { + "header": "Eigene Position", + "text": "Hier kannst du dich lokalisieren lassen." + }, + "step6": { + "header": "Listenauswahl", + "text": "Hier ist eine Zeitreihenauswahl durch geordnete Listen möglich." + }, + "step7": { + "header": "Auswahl einer Station", + "text": "Bitte wähle eine Station auf der Karte aus." + }, + "step8": { + "header": "Zeitreihe auswählen", + "text": "Wähle eine Zeitreihe durch Anklicken der Checkbox. Liegt an dieser Station nur eine Zeitreihe vor, ist diese direkt angewählt. Durch klicken des OK-Buttons wird die Zeitreihe eingeladen." + }, + "step9": { + "header": "Legendeneintrag", + "text": "Hier wird die zugefügte Zeitreihe angezeigt. Du kannst die Zeitreihe hier wieder entfernen oder den Style ändern." + }, + "step10": { + "header": "Diagramm", + "text": "Dies ist das Diagramm der gewählten Zeitreihen." + }, + "step11": { + "header": "Zeit ändern", + "text": "Hier kann der Zeitraum angepasst werden." + }, + "step12": { + "header": "Tabellenansicht", + "text": "Hier bekommt man die Rohdaten in einer Tabelle präsentiert." + }, + "step13": { + "header": "Favoritenverwaltung", + "text": "Die Legendeneinträge/Zeitreihen können als Favoriten abgespeichert werden. Hier werden alle Favoriten gelistet und können verwaltet werden." + }, + "step14": { + "header": "Fertig", + "text": "Super!
Dieser Client ist ein Produkt von der 52°North GmbH. Auf GitHub findest du den aktuellen Entwicklungsstand." + } + }, + "favorite": { + "firstValueAt": "Erster Wert bei", + "lastValueAt": "Letzter Wert bei", + "label": "Favorit", + "edit": { + "header": "Favorit editieren" + }, + "group": { + "add": "Der Status wird mit dem Name '{0}' in den Favoriten abgelegt.", + "exists": "Dieser Status existiert bereits.", + "noTimeseries": "Derzeit sind keine Zeitreihen ausgewählt.", + "notSupported": "Der Datenanbieter eines Eintrag aus '{0}' wird nicht unterstützt und kann deswegen nicht eingeladen werden." + }, + "single": { + "add": "Einer neuer Favorit mit dem Name '{0}' ist abgelegt worden.", + "remove": "Der Favorit '{0}' ist entfernt worden.", + "exists": "Dieser Favorit existiert bereits.", + "notSupported": "Der Datenanbieter des Favoriten '{0}' wird nicht unterstützt und kann deswegen nicht eingeladen werden." + }, + "import": { + "override": "Wollen Sie die aktuellen Favoriten überschreiben?", + "wrongFile": "Die Datei kann nicht gelesen werden.", + "noValidJson": "Die JSON Datei ist nicht valide.", + "header": "Importiere Favoriten", + "text": "Hier können Sie ihre Favoriten importieren. Einfach das JSON in das Textfeld einfügen:" + }, + "export": { + "header": "Exportiere Favortien", + "text": "Hier können Sie ihre Favoriten exportieren. Einfah das JSON aus dem Textfeld kopieren und speichern, um es später wieder zu importieren:" + }, + "error": { + "fileApiNotSupported": "Die File-API wird in diesem Browser nicht unterstüzt." + } + }, + "inform": { + "error": "Ein Fehler ist aufgetreten: ", + "warn": "Bitte beachten Sie: " + }, + "metadataOutput": { + "selectRawProcedureFormat": "Procedure als Rohdata", + "selectTimeseriesDataFormat": "Zeitreihendaten als Rohdaten", + "showCapabilities": "Zeige SOS-Capabilities" + } +} diff --git a/webapp/src/main/webapp/static/client/helgoland/i18n/en.json b/webapp/src/main/webapp/static/client/helgoland/i18n/en.json new file mode 100644 index 0000000000..b575105099 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/i18n/en.json @@ -0,0 +1,288 @@ +{ + "fullName": "English", + "ok": "OK", + "main": { + "legend": "Legend", + "stationSelection": "Select a station", + "chartView": "Chart view", + "allPhenomena": "All Phenomena", + "phenomenon": "Phenomenon", + "favoritesList": "Favorites", + "importFavorites": "Import", + "exportFavorites": "Export", + "importExportHelp": "To import a file, please choose a file you exported before.", + "noFileSelected": "No file selected" + }, + "navigation": { + "diagram": "Diagram", + "map": "Map", + "favorite": "Favorites", + "provider": "Provider", + "listSelection": "List selection", + "settings": "Settings" + }, + "chart": { + "noTimeseriesSelected": "You have selected no timeseries, the selected timeseries have no values in the given time range or the timeseries are hidden.", + "outsideOfDataRange": "Outside of data range!", + "annotation": "Data without warranty!", + "monthNames": { + "jan": "Jan", + "feb": "Feb", + "mar": "Mar", + "apr": "Apr", + "may": "May", + "jun": "Jun", + "jul": "Jul", + "aug": "Aug", + "sep": "Sep", + "oct": "Oct", + "nov": "Nov", + "dec": "Dec" + }, + "permalink": { + "useTimeParameter": "Use current selected time period in permalink" + } + }, + "table": { + "time": "Time" + }, + "providerList": { + "provider": "Provider", + "serviceUrl": "Service-URL", + "stations": "Stations", + "platforms": "Platforms", + "timeseries": "Timeseries", + "datasets": "Datasets", + "phenomena": "Phenomena", + "selectAll": "Select all provider" + }, + "map": { + "userLocation": "Here is your current location", + "loading": "Stations will be loaded", + "stationSelection": { + "station": "Station", + "selectAllTimeseries": "select all timeseries" + }, + "platformSelection": { + "platform": "Platform", + "datasetType": "Dataset type" + }, + "stationLocation": { + "station": "Station", + "timeseries": "Timeseries", + "provider": "Provider", + "jumpBackToChart": "back to chart" + }, + "search": { + "label": "search for address ...", + "noResult": "Sorry, that address could not be found." + } + }, + "listSelection": { + "header": "Select timeseries by list", + "loading": "loading from {{countProvider}} provider(s)...", + "headers": { + "category": "Category", + "station": "Station", + "phenomenon": "Phenomenon", + "procedure": "Sensor" + }, + "warning": { + "moreThanOneTimeseries": "found more than one timeseries" + } + }, + "legend": { + "entry": { + "noData": "no Data available", + "jumpToLastValue": "jump to last value", + "firstValueAt": "First value at", + "lastValueAt": "Last value at" + } + }, + "metadata": { + "procedure": { + "button": "Show sensor metadata", + "header": "Sensor metadata" + } + }, + "export": { + "label": "Data as CSV (Zip Archive)" + }, + "timeSelection": { + "header": "Time Range", + "presetsHeader": "presets", + "presets": { + "lastHour": "last hour", + "today": "today", + "yesterday": "yesterday", + "todayYesterday": "today & yesterday", + "thisWeek": "this week", + "lastWeek": "last week", + "thisMonth": "this month", + "lastMonth": "last month", + "thisYear": "this year", + "lastYear": "last year" + }, + "custom": { + "header": "custom", + "start": "Start date", + "end": "End date" + }, + "warning": { + "startBeforeEnd": "The start date can not be greater then the end date", + "maxTimeRange": "The time range can not be greater then one year" + } + }, + "styleChange": { + "header": "Change style", + "currentColor": "Current color", + "selectColor": "Select a new color", + "selectBarInterval": "Select the bar interval", + "barChartInterval": { + "hour": "Hour", + "day": "Day", + "week": "Week", + "month": "Month" + }, + "zeroScaled": "zero scaled Y-axis", + "groupedAxis": "grouped axis" + }, + "settings": { + "header": "Settings", + "chooseLanguage": "Switch language", + "requiresRestart": "Needs Restart!", + "permalink": { + "create": "Create a permalink as", + "inWindow": "link in a new window", + "inMail": "link in an email", + "inClipboard": "link for the clipboard", + "clipboardInfo": "Please copy the following link by yourself to clipboard:", + "inQrCode": "as QR-Code", + "favorite": "Save working environment as favorite entry" + }, + "clusterMarker": "cluster marker", + "markerWithLastInfo": { + "header": "marker with last value information", + "label": "attention - some data provider are very slow" + }, + "saveStatus": { + "header": "Save environment", + "label": "All timeseries, the selected timespan and the settings are saved continuous." + }, + "resetStatus": "Reset environment", + "generalizeData": "generalize Data", + "imprint": { + "header": "Imprint", + "github": "Find this project at GitHub", + "text": "

52°North GmbH is responsible for this website.

52°North Initiative for Geospatial Open Source Software GmbH
Martin-Luther-King-Weg 24
48155 Muenster, Germany

" + } + }, + "permalink": { + "noMatchingTimeseriesFound": "No matching timeseries is found.", + "optionsHeader": "Permalink options:" + }, + "guide": { + "start": { + "request": "When you start this guide, the the current state will be reset." + }, + "step1": { + "header": "JavaScript Client - Guided Tour", + "text": "This tour gives in a few steps an overview how to use this client. First we add a timeseries from the map." + }, + "step2": { + "header": "Go to the map", + "text": "Here we switch the view to get a map." + }, + "step3": { + "header": "Map view", + "text": "This is the map view. In the map you can see markers or markergroups." + }, + "step4": { + "header": "Change Provider", + "text": "Here you can select another timeseries provider." + }, + "step5": { + "header": "Show location", + "text": "And here you can locate your device on the map." + }, + "step6": { + "header": "List selection", + "text": "Here you can select a timeseries out of ordered lists." + }, + "step7": { + "header": "Select a station", + "text": "Please select now a station on the map." + }, + "step8": { + "header": "Select timeseries", + "text": "Select this checkbox. If there is only one timeseries for this station, the checkbox is already checked. Now you can go on with the 'OK' button to load the timeseries." + }, + "step9": { + "header": "Legend entry", + "text": "Here you see the added time series. You can delete or locate the time series or change the color." + }, + "step10": { + "header": "Chart", + "text": "This is the chart of the selected time series." + }, + "step11": { + "header": "Change time", + "text": "Here you can change the time extent for your selected time series." + }, + "step12": { + "header": "Table View", + "text": "Here you get a table of the raw data values to your selected time series." + }, + "step13": { + "header": "Favorite management", + "text": "The legend entries/timeseries could be saved as favorites. In this view all favorites are listed and could be maintained." + }, + "step14": { + "header": "Finished", + "text": "Well done!
This client is a product of 52°North GmbH. You can find the source code on GitHub." + } + }, + "favorite": { + "firstValueAt": "First value at", + "lastValueAt": "Last value at", + "label": "favorite", + "edit": { + "header": "Edit favorite" + }, + "group": { + "add": "The status '{0}' is added to the favorite list.", + "exists": "This status still exists.", + "noTimeseries": "Currently no timeseries are selected.", + "notSupported": "The provider of an entry of the status '{0}' isn't supported and can't be loaded." + }, + "single": { + "add": "A new favorite '{0}' is added to the list.", + "remove": "The favorite '{0}' is removed.", + "exists": "This favorite still exists.", + "notSupported": "The provider of the favorite '{0}' isn't supported and can't be loaded." + }, + "import": { + "override": "Do you want to override your current favorites?", + "wrongFile": "Could not read the file", + "noValidJson": "The JSON file is not valid!", + "header": "Import favorites", + "text": "Here you can import your exported favorites. Just paste the JSON in this text field:" + }, + "export": { + "header": "Export favorites", + "text": "Here you can export your favorites. Just copy the JSON out of this textbox and save it in a file to import it later:" + }, + "error": { + "fileApiNotSupported": "The File APIs are not fully supported in this browser." + } + }, + "inform": { + "error": "An error occured: ", + "warn": "Please remember that: " + }, + "metadataOutput": { + "selectRawProcedureFormat": "Select raw format for procedure", + "selectTimeseriesDataFormat": "Select raw format for timeseries data", + "showCapabilities": "Show Capabilities of the SOS" + } +} diff --git a/webapp/src/main/webapp/static/client/helgoland/i18n/pt.json b/webapp/src/main/webapp/static/client/helgoland/i18n/pt.json new file mode 100644 index 0000000000..ef5e77a391 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/i18n/pt.json @@ -0,0 +1,284 @@ +{ + "fullName": "Portuguese", + "ok": "OK", + "main": { + "legend": "Legenda", + "stationSelection": "Selecione uma estação", + "chartView": "Visualização do gráfico", + "allPhenomena": "Todos os fenômenos", + "phenomenon": "Fenômeno", + "favoritesList": "Favoritos", + "importFavorites": "Importar", + "exportFavorites": "Exportar", + "importExportHelp": "Para importar um arquivo, escolha um arquivo que você exportou antes.", + "noFileSelected": "Nenhum arquivo selecionado" + }, + "navigation": { + "diagram": "Diagrama", + "map": "Mapa", + "favorite": "Favoritos", + "provider": "Provedor", + "listSelection": "Listar Seleção", + "settings": "Configurações" + }, + "chart": { + "noTimeseriesSelected": "Nenhuma série temporal foi selecionada, as séries temporais selecionadas não têm valores no intervalo de tempo determinado ou as séries temporais estão ocultas.", + "outsideOfDataRange": "Fora do intervalo de dados!", + "annotation": "Dados sem garantia!", + "monthNames": { + "jan": "Jan", + "feb": "Fev", + "mar": "Mar", + "apr": "Abr", + "may": "Maio", + "jun": "Jun", + "jul": "Jul", + "aug": "Ago", + "sep": "Set", + "oct": "Out", + "nov": "Nov", + "dec": "Dez" + } + }, + "table": { + "time": "Período" + }, + "providerList": { + "provider": "Provedor", + "serviceUrl": "Servidor-URL", + "stations": "Estações", + "platforms": "Plataformas", + "timeseries": "Séries Temporais", + "datasets": "Conjuntos de dados", + "phenomena": "Fenômenos", + "selectAll": "Selecionar tudo" + }, + "map": { + "userLocation": "Aqui está a sua localização atual", + "loading": "As estações serão carregadas", + "stationSelection": { + "station": "Estação", + "selectAllTimeseries": "Selecione todas as séries temporais" + }, + "platformSelection": { + "platform": "Plataforma", + "datasetType": "Tipo de conjunto de dados" + }, + "stationLocation": { + "station": "Estação", + "timeseries": "Séries Temporais", + "provider": "Provedor", + "jumpBackToChart": "Voltar ao gráfico" + }, + "search": { + "label": "Procurar endereço ...", + "noResult": "Desculpe, esse endereço não pode ser encontrado." + } + }, + "listSelection": { + "header": "Selecionar série temporal por lista", + "loading": "carregando do(s){{countProvider}} fornecedor(es) ...", + "headers": { + "category": "Categoria", + "station": "Estação", + "phenomenon": "Fenômeno", + "procedure": "Sensor" + }, + "warning": { + "moreThanOneTimeseries": "Foram encontradas mais de uma série temporal" + } + }, + "legend": { + "entry": { + "noData": "Não há dados disponí­veis", + "jumpToLastValue": "vá para o último valor", + "firstValueAt": "Primeiro valor em", + "lastValueAt": "Último valor em" + } + }, + "metadata": { + "procedure": { + "button": "Mostrar metadados do sensor", + "header": "Metadados do sensor" + } + }, + "export": { + "label": "Dados como CSV (Arquivo Zip)" + }, + "timeSelection": { + "header": "Intervalo de tempo", + "presetsHeader": "Predefinições", + "presets": { + "lastHour": "última hora", + "today": "hoje", + "yesterday": "ontem", + "todayYesterday": "hoje & ontem", + "thisWeek": "esta semana", + "lastWeek": "semana passada", + "thisMonth": "este mês", + "lastMonth": "mês passado", + "thisYear": "este ano", + "lastYear": "ano passado" + }, + "custom": { + "header": "personalizado", + "start": "Data de início", + "end": "Data de término" + }, + "warning": { + "startBeforeEnd": "A data de início não pode ser superior a data final", + "maxTimeRange": "O intervalo de tempo não pode ser superior a um ano" + } + }, + "styleChange": { + "header": "Alterar estilo", + "currentColor": "Cor", + "selectColor": "Selecione uma nova cor", + "selectBarInterval": "Selecione o intervalo da barra", + "barChartInterval": { + "hour": "Hora", + "day": "dia", + "week": "semana", + "month": "mês" + }, + "zeroScaled": "Escala zero do Eixo Y", + "groupedAxis": "Eixo agrupado" + }, + "settings": { + "header": "Configurações", + "chooseLanguage": "Alterar idioma", + "requiresRestart": "Reinicialização necessária!", + "permalink": { + "create": "Crie um permalink como", + "inWindow": "Link em uma nova janela", + "inMail": "Link em um email", + "inClipboard": "Link para a área de transferência", + "clipboardInfo": "Por favor, copie o seguinte link para a área de transferência", + "inQrCode": "como QR - Code ", + "favorite": "Salvar ambiente de trabalho como entrada favorita" + }, + "clusterMarker": "marcador de agrupamento", + "markerWithLastInfo": { + "header": "Marcador com informações de último valor", + "label": "Atenção - alguns provedores de dados são muito lentos" + }, + "saveStatus": { + "header": "Salvar ambiente", + "label": "Todas as séries temporais, o perí­odo de tempo selecionado e as configurações serõa salvas continuamente." + }, + "resetStatus": "Redefinir ambiente", + "generalizeData": "Generalizar dados", + "imprint": { + "header": "Impressão", + "github": "Encontre este projeto em GitHub", + "text": "

52°North GmbH é responsável por este site.

52°North Initiative for Geospatial Open Source Software GmbH
Martin-Luther-King-Weg 24
48155 Muenster, Germany

" + } + }, + "permalink": { + "noMatchingTimeseriesFound": "Nenhuma Série Temporal correspondente encontrada." + }, + "guide": { + "start": { + "request": "Quando você iniciar este guia, o estado atual será reiniciado." + }, + "step1": { + "header": "Cliente JavaScript - Visita guiada", + "text": "Este guia dá em alguns passos uma visão geral sobre como usar esse cliente. Primeiro, adicionamos uma série temporal do mapa." + }, + "step2": { + "header": "Vá para o mapa", + "text": "Aqui mudamos a vista para obter um mapa." + }, + "step3": { + "header": "Visão do mapa", + "text": "Esta é a vista do mapa. No mapa você pode ver marcadores ou grupos de marcadores." + }, + "step4": { + "header": "Alterar provedor", + "text": "Aqui você pode selecionar outro provedor de séries temporais." + }, + "step5": { + "header": "Mostrar localização", + "text": "E aqui você pode localizar seu dispositivo no mapa." + }, + "step6": { + "header": "Seleção de lista", + "text": "Aqui você pode selecionar uma série temporal fora das listas ordenadas." + }, + "step7": { + "header": "Selecione uma estação", + "text": "Por favor, selecione agora uma estação no mapa." + }, + "step8": { + "header": "Selecionar séries temporais", + "text": "Selecione esta caixa de verificação. Se houver apenas uma série temporal para esta estação, a caixa de seleção já está marcada. Agora você pode continuar com o botão 'OK' para carregar as séries temporais." + }, + "step9": { + "header": "Entrada de legenda", + "text": "Aqui você vê as séries temporais adicionadas. Você pode excluir ou localizar a série temporal ou alterar a cor." + }, + "step10": { + "header": "Gráficos", + "text": "Este é o gráfico das séries temporais selecionadas." + }, + "step11": { + "header": "Alterar o tempo", + "text": "Aqui você pode alterar a extensão do tempo, para a série temporal selecionada." + }, + "step12": { + "header": "Vista de tabela", + "text": "Aqui você obtém uma tabela dos valores de dados brutos para as séries temporais selecionadas." + }, + "step13": { + "header": "Gestão de favoritos", + "text": "As entradas de legenda/séries temporais podem ser salvas como favoritos. Nesta visão, todos os favoritos são listados e mantidos.." + }, + "step14": { + "header": "Finalizado", + "text": "Bem feito!
Este cliente é um produto de 52°North GmbH. Você pode encontrar o código-fonte em GitHub." + } + }, + "favorite": { + "firstValueAt": "Primeiro valor em", + "lastValueAt": "Último valor em", + "label": "favorito", + "edit": { + "header": "Editar favoritos" + }, + "group": { + "add": "O status '{0}' é adicionado a lista de favoritos.", + "exists": "Esse status já existe.", + "noTimeseries": "Atualmente não há séries temporais selecionadas.", + "notSupported": "O provedor de uma entrada do status '{0}' não é suportado e não pode ser carregado." + }, + "single": { + "add": "Um novo favorito '{0}' é adicionado à lista.", + "remove": "O favorito '{0}' é removido.", + "exists": "Este favorito já existe..", + "notSupported": "O provedor do favorito '{0}' não é suportado e não pode ser carregado." + }, + "import": { + "override": "Deseja substituir seus favoritos?", + "wrongFile": "não foi possí­vel ler o arquivo", + "noValidJson": "O arquivo JSON não é válido!", + "header": "Importar favoritos", + "text": "Aqui você pode importar seus favoritos exportados. Basta colar o JSON neste campo de texto:" + }, + "export": { + "header": "Exportar favoritos", + "text": "Aqui Você pode exportar seus favoritos. Basta copiar o JSON desta caixa de texto e guardá-lo em um arquivo para importá-lo mais tarde:" + }, + "error": { + "fileApiNotSupported": " Os arquivos API não são totalmente compatíveis neste navegador." + } + }, + "inform": { + "error": "Um erro ocorreu: ", + "warn": "Por favor lembre-se disso: " + }, + "metadataOutput": { + "selectRawProcedureFormat": "Selecione o formato bruto para o procedimento", + "selectTimeseriesDataFormat": " Selecione o formato bruto para dados da série temporal", + "showCapabilities": "Mostrar capacidades do SOS" + } +} diff --git a/webapp/src/main/webapp/static/client/helgoland/images/blank.gif b/webapp/src/main/webapp/static/client/helgoland/images/blank.gif new file mode 100644 index 0000000000..26da8e21a2 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/images/blank.gif differ diff --git a/webapp/src/main/webapp/static/client/helgoland/images/favicon.ico b/webapp/src/main/webapp/static/client/helgoland/images/favicon.ico new file mode 100644 index 0000000000..3ea23894c3 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/images/favicon.ico differ diff --git a/webapp/src/main/webapp/static/client/helgoland/images/flags.png b/webapp/src/main/webapp/static/client/helgoland/images/flags.png new file mode 100644 index 0000000000..da2bff7834 Binary files /dev/null and b/webapp/src/main/webapp/static/client/helgoland/images/flags.png differ diff --git a/webapp/src/main/webapp/static/client/helgoland/index.html b/webapp/src/main/webapp/static/client/helgoland/index.html new file mode 100644 index 0000000000..50b645ea8d --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + Helgoland + + + + + + + + + + diff --git a/webapp/src/main/webapp/static/client/helgoland/main.1ec83566c281d8de294a.bundle.js b/webapp/src/main/webapp/static/client/helgoland/main.1ec83566c281d8de294a.bundle.js new file mode 100644 index 0000000000..9dccbc361e --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/main.1ec83566c281d8de294a.bundle.js @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2012-2018 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. + */ +!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=62)}([function(e,t){function n(e,t){var n=e[1]||"",i=e[3];if(!i)return n;if(t&&"function"==typeof btoa){var o=r(i);return[n].concat(i.sources.map(function(e){return"/*# sourceURL="+i.sourceRoot+e+" */"})).concat([o]).join("\n")}return[n].join("\n")}function r(e){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e))))+" */"}e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var r=n(t,e);return t[2]?"@media "+t[2]+"{"+r+"}":r}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},i=0;i=0&&y.splice(t,1)}function s(e){var t=document.createElement("style");return e.attrs.type="text/css",c(t,e.attrs),o(e,t),t}function l(e){var t=document.createElement("link");return e.attrs.type="text/css",e.attrs.rel="stylesheet",c(t,e.attrs),o(e,t),t}function c(e,t){Object.keys(t).forEach(function(n){e.setAttribute(n,t[n])})}function u(e,t){var n,r,i,o;if(t.transform&&e.css){if(!(o=t.transform(e.css)))return function(){};e.css=o}if(t.singleton){var c=b++;n=v||(v=s(t)),r=d.bind(null,n,c,!1),i=d.bind(null,n,c,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=l(t),r=f.bind(null,n,t),i=function(){a(n),n.href&&URL.revokeObjectURL(n.href)}):(n=s(t),r=p.bind(null,n),i=function(){a(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else i()}}function d(e,t,n,r){var i=n?"":r.css;if(e.styleSheet)e.styleSheet.cssText=w(t,i);else{var o=document.createTextNode(i),a=e.childNodes;a[t]&&e.removeChild(a[t]),a.length?e.insertBefore(o,a[t]):e.appendChild(o)}}function p(e,t){var n=t.css,r=t.media;if(r&&e.setAttribute("media",r),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}function f(e,t,n){var r=n.css,i=n.sourceMap,o=void 0===t.convertToAbsoluteUrls&&i;(t.convertToAbsoluteUrls||o)&&(r=x(r)),i&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(i))))+" */");var a=new Blob([r],{type:"text/css"}),s=e.href;e.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}var h={},g=function(e){var t;return function(){return void 0===t&&(t=e.apply(this,arguments)),t}}(function(){return window&&document&&document.all&&!window.atob}),m=function(e){var t={};return function(n){return void 0===t[n]&&(t[n]=e.call(this,n)),t[n]}}(function(e){return document.querySelector(e)}),v=null,b=0,y=[],x=n(99);e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");t=t||{},t.attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||(t.singleton=g()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=i(e,t);return r(n,t),function(e){for(var o=[],a=0;a=0&&e.splice(n,1),e}function l(e,t){return e.push(t),t}function c(e){for(var n=[],r=1;r=r?e.apply(null,n):function(){return t(n.concat([].slice.apply(arguments)))}}var n=[].slice.apply(arguments,[1]),r=e.length;return t(n)}function i(){var e=arguments,t=e.length-1;return function(){for(var n=t,r=e[t].apply(this,arguments);n--;)r=e[n].call(this,r);return r}}function o(){for(var e=[],t=0;t0&&t-1 in e)}function l(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}function c(e,t,n){return be.isFunction(t)?be.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?be.grep(e,function(e){return e===t!==n}):"string"!=typeof t?be.grep(e,function(e){return de.call(t,e)>-1!==n}):Ee.test(t)?be.filter(t,e,n):(t=be.filter(t,e),be.grep(e,function(e){return de.call(t,e)>-1!==n&&1===e.nodeType}))}function u(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function d(e){var t={};return be.each(e.match(Me)||[],function(e,n){t[n]=!0}),t}function p(e){return e}function f(e){throw e}function h(e,t,n,r){var i;try{e&&be.isFunction(i=e.promise)?i.call(e).done(t).fail(n):e&&be.isFunction(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}function g(){ae.removeEventListener("DOMContentLoaded",g),n.removeEventListener("load",g),be.ready()}function m(){this.expando=be.expando+m.uid++}function v(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Ue.test(e)?JSON.parse(e):e)}function b(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ze,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=v(n)}catch(e){}Ne.set(e,t,n)}else n=void 0;return n}function y(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return be.css(e,t,"")},l=s(),c=n&&n[3]||(be.cssNumber[t]?"":"px"),u=(be.cssNumber[t]||"px"!==c&&+l)&&He.exec(be.css(e,t));if(u&&u[3]!==c){c=c||u[3],n=n||[],u=+l||1;do{o=o||".5",u/=o,be.style(e,t,u+c)}while(o!==(o=s()/l)&&1!==o&&--a)}return n&&(u=+u||+l||0,i=n[1]?u+(n[1]+1)*n[2]:+n[2],r&&(r.unit=c,r.start=u,r.end=i)),i}function x(e){var t,n=e.ownerDocument,r=e.nodeName,i=Ge[r];return i||(t=n.body.appendChild(n.createElement(r)),i=be.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),Ge[r]=i,i)}function w(e,t){for(var n,r,i=[],o=0,a=e.length;o-1)i&&i.push(o);else if(c=be.contains(o.ownerDocument,o),a=k(d.appendChild(o),"script"),c&&_(a),n)for(u=0;o=a[u++];)Je.test(o.type||"")&&n.push(o);return d}function C(){return!0}function S(){return!1}function T(){try{return ae.activeElement}catch(e){}}function E(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)E(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=S;else if(!i)return e;return 1===o&&(a=i,i=function(e){return be().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=be.guid++)),e.each(function(){be.event.add(this,t,i,r,n)})}function D(e,t){return l(e,"table")&&l(11!==t.nodeType?t:t.firstChild,"tr")?be(">tbody",e)[0]||e:e}function P(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function L(e){var t=at.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function O(e,t){var n,r,i,o,a,s,l,c;if(1===t.nodeType){if(Re.hasData(e)&&(o=Re.access(e),a=Re.set(t,o),c=o.events)){delete a.handle,a.events={};for(i in c)for(n=0,r=c[i].length;n1&&"string"==typeof h&&!ve.checkClone&&ot.test(h))return e.each(function(i){var o=e.eq(i);g&&(t[0]=h.call(this,i,o.html())),A(o,t,n,r)});if(p&&(i=$(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(s=be.map(k(i,"script"),P),l=s.length;d=0&&nw.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[R]=!0,e}function i(e){var t=L.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)w.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ke(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&void 0!==e.getElementsByTagName&&e}function u(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function h(e,n,r){for(var i=0,o=n.length;i-1&&(r[c]=!(a[c]=d))}}else y=g(y===a?y.splice(m,y.length):y),o?o(null,a,y,l):J.apply(a,y)})}function v(e){for(var t,n,r,i=e.length,o=w.relative[e[0].type],a=o||w.relative[" "],s=o?1:0,l=p(function(e){return e===t},a,!0),c=p(function(e){return K(t,e)>-1},a,!0),u=[function(e,n,r){var i=!o&&(r||n!==T)||((t=n).nodeType?l(e,n,r):c(e,n,r));return t=null,i}];s1&&f(u),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(oe,"$1"),n,s0,o=e.length>0,a=function(r,a,s,l,c){var u,d,p,f=0,h="0",m=r&&[],v=[],b=T,y=r||o&&w.find.TAG("*",c),x=U+=null==b?1:Math.random()||.1,k=y.length;for(c&&(T=a===L||a||c);h!==k&&null!=(u=y[h]);h++){if(o&&u){for(d=0,a||u.ownerDocument===L||(P(u),s=!M);p=e[d++];)if(p(u,a||L,s)){l.push(u);break}c&&(U=x)}i&&((u=!p&&u)&&f--,r&&m.push(u))}if(f+=h,i&&h!==f){for(d=0;p=n[d++];)p(m,v,a,s);if(r){if(f>0)for(;h--;)m[h]||v[h]||(v[h]=Z.call(l));v=g(v)}J.apply(l,v),c&&!r&&v.length>0&&f+n.length>1&&t.uniqueSort(l)}return c&&(U=x,T=b),m};return i?r(a):a}var y,x,w,k,_,$,C,S,T,E,D,P,L,O,M,A,F,I,j,R="sizzle"+1*new Date,N=e.document,U=0,z=0,B=n(),H=n(),V=n(),q=function(e,t){return e===t&&(D=!0),0},W={}.hasOwnProperty,G=[],Z=G.pop,Y=G.push,J=G.push,X=G.slice,K=function(e,t){for(var n=0,r=e.length;n+~]|"+ee+")"+ee+"*"),le=new RegExp("="+ee+"*([^\\]'\"]*?)"+ee+"*\\]","g"),ce=new RegExp(re),ue=new RegExp("^"+te+"$"),de={ID:new RegExp("^#("+te+")"),CLASS:new RegExp("^\\.("+te+")"),TAG:new RegExp("^("+te+"|[*])"),ATTR:new RegExp("^"+ne),PSEUDO:new RegExp("^"+re),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ee+"*(even|odd|(([+-]|)(\\d*)n|)"+ee+"*(?:([+-]|)"+ee+"*(\\d+)|))"+ee+"*\\)|)","i"),bool:new RegExp("^(?:"+Q+")$","i"),needsContext:new RegExp("^"+ee+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ee+"*((?:-\\d)?\\d*)"+ee+"*\\)|)(?=[^-]|$)","i")},pe=/^(?:input|select|textarea|button)$/i,fe=/^h\d$/i,he=/^[^{]+\{\s*\[native \w/,ge=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,me=/[+~]/,ve=new RegExp("\\\\([\\da-f]{1,6}"+ee+"?|("+ee+")|.)","ig"),be=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},ye=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,xe=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},we=function(){P()},ke=p(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{J.apply(G=X.call(N.childNodes),N.childNodes),G[N.childNodes.length].nodeType}catch(e){J={apply:G.length?function(e,t){Y.apply(e,X.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}x=t.support={},_=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},P=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:N;return r!==L&&9===r.nodeType&&r.documentElement?(L=r,O=L.documentElement,M=!_(L),N!==L&&(n=L.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",we,!1):n.attachEvent&&n.attachEvent("onunload",we)),x.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),x.getElementsByTagName=i(function(e){return e.appendChild(L.createComment("")),!e.getElementsByTagName("*").length}),x.getElementsByClassName=he.test(L.getElementsByClassName),x.getById=i(function(e){return O.appendChild(e).id=R,!L.getElementsByName||!L.getElementsByName(R).length}),x.getById?(w.filter.ID=function(e){var t=e.replace(ve,be);return function(e){return e.getAttribute("id")===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&M){var n=t.getElementById(e);return n?[n]:[]}}):(w.filter.ID=function(e){var t=e.replace(ve,be);return function(e){var n=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&M){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),w.find.TAG=x.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):x.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},w.find.CLASS=x.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&M)return t.getElementsByClassName(e)},F=[],A=[],(x.qsa=he.test(L.querySelectorAll))&&(i(function(e){O.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&A.push("[*^$]="+ee+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||A.push("\\["+ee+"*(?:value|"+Q+")"),e.querySelectorAll("[id~="+R+"-]").length||A.push("~="),e.querySelectorAll(":checked").length||A.push(":checked"),e.querySelectorAll("a#"+R+"+*").length||A.push(".#.+[+~]")}),i(function(e){e.innerHTML="";var t=L.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&A.push("name"+ee+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&A.push(":enabled",":disabled"),O.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&A.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),A.push(",.*:")})),(x.matchesSelector=he.test(I=O.matches||O.webkitMatchesSelector||O.mozMatchesSelector||O.oMatchesSelector||O.msMatchesSelector))&&i(function(e){x.disconnectedMatch=I.call(e,"*"),I.call(e,"[s!='']:x"),F.push("!=",re)}),A=A.length&&new RegExp(A.join("|")),F=F.length&&new RegExp(F.join("|")),t=he.test(O.compareDocumentPosition),j=t||he.test(O.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},q=t?function(e,t){if(e===t)return D=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!x.sortDetached&&t.compareDocumentPosition(e)===n?e===L||e.ownerDocument===N&&j(N,e)?-1:t===L||t.ownerDocument===N&&j(N,t)?1:E?K(E,e)-K(E,t):0:4&n?-1:1)}:function(e,t){if(e===t)return D=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],l=[t];if(!i||!o)return e===L?-1:t===L?1:i?-1:o?1:E?K(E,e)-K(E,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)l.unshift(n);for(;s[r]===l[r];)r++;return r?a(s[r],l[r]):s[r]===N?-1:l[r]===N?1:0},L):L},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==L&&P(e),n=n.replace(le,"='$1']"),x.matchesSelector&&M&&!V[n+" "]&&(!F||!F.test(n))&&(!A||!A.test(n)))try{var r=I.call(e,n);if(r||x.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return t(n,L,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==L&&P(e),j(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==L&&P(e);var n=w.attrHandle[t.toLowerCase()],r=n&&W.call(w.attrHandle,t.toLowerCase())?n(e,t,!M):void 0;return void 0!==r?r:x.attributes||!M?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.escape=function(e){return(e+"").replace(ye,xe)},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(D=!x.detectDuplicates,E=!x.sortStable&&e.slice(0),e.sort(q),D){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return E=null,e},k=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=k(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=k(t);return n},w=t.selectors={cacheLength:50,createPseudo:r,match:de,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(ve,be),e[3]=(e[3]||e[4]||e[5]||"").replace(ve,be),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return de.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&ce.test(n)&&(t=$(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(ve,be).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=B[e+" "];return t||(t=new RegExp("(^|"+ee+")"+e+"("+ee+"|$)"))&&B(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ie," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var c,u,d,p,f,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,v=s&&t.nodeName.toLowerCase(),b=!l&&!s,y=!1;if(m){if(o){for(;g;){for(p=t;p=p[g];)if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&b){for(p=m,d=p[R]||(p[R]={}),u=d[p.uniqueID]||(d[p.uniqueID]={}),c=u[e]||[],f=c[0]===U&&c[1],y=f&&c[2],p=f&&m.childNodes[f];p=++f&&p&&p[g]||(y=f=0)||h.pop();)if(1===p.nodeType&&++y&&p===t){u[e]=[U,f,y];break}}else if(b&&(p=t,d=p[R]||(p[R]={}),u=d[p.uniqueID]||(d[p.uniqueID]={}),c=u[e]||[],f=c[0]===U&&c[1],y=f),!1===y)for(;(p=++f&&p&&p[g]||(y=f=0)||h.pop())&&((s?p.nodeName.toLowerCase()!==v:1!==p.nodeType)||!++y||(b&&(d=p[R]||(p[R]={}),u=d[p.uniqueID]||(d[p.uniqueID]={}),u[e]=[U,y]),p!==t)););return(y-=i)===r||y%r==0&&y/r>=0}}},PSEUDO:function(e,n){var i,o=w.pseudos[e]||w.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[R]?o(n):o.length>1?(i=[e,e,"",n],w.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=K(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=C(e.replace(oe,"$1"));return i[R]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(ve,be),function(t){return(t.textContent||t.innerText||k(t)).indexOf(e)>-1}}),lang:r(function(e){return ue.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(ve,be).toLowerCase(),function(t){var n;do{if(n=M?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===O},focus:function(e){return e===L.activeElement&&(!L.hasFocus||L.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:s(!1),disabled:s(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!w.pseudos.empty(e)},header:function(e){return fe.test(e.nodeName)},input:function(e){return pe.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&9===t.nodeType&&M&&w.relative[o[1].type]){if(!(t=(w.find.ID(a.matches[0].replace(ve,be),t)||[])[0]))return n;u&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=de.needsContext.test(e)?0:o.length;i--&&(a=o[i],!w.relative[s=a.type]);)if((l=w.find[s])&&(r=l(a.matches[0].replace(ve,be),me.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&d(o)))return J.apply(n,r),n;break}}return(u||C(e,p))(r,t,!M,n,!t||me.test(e)&&c(t.parentNode)||t),n},x.sortStable=R.split("").sort(q).join("")===R,x.detectDuplicates=!!D,P(),x.sortDetached=i(function(e){return 1&e.compareDocumentPosition(L.createElement("fieldset"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),x.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(Q,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(n);be.find=_e,be.expr=_e.selectors,be.expr[":"]=be.expr.pseudos,be.uniqueSort=be.unique=_e.uniqueSort,be.text=_e.getText,be.isXMLDoc=_e.isXML,be.contains=_e.contains,be.escapeSelector=_e.escape;var $e=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&be(e).is(n))break;r.push(e)}return r},Ce=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},Se=be.expr.match.needsContext,Te=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,Ee=/^.[^:#\[\.,]*$/;be.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?be.find.matchesSelector(r,e)?[r]:[]:be.find.matches(e,be.grep(t,function(e){return 1===e.nodeType}))},be.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(be(e).filter(function(){for(t=0;t1?be.uniqueSort(n):n},filter:function(e){return this.pushStack(c(this,e||[],!1))},not:function(e){return this.pushStack(c(this,e||[],!0))},is:function(e){return!!c(this,"string"==typeof e&&Se.test(e)?be(e):e||[],!1).length}});var De,Pe=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(be.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||De,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:Pe.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof be?t[0]:t,be.merge(this,be.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:ae,!0)),Te.test(r[1])&&be.isPlainObject(t))for(r in t)be.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=ae.getElementById(r[2]),i&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):be.isFunction(e)?void 0!==n.ready?n.ready(e):e(be):be.makeArray(e,this)}).prototype=be.fn,De=be(ae);var Le=/^(?:parents|prev(?:Until|All))/,Oe={children:!0,contents:!0,next:!0,prev:!0};be.fn.extend({has:function(e){var t=be(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&be.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?be.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?de.call(be(e),this[0]):de.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(be.uniqueSort(be.merge(this.get(),be(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),be.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return $e(e,"parentNode")},parentsUntil:function(e,t,n){return $e(e,"parentNode",n)},next:function(e){return u(e,"nextSibling")},prev:function(e){return u(e,"previousSibling")},nextAll:function(e){return $e(e,"nextSibling")},prevAll:function(e){return $e(e,"previousSibling")},nextUntil:function(e,t,n){return $e(e,"nextSibling",n)},prevUntil:function(e,t,n){return $e(e,"previousSibling",n)},siblings:function(e){return Ce((e.parentNode||{}).firstChild,e)},children:function(e){return Ce(e.firstChild)},contents:function(e){return l(e,"iframe")?e.contentDocument:(l(e,"template")&&(e=e.content||e),be.merge([],e.childNodes))}},function(e,t){be.fn[e]=function(n,r){var i=be.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=be.filter(r,i)),this.length>1&&(Oe[e]||be.uniqueSort(i),Le.test(e)&&i.reverse()),this.pushStack(i)}});var Me=/[^\x20\t\r\n\f]+/g;be.Callbacks=function(e){e="string"==typeof e?d(e):be.extend({},e);var t,n,r,i,o=[],a=[],s=-1,l=function(){for(i=i||e.once,r=t=!0;a.length;s=-1)for(n=a.shift();++s-1;)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?be.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],a.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},be.extend({Deferred:function(e){var t=[["notify","progress",be.Callbacks("memory"),be.Callbacks("memory"),2],["resolve","done",be.Callbacks("once memory"),be.Callbacks("once memory"),0,"resolved"],["reject","fail",be.Callbacks("once memory"),be.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},catch:function(e){return i.then(null,e)},pipe:function(){var e=arguments;return be.Deferred(function(n){be.each(t,function(t,r){var i=be.isFunction(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&be.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(e,r,i){function o(e,t,r,i){return function(){var s=this,l=arguments,c=function(){var n,c;if(!(e=a&&(r!==f&&(s=void 0,l=[n]),t.rejectWith(s,l))}};e?u():(be.Deferred.getStackHook&&(u.stackTrace=be.Deferred.getStackHook()),n.setTimeout(u))}}var a=0;return be.Deferred(function(n){t[0][3].add(o(0,n,be.isFunction(i)?i:p,n.notifyWith)),t[1][3].add(o(0,n,be.isFunction(e)?e:p)),t[2][3].add(o(0,n,be.isFunction(r)?r:f))}).promise()},promise:function(e){return null!=e?be.extend(e,i):i}},o={};return be.each(t,function(e,n){var a=n[2],s=n[5];i[n[1]]=a.add,s&&a.add(function(){r=s},t[3-e][2].disable,t[0][2].lock),a.add(n[3].fire),o[n[0]]=function(){return o[n[0]+"With"](this===o?void 0:this,arguments),this},o[n[0]+"With"]=a.fireWith}),i.promise(o),e&&e.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=le.call(arguments),o=be.Deferred(),a=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?le.call(arguments):n,--t||o.resolveWith(r,i)}};if(t<=1&&(h(e,o.done(a(n)).resolve,o.reject,!t),"pending"===o.state()||be.isFunction(i[n]&&i[n].then)))return o.then();for(;n--;)h(i[n],a(n),o.reject);return o.promise()}});var Ae=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;be.Deferred.exceptionHook=function(e,t){n.console&&n.console.warn&&e&&Ae.test(e.name)&&n.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},be.readyException=function(e){n.setTimeout(function(){throw e})};var Fe=be.Deferred();be.fn.ready=function(e){return Fe.then(e).catch(function(e){be.readyException(e)}),this},be.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--be.readyWait:be.isReady)||(be.isReady=!0,!0!==e&&--be.readyWait>0||Fe.resolveWith(ae,[be]))}}),be.ready.then=Fe.then,"complete"===ae.readyState||"loading"!==ae.readyState&&!ae.documentElement.doScroll?n.setTimeout(be.ready):(ae.addEventListener("DOMContentLoaded",g),n.addEventListener("load",g));var Ie=function(e,t,n,r,i,o,a){var s=0,l=e.length,c=null==n;if("object"===be.type(n)){i=!0;for(s in n)Ie(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,be.isFunction(r)||(a=!0),c&&(a?(t.call(e,r),t=null):(c=t,t=function(e,t,n){return c.call(be(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){Ne.remove(this,e)})}}),be.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Re.get(e,t),n&&(!r||Array.isArray(n)?r=Re.access(e,t,be.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=be.queue(e,t),r=n.length,i=n.shift(),o=be._queueHooks(e,t),a=function(){be.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Re.get(e,n)||Re.access(e,n,{empty:be.Callbacks("once memory").add(function(){Re.remove(e,[t+"queue",n])})})}}),be.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,Je=/^$|\/(?:java|ecma)script/i,Xe={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ke=/<|&#?\w+;/;!function(){var e=ae.createDocumentFragment(),t=e.appendChild(ae.createElement("div")),n=ae.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),ve.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",ve.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var Qe=ae.documentElement,et=/^key/,tt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,nt=/^([^.]*)(?:\.(.+)|)/;be.event={global:{},add:function(e,t,n,r,i){var o,a,s,l,c,u,d,p,f,h,g,m=Re.get(e);if(m)for(n.handler&&(o=n,n=o.handler,i=o.selector),i&&be.find.matchesSelector(Qe,i),n.guid||(n.guid=be.guid++),(l=m.events)||(l=m.events={}),(a=m.handle)||(a=m.handle=function(t){return void 0!==be&&be.event.triggered!==t.type?be.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(Me)||[""],c=t.length;c--;)s=nt.exec(t[c])||[],f=g=s[1],h=(s[2]||"").split(".").sort(),f&&(d=be.event.special[f]||{},f=(i?d.delegateType:d.bindType)||f,d=be.event.special[f]||{},u=be.extend({type:f,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&be.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=l[f])||(p=l[f]=[],p.delegateCount=0,d.setup&&!1!==d.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(f,a)),d.add&&(d.add.call(e,u),u.handler.guid||(u.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,u):p.push(u),be.event.global[f]=!0)},remove:function(e,t,n,r,i){var o,a,s,l,c,u,d,p,f,h,g,m=Re.hasData(e)&&Re.get(e);if(m&&(l=m.events)){for(t=(t||"").match(Me)||[""],c=t.length;c--;)if(s=nt.exec(t[c])||[],f=g=s[1],h=(s[2]||"").split(".").sort(),f){for(d=be.event.special[f]||{},f=(r?d.delegateType:d.bindType)||f,p=l[f]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)u=p[o],!i&&g!==u.origType||n&&n.guid!==u.guid||s&&!s.test(u.namespace)||r&&r!==u.selector&&("**"!==r||!u.selector)||(p.splice(o,1),u.selector&&p.delegateCount--,d.remove&&d.remove.call(e,u));a&&!p.length&&(d.teardown&&!1!==d.teardown.call(e,h,m.handle)||be.removeEvent(e,f,m.handle),delete l[f])}else for(f in l)be.event.remove(e,f+t[c],n,r,!0);be.isEmptyObject(l)&&Re.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=be.event.fix(e),l=new Array(arguments.length),c=(Re.get(this,"events")||{})[s.type]||[],u=be.event.special[s.type]||{};for(l[0]=s,t=1;t=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==e.type||!0!==c.disabled)){for(o=[],a={},n=0;n-1:be.find(i,this,null,[c]).length),a[i]&&o.push(r);o.length&&s.push({elem:c,handlers:o})}return c=this,l\x20\t\r\n\f]*)[^>]*)\/>/gi,it=/\s*$/g;be.extend({htmlPrefilter:function(e){return e.replace(rt,"<$1>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),l=be.contains(e.ownerDocument,e);if(!(ve.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||be.isXMLDoc(e)))for(a=k(s),o=k(e),r=0,i=o.length;r0&&_(a,!l&&k(e,"script")),s},cleanData:function(e){for(var t,n,r,i=be.event.special,o=0;void 0!==(n=e[o]);o++)if(je(n)){if(t=n[Re.expando]){if(t.events)for(r in t.events)i[r]?be.event.remove(n,r):be.removeEvent(n,r,t.handle);n[Re.expando]=void 0}n[Ne.expando]&&(n[Ne.expando]=void 0)}}}),be.fn.extend({detach:function(e){return F(this,e,!0)},remove:function(e){return F(this,e)},text:function(e){return Ie(this,function(e){return void 0===e?be.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return A(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){D(this,e).appendChild(e)}})},prepend:function(){return A(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=D(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return A(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return A(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(be.cleanData(k(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return be.clone(this,e,t)})},html:function(e){return Ie(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!Xe[(Ye.exec(e)||["",""])[1].toLowerCase()]){e=be.htmlPrefilter(e);try{for(;n1)}}),be.Tween=H,H.prototype={constructor:H,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||be.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(be.cssNumber[n]?"":"px")},cur:function(){var e=H.propHooks[this.prop];return e&&e.get?e.get(this):H.propHooks._default.get(this)},run:function(e){var t,n=H.propHooks[this.prop];return this.options.duration?this.pos=t=be.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):H.propHooks._default.set(this),this}},H.prototype.init.prototype=H.prototype,H.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=be.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){be.fx.step[e.prop]?be.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[be.cssProps[e.prop]]&&!be.cssHooks[e.prop]?e.elem[e.prop]=e.now:be.style(e.elem,e.prop,e.now+e.unit)}}},H.propHooks.scrollTop=H.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},be.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},be.fx=H.prototype.init,be.fx.step={};var vt,bt,yt=/^(?:toggle|show|hide)$/,xt=/queueHooks$/;be.Animation=be.extend(J,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return y(n.elem,e,He.exec(t),n),n}]},tweener:function(e,t){be.isFunction(e)?(t=e,e=["*"]):e=e.match(Me);for(var n,r=0,i=e.length;r1)},removeAttr:function(e){return this.each(function(){be.removeAttr(this,e)})}}),be.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===e.getAttribute?be.prop(e,t,n):(1===o&&be.isXMLDoc(e)||(i=be.attrHooks[t.toLowerCase()]||(be.expr.match.bool.test(t)?wt:void 0)),void 0!==n?null===n?void be.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=be.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!ve.radioValue&&"radio"===t&&l(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(Me);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),wt={set:function(e,t,n){return!1===t?be.removeAttr(e,n):e.setAttribute(n,n),n}},be.each(be.expr.match.bool.source.match(/\w+/g),function(e,t){var n=kt[t]||be.find.attr;kt[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=kt[a],kt[a]=i,i=null!=n(e,t,r)?a:null,kt[a]=o),i}});var _t=/^(?:input|select|textarea|button)$/i,$t=/^(?:a|area)$/i;be.fn.extend({prop:function(e,t){return Ie(this,be.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[be.propFix[e]||e]})}}),be.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&be.isXMLDoc(e)||(t=be.propFix[t]||t,i=be.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=be.find.attr(e,"tabindex");return t?parseInt(t,10):_t.test(e.nodeName)||$t.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),ve.optSelected||(be.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),be.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){be.propFix[this.toLowerCase()]=this}),be.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,l=0;if(be.isFunction(e))return this.each(function(t){be(this).addClass(e.call(this,t,K(this)))});if("string"==typeof e&&e)for(t=e.match(Me)||[];n=this[l++];)if(i=K(n),r=1===n.nodeType&&" "+X(i)+" "){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");s=X(r),i!==s&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,l=0;if(be.isFunction(e))return this.each(function(t){be(this).removeClass(e.call(this,t,K(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(Me)||[];n=this[l++];)if(i=K(n),r=1===n.nodeType&&" "+X(i)+" "){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");s=X(r),i!==s&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):be.isFunction(e)?this.each(function(n){be(this).toggleClass(e.call(this,n,K(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=be(this),o=e.match(Me)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==n||(t=K(this),t&&Re.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":Re.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+X(K(n))+" ").indexOf(t)>-1)return!0;return!1}});var Ct=/\r/g;be.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=be.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,be(this).val()):e,null==i?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=be.map(i,function(e){return null==e?"":e+""})),(t=be.valHooks[this.type]||be.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=be.valHooks[i.type]||be.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(Ct,""):null==n?"":n)}}}),be.extend({valHooks:{option:{get:function(e){var t=be.find.attr(e,"value");return null!=t?t:X(be.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],c=a?o+1:i.length;for(r=o<0?c:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),be.each(["radio","checkbox"],function(){be.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=be.inArray(be(e).val(),t)>-1}},ve.checkOn||(be.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var St=/^(?:focusinfocus|focusoutblur)$/;be.extend(be.event,{trigger:function(e,t,r,i){var o,a,s,l,c,u,d,p=[r||ae],f=he.call(e,"type")?e.type:e,h=he.call(e,"namespace")?e.namespace.split("."):[];if(a=s=r=r||ae,3!==r.nodeType&&8!==r.nodeType&&!St.test(f+be.event.triggered)&&(f.indexOf(".")>-1&&(h=f.split("."),f=h.shift(),h.sort()),c=f.indexOf(":")<0&&"on"+f,e=e[be.expando]?e:new be.Event(f,"object"==typeof e&&e),e.isTrigger=i?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=r),t=null==t?[e]:be.makeArray(t,[e]),d=be.event.special[f]||{},i||!d.trigger||!1!==d.trigger.apply(r,t))){if(!i&&!d.noBubble&&!be.isWindow(r)){for(l=d.delegateType||f,St.test(l+f)||(a=a.parentNode);a;a=a.parentNode)p.push(a),s=a;s===(r.ownerDocument||ae)&&p.push(s.defaultView||s.parentWindow||n)}for(o=0;(a=p[o++])&&!e.isPropagationStopped();)e.type=o>1?l:d.bindType||f,u=(Re.get(a,"events")||{})[e.type]&&Re.get(a,"handle"),u&&u.apply(a,t),(u=c&&a[c])&&u.apply&&je(a)&&(e.result=u.apply(a,t),!1===e.result&&e.preventDefault());return e.type=f,i||e.isDefaultPrevented()||d._default&&!1!==d._default.apply(p.pop(),t)||!je(r)||c&&be.isFunction(r[f])&&!be.isWindow(r)&&(s=r[c],s&&(r[c]=null),be.event.triggered=f,r[f](),be.event.triggered=void 0,s&&(r[c]=s)),e.result}},simulate:function(e,t,n){var r=be.extend(new be.Event,n,{type:e,isSimulated:!0});be.event.trigger(r,null,t)}}),be.fn.extend({trigger:function(e,t){return this.each(function(){be.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return be.event.trigger(e,t,n,!0)}}),be.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){be.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),be.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),ve.focusin="onfocusin"in n,ve.focusin||be.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){be.event.simulate(t,e.target,be.event.fix(e))};be.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=Re.access(r,t);i||r.addEventListener(e,n,!0),Re.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=Re.access(r,t)-1;i?Re.access(r,t,i):(r.removeEventListener(e,n,!0),Re.remove(r,t))}}});var Tt=n.location,Et=be.now(),Dt=/\?/;be.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new n.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||be.error("Invalid XML: "+e),t};var Pt=/\[\]$/,Lt=/\r?\n/g,Ot=/^(?:submit|button|image|reset|file)$/i,Mt=/^(?:input|select|textarea|keygen)/i;be.param=function(e,t){var n,r=[],i=function(e,t){var n=be.isFunction(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!be.isPlainObject(e))be.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join("&")},be.fn.extend({serialize:function(){return be.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=be.prop(this,"elements");return e?be.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!be(this).is(":disabled")&&Mt.test(this.nodeName)&&!Ot.test(e)&&(this.checked||!Ze.test(e))}).map(function(e,t){var n=be(this).val();return null==n?null:Array.isArray(n)?be.map(n,function(e){return{name:t.name,value:e.replace(Lt,"\r\n")}}):{name:t.name,value:n.replace(Lt,"\r\n")}}).get()}});var At=/%20/g,Ft=/#.*$/,It=/([?&])_=[^&]*/,jt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nt=/^(?:GET|HEAD)$/,Ut=/^\/\//,zt={},Bt={},Ht="*/".concat("*"),Vt=ae.createElement("a");Vt.href=Tt.href,be.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:Rt.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Ht,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":be.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?ne(ne(e,be.ajaxSettings),t):ne(be.ajaxSettings,e)},ajaxPrefilter:ee(zt),ajaxTransport:ee(Bt),ajax:function(e,t){function r(e,t,r,s){var c,p,f,x,w,k=t;u||(u=!0,l&&n.clearTimeout(l),i=void 0,a=s||"",_.readyState=e>0?4:0,c=e>=200&&e<300||304===e,r&&(x=re(h,_,r)),x=ie(h,x,_,c),c?(h.ifModified&&(w=_.getResponseHeader("Last-Modified"),w&&(be.lastModified[o]=w),(w=_.getResponseHeader("etag"))&&(be.etag[o]=w)),204===e||"HEAD"===h.type?k="nocontent":304===e?k="notmodified":(k=x.state,p=x.data,f=x.error,c=!f)):(f=k,!e&&k||(k="error",e<0&&(e=0))),_.status=e,_.statusText=(t||k)+"",c?v.resolveWith(g,[p,k,_]):v.rejectWith(g,[_,k,f]),_.statusCode(y),y=void 0,d&&m.trigger(c?"ajaxSuccess":"ajaxError",[_,h,c?p:f]),b.fireWith(g,[_,k]),d&&(m.trigger("ajaxComplete",[_,h]),--be.active||be.event.trigger("ajaxStop")))}"object"==typeof e&&(t=e,e=void 0),t=t||{};var i,o,a,s,l,c,u,d,p,f,h=be.ajaxSetup({},t),g=h.context||h,m=h.context&&(g.nodeType||g.jquery)?be(g):be.event,v=be.Deferred(),b=be.Callbacks("once memory"),y=h.statusCode||{},x={},w={},k="canceled",_={readyState:0,getResponseHeader:function(e){var t;if(u){if(!s)for(s={};t=jt.exec(a);)s[t[1].toLowerCase()]=t[2];t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return u?a:null},setRequestHeader:function(e,t){return null==u&&(e=w[e.toLowerCase()]=w[e.toLowerCase()]||e,x[e]=t),this},overrideMimeType:function(e){return null==u&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(u)_.always(e[_.status]);else for(t in e)y[t]=[y[t],e[t]];return this},abort:function(e){var t=e||k;return i&&i.abort(t),r(0,t),this}};if(v.promise(_),h.url=((e||h.url||Tt.href)+"").replace(Ut,Tt.protocol+"//"),h.type=t.method||t.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(Me)||[""],null==h.crossDomain){c=ae.createElement("a");try{c.href=h.url,c.href=c.href,h.crossDomain=Vt.protocol+"//"+Vt.host!=c.protocol+"//"+c.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=be.param(h.data,h.traditional)),te(zt,h,t,_),u)return _;d=be.event&&h.global,d&&0==be.active++&&be.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Nt.test(h.type),o=h.url.replace(Ft,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(At,"+")):(f=h.url.slice(o.length),h.data&&(o+=(Dt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(It,"$1"),f=(Dt.test(o)?"&":"?")+"_="+Et+++f),h.url=o+f),h.ifModified&&(be.lastModified[o]&&_.setRequestHeader("If-Modified-Since",be.lastModified[o]),be.etag[o]&&_.setRequestHeader("If-None-Match",be.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||t.contentType)&&_.setRequestHeader("Content-Type",h.contentType),_.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+Ht+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)_.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,_,h)||u))return _.abort();if(k="abort",b.add(h.complete),_.done(h.success),_.fail(h.error),i=te(Bt,h,t,_)){if(_.readyState=1,d&&m.trigger("ajaxSend",[_,h]),u)return _;h.async&&h.timeout>0&&(l=n.setTimeout(function(){_.abort("timeout")},h.timeout));try{u=!1,i.send(x,r)}catch(e){if(u)throw e;r(-1,e)}}else r(-1,"No Transport");return _},getJSON:function(e,t,n){return be.get(e,t,n,"json")},getScript:function(e,t){return be.get(e,void 0,t,"script")}}),be.each(["get","post"],function(e,t){be[t]=function(e,n,r,i){return be.isFunction(n)&&(i=i||r,r=n,n=void 0),be.ajax(be.extend({url:e,type:t,dataType:i,data:n,success:r},be.isPlainObject(e)&&e))}}),be._evalUrl=function(e){return be.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,throws:!0})},be.fn.extend({wrapAll:function(e){var t;return this[0]&&(be.isFunction(e)&&(e=e.call(this[0])),t=be(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return be.isFunction(e)?this.each(function(t){be(this).wrapInner(e.call(this,t))}):this.each(function(){var t=be(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=be.isFunction(e);return this.each(function(n){be(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){be(this).replaceWith(this.childNodes)}),this}}),be.expr.pseudos.hidden=function(e){return!be.expr.pseudos.visible(e)},be.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},be.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(e){}};var qt={0:200,1223:204},Wt=be.ajaxSettings.xhr();ve.cors=!!Wt&&"withCredentials"in Wt,ve.ajax=Wt=!!Wt,be.ajaxTransport(function(e){var t,r;if(ve.cors||Wt&&!e.crossDomain)return{send:function(i,o){var a,s=e.xhr();if(s.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(a in e.xhrFields)s[a]=e.xhrFields[a];e.mimeType&&s.overrideMimeType&&s.overrideMimeType(e.mimeType),e.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);t=function(e){return function(){t&&(t=r=s.onload=s.onerror=s.onabort=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(qt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=t(),r=s.onerror=t("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&n.setTimeout(function(){t&&r()})},t=t("abort");try{s.send(e.hasContent&&e.data||null)}catch(e){if(t)throw e}},abort:function(){t&&t()}}}),be.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),be.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return be.globalEval(e),e}}}),be.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),be.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,i){t=be(" + + + + + + + + + +
+ + {{row[column.field] | date : 'dd.MM.yy HH:mm'}} + + + {{row[column.field]}} + +
+ \ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/templates.json b/webapp/src/main/webapp/static/client/helgoland/templates/templates.json new file mode 100644 index 0000000000..8d47b489a8 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/templates.json @@ -0,0 +1,51 @@ +{ + "n52.core.diagram.reload-button": "templates/diagram/reload-button.html", + "n52.core.diagram.refresh-time": "templates/diagram/refresh-time.html", + "n52.core.diagram.y-axis-hide-button": "templates/diagram/y-axis-hide-button.html", + "n52.core.favoriteUi.favorite-edit-label-modal": "templates/favorite/favorite-edit-label-modal.html", + "n52.core.favoriteUi.favorite-star": "templates/favorite/favorite-star.html", + "n52.core.favoriteUi.favorite-add-group": "templates/favorite/favorite-add-group.html", + "n52.core.favoriteUi.favorite-import-button": "templates/favorite/favorite-import-button.html", + "n52.core.favoriteUi.favorite-export-button": "templates/favorite/favorite-export-button.html", + "n52.core.favoriteUi.favorite-list": "templates/favorite/favorite-list.html", + "n52.core.ie9.import-export": "templates/ie9/import-export.html", + "n52.core.legend.legend": "templates/legend/legend.html", + "n52.core.legend.legend-entry": "templates/legend/legend-entry.html", + "n52.core.legend.label-mapper": "templates/legend/label-mapper.html", + "n52.core.legend.geometry-map-viewer": "templates/legend/geometry-map-viewer.html", + "n52.core.listSelection.list-selection": "templates/listSelection/list-selection.html", + "n52.core.listSelection.modal-list-selection": "templates/listSelection/modal-list-selection.html", + "n52.core.listSelection.tabbed-list-selection": "templates/listSelection/tabbed-list-selection.html", + "n52.core.dataLoading.data-loading": "templates/loading/data-loading.html", + "n52.core.map.station-loading": "templates/map/station-loading.html", + "n52.core.map.selectable-station-entry": "templates/map/selectable-station-entry.html", + "n52.core.map.station": "templates/map/station.html", + "n52.core.map.locate-station": "templates/map/locateStation.html", + "n52.core.map.stationary-insitu": "templates/map/stationary-insitu.html", + "n52.core.metadata.timeseries-rawdata": "templates/metadata/timeseries-rawdata.html", + "n52.core.metadata.sos-url": "templates/metadata/sos-url.html", + "n52.core.metadata.procedure-rawdata": "templates/metadata/procedure/rawdata.html", + "n52.core.metadata.procedure-button": "templates/metadata/procedure/button.html", + "n52.core.metadata.procedure-modal": "templates/metadata/procedure/modal.html", + "n52.core.provider.add-provider": "templates/provider/add-provider.html", + "n52.core.userSettings.settings-toggle-button": "templates/settings/settings-toggle-button.html", + "n52.core.userSettings.qr-code-button": "templates/settings/qr-code-button.html", + "n52.core.userSettings.user-settings-modal": "templates/settings/user-settings-modal.html", + "n52.core.translate.language-selector": "templates/language/language-selector.html", + "n52.core.style.modal-style-editor": "templates/styling/modal-style-editor.html", + "n52.core.style.zero-based-axis-toggler": "templates/styling/zero-based-axis-toggler.html", + "n52.core.style.group-axis-toggler": "templates/styling/group-axis-toggler.html", + "n52.core.style.bar-toggler": "templates/styling/bar-toggler.html", + "n52.core.style.color-chooser": "templates/styling/color-chooser.html", + "n52.core.timeUi.time-selector-buttons": "templates/time/time-selector-buttons.html", + "n52.core.timeUi.time-range-modal": "templates/time/time-range-modal.html", + "n52.core.timeUi.predefined-time-range-button": "templates/time/predefined-time-range-button.html", + "n52.core.timeUi.custom-time-range-selection": "templates/time/custom-time-range-selection.html", + "n52.core.series.list-selection": "templates/series/list-selection.html", + "n52.core.selection.multi-service-filter-selector": "templates/selection/multi-service-filter-selector.html", + "n52.core.permalink.button": "templates/permalink/permalink-button.html", + "n52.core.permalink.simple-modal": "templates/permalink/simple-modal.html", + "n52.core.permalink.in-mail": "templates/permalink/in-mail.html", + "n52.core.permalink.new-window": "templates/permalink/new-window.html", + "n52.core.permalink.to-clipboard": "templates/permalink/to-clipboard.html" +} diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/time/custom-time-range-selection.html b/webapp/src/main/webapp/static/client/helgoland/templates/time/custom-time-range-selection.html new file mode 100644 index 0000000000..a40e27c3fc --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/time/custom-time-range-selection.html @@ -0,0 +1,13 @@ +
+ + +
+ +
+ + +
+ +
+ \ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/time/predefined-time-range-button.html b/webapp/src/main/webapp/static/client/helgoland/templates/time/predefined-time-range-button.html new file mode 100644 index 0000000000..8b6fde4efa --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/time/predefined-time-range-button.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/time/time-range-modal.html b/webapp/src/main/webapp/static/client/helgoland/templates/time/time-range-modal.html new file mode 100644 index 0000000000..2042561fcc --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/time/time-range-modal.html @@ -0,0 +1,43 @@ + \ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/time/time-selector-buttons.html b/webapp/src/main/webapp/static/client/helgoland/templates/time/time-selector-buttons.html new file mode 100644 index 0000000000..ddaf10ed65 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/time/time-selector-buttons.html @@ -0,0 +1,11 @@ +
+ + + +
\ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/views/diagramView.html b/webapp/src/main/webapp/static/client/helgoland/templates/views/diagramView.html new file mode 100644 index 0000000000..4880ce33d4 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/views/diagramView.html @@ -0,0 +1,61 @@ +
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + + + + + +
+
+
+
+

+ +
+ +
+
+
diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/views/favoriteView.html b/webapp/src/main/webapp/static/client/helgoland/templates/views/favoriteView.html new file mode 100644 index 0000000000..4e529ee2f4 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/views/favoriteView.html @@ -0,0 +1,10 @@ +
+
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/webapp/src/main/webapp/static/client/helgoland/templates/views/mapView.html b/webapp/src/main/webapp/static/client/helgoland/templates/views/mapView.html new file mode 100644 index 0000000000..3607be3582 --- /dev/null +++ b/webapp/src/main/webapp/static/client/helgoland/templates/views/mapView.html @@ -0,0 +1,59 @@ +
+
+
+
+
+ + +
+
+ + +
+ + +
+
+
+
+
+
+
+ +
+
+
+
+
diff --git a/webapp/src/main/webapp/static/conf/client-config.json b/webapp/src/main/webapp/static/conf/client-config.json index 8a761df1d0..50bd68eba6 100644 --- a/webapp/src/main/webapp/static/conf/client-config.json +++ b/webapp/src/main/webapp/static/conf/client-config.json @@ -4652,8 +4652,8 @@ "geometry":{ "type":"Point", "coordinates":[ - 51.883906, - 7.727958 + 51.9690871, + 7.5935498 ], "crs":{ "type":"name", diff --git a/webapp/src/main/webapp/version-info.txt b/webapp/src/main/webapp/version-info.txt index bf0ba9fa77..ad5b68ed9d 100644 --- a/webapp/src/main/webapp/version-info.txt +++ b/webapp/src/main/webapp/version-info.txt @@ -6,7 +6,7 @@ builddate = ${git.build.time} Subversion Infos: ================= -repository = ${git.repository} +repository = ${git.remote.origin.url} path = ${git.branch} revision = ${git.commit.id} lastCommitMessage = ${git.commit.message.short}