/* (c) 2017 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.opensearch.eo; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import org.geoserver.opensearch.eo.store.OpenSearchAccess; import org.geotools.data.Parameter; import org.geotools.feature.NameImpl; import org.geotools.referencing.CRS; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.PropertyName; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; /** * Container/provider for common OpenSearch parameters. Parameter keys are used as the Kvp keys in URLs, * an optional prefix associates them to a namespace, an optional name can be used to build the fully * qualified name of the parameter, otherwise the key will be used (the difference between the two * is used to resolve some conflicts like "relation" used by both time and geo namespaces): * * @author Andrea Aime - GeoSolutions */ public class OpenSearchParameters { public static final CoordinateReferenceSystem OUTPUT_CRS; public static enum GeometryRelation { intersects, disjoint, contains } /** * Possible relationships between data time validity and query one * * @author Andrea Aime - GeoSolutions */ public static enum DateRelation { intersects, contains, during, disjoint, equals }; public static final String OS_PREFIX = "os"; public static final String TIME_PREFIX = "time"; public static final Parameter<?> TIME_END = new ParameterBuilder("timeEnd", Date.class) .prefix(TIME_PREFIX).name("end").build(); public static final Parameter<?> TIME_START = new ParameterBuilder("timeStart", Date.class) .prefix(TIME_PREFIX).name("start").build(); public static final Parameter<?> TIME_RELATION = new ParameterBuilder("timeRelation", DateRelation.class).prefix(TIME_PREFIX).name("relation").build(); public static final String GEO_PREFIX = "geo"; public static final Parameter<?> GEO_RADIUS = new ParameterBuilder("radius", Double.class) .prefix(GEO_PREFIX).minimumInclusive(0).build(); public static final Parameter<?> GEO_RELATION = new ParameterBuilder("geoRelation", DateRelation.class).prefix(GEO_PREFIX).name("relation").build(); public static final Parameter<?> GEO_GEOMETRY = new ParameterBuilder("geometry", Geometry.class) .prefix(GEO_PREFIX).build(); public static final Parameter<?> GEO_LON = new ParameterBuilder("lon", Double.class) .prefix(GEO_PREFIX).minimumInclusive(-180).maximumInclusive(180).build(); public static final Parameter<?> GEO_LAT = new ParameterBuilder("lat", Double.class) .prefix(GEO_PREFIX).minimumInclusive(-90).maximumInclusive(90).build(); public static final Parameter<?> GEO_NAME = new ParameterBuilder("name", String.class) .prefix(GEO_PREFIX).build(); public static final String EO_PREFIX = "eo"; public static final Parameter<?> SEARCH_TERMS = new ParameterBuilder("searchTerms", String.class).prefix(OS_PREFIX).build(); public static final Parameter<?> START_INDEX = new ParameterBuilder("startIndex", Integer.class) .prefix(OS_PREFIX).build(); public static final Parameter<?> GEO_UID = new ParameterBuilder("uid", String.class) .prefix(GEO_PREFIX).build(); public static final Parameter<?> GEO_BOX = new ParameterBuilder("box", Envelope.class) .prefix(GEO_PREFIX).build(); public static final String PARAM_PREFIX = "parameterPrefix"; /** * Name of the parameter in the URLs, if missing it's the same as key */ public static final String PARAM_NAME = "parameterName"; public static final String MIN_INCLUSIVE = "minInclusive"; public static final String MAX_INCLUSIVE = "maxInclusive"; private static final List<Parameter<?>> BASIC_OPENSEARCH; private static final List<Parameter<?>> GEO_TIME_OPENSEARCH; static { BASIC_OPENSEARCH = basicOpenSearchParameters(); GEO_TIME_OPENSEARCH = geoTimeOpenSearchParameters(); try { OUTPUT_CRS = CRS.decode("urn:ogc:def:crs:EPSG:4326", false); } catch (FactoryException e) { throw new RuntimeException("Unepected error decoding wgs84 in lat/lon order", e); } } private static List<Parameter<?>> basicOpenSearchParameters() { return Arrays.asList( // SEARCH_TERMS, START_INDEX); } private static List<Parameter<?>> geoTimeOpenSearchParameters() { return Arrays.asList( // GEO_UID, GEO_BOX, GEO_NAME, GEO_LAT, GEO_LON, GEO_RADIUS, GEO_GEOMETRY, GEO_RELATION, TIME_START, TIME_END, TIME_RELATION); } /** * Returns the basic OpenSearch search parameters * * @return */ public static List<Parameter<?>> getBasicOpensearch(OSEOInfo info) { List<Parameter<?>> result = new ArrayList<>(BASIC_OPENSEARCH); ParameterBuilder count = new ParameterBuilder("count", Integer.class).prefix(OS_PREFIX); count.minimumInclusive(0); if (info.getMaximumRecordsPerPage() > 0) { count.maximumInclusive(info.getMaximumRecordsPerPage()); } result.add(count.build()); return result; } /** * Returns the OGC geo/time extension parameters * * @return */ public static List<Parameter<?>> getGeoTimeOpensearch() { return GEO_TIME_OPENSEARCH; } /** * Returns the qualified name of a parameter, in case the parameter has a PARAM_PREFIX among its metadata, or the simple parameter key other * * @param p * @return */ public static String getQualifiedParamName(Parameter p) { return getQualifiedParamName(p, true); } /** * Returns the qualified name of a parameter, in case the parameter has a PARAM_PREFIX among its metadata, or the simple parameter key other * * @param p * @return */ public static String getQualifiedParamName(Parameter p, boolean qualifyOpenSearchNative) { String name = getParameterName(p); String prefix = getParameterPrefix(p); if (prefix != null && (!OS_PREFIX.equals(prefix) || qualifyOpenSearchNative)) { return prefix + ":" + name; } else { return name; } } /** * Returns the PARAM_PREFIX entry found in the parameter metadata, if any * * @param p * @return */ public static String getParameterPrefix(Parameter p) { String prefix = p.metadata == null ? null : (String) p.metadata.get(PARAM_PREFIX); return prefix; } /** * Returns the PARAM_NAME entry found in the parameter metadata, if any, or the key otherwise * * @param p * @return */ public static String getParameterName(Parameter p) { String name = p.metadata == null ? null : (String) p.metadata.get(PARAM_NAME); if(name == null) { name = p.key; } return name; } /** * Builds the {@link PropertyName} for the given OpenSearch parameter * * @param parameter * @return */ public static PropertyName getFilterPropertyFor(FilterFactory2 ff, Parameter<?> parameter) { String prefix = getParameterPrefix(parameter); String namespace = null; if(EO_PREFIX.equals(prefix)) { namespace = OpenSearchAccess.EO_NAMESPACE; } else { // product parameter maybe? for (OpenSearchAccess.ProductClass pc : OpenSearchAccess.ProductClass.values()) { if (pc.getPrefix().equals(prefix)) { namespace = pc.getNamespace(); } } } // the name String name = getParameterName(parameter); return ff.property(new NameImpl(namespace, name)); } }