Creating Filters
Overview
An OGC Filter is a Open Geospatial Consortium (OGC) standard that describes a query expression in terms of Extensible Markup Language (XML) and key-value pairs (KVP). The DDF Catalog Framework does not use the XML representation of the OGC Filter standard.
DDF
instead utilizes the Java implementation provided by Geotools. Geotools provides Java equivalent classes for OGC Filter XML elements. Geotools originally provided the standard Java classes for the OGC Filter Encoding 1.0 under the package nameorg.opengis.filter
. The same package name is used today and is currently used by DDF
. Java developers do not parse or view the XML representation of aFilter
in DDF
. Developers instead solely use the Java objects to complete query tasks.Note that the ddf.catalog.operation.Query
interface extends the org.opengis.filter.Filter
interface, which means that a Query object is an OGC Java Filter
with Query Options.
public interface Query extends Filter
Usage
FilterBuilder API
To abstract developers from the complexities of working with the Filter interface directly and implementing the DDF Profile of the Filter specification, the DDF Catalog includes an API, primarily in ddf.filter, to build Filters using a fluent API.
To use the FilterBuilder API, an instance of ddf.filter.FilterBuilder should be used via the OSGi registry. Typically this will be injected via a dependency injection framework. Once an instance of FilterBuilder is available, methods can be called to create and combine Filters.
The fluent API is best accessed using an IDE that supports code-completion. For additional details, refer to the Catalog API Javadoc.
Boolean Operators
FilterBuilder.allOf(Filter ...)
creates a new Filter that requires all provided Filters are satisfied (Boolean AND), either from a List or Array of Filter instances.
FilterBuilder.anyOf(Filter ...)
creates a new Filter that requires all provided Filters are satisfied (Boolean OR), either from a List or Array of Filter instances.
FilterBuilder.not(Filter filter)
creates a new Filter that requires the provided Filter must not be match (Boolean NOT).
Attribute
FilterBuilder.attribute(String attributeName)
begins a fluent API for creating an Attribute-based Filter, i.e., a Filter that matches on Metacards with Attributes of a particular value.
XPath
FilterBuilder.xpath(String xpath)
begins a fluent API for creating an XPath-based Filter, i.e., a Filter that matches on Metacards with Attributes of type XML that match when evaluating a provided XPath selector.
Contextual Operators
FilterBuilder.attribute(attributeName).is().like().text(String contextualSearchPhrase); FilterBuilder.attribute(attributeName).is().like().caseSensitiveText(String caseSensitiveContextualSearchPhrase); FilterBuilder.attribute(attributeName).is().like().fuzzyText(String fuzzySearchPhrase);
Directly implementing the Filter (advanced)
Implementing the Filter interface directly is only for extremely advanced use cases and is highly discouraged. Instead, use of the DDF-specific FilterBuilder API is recommended.
Developers create a Filter
object in order to "filter" or constrain the amount of records returned from a Source
. The OGC Filter Specification has several types of filters that can be combined in a tree-like structure to describe the set of metacards that should be returned.
Categories of Filters
- Comparison Operators
- Logical Operators
- Expressions
- Literals
- Functions
- Spatial Operators
- Temporal Operators
Units of Measure
According to the OGC Filter Specifications 09-026r1 and 04-095, units of measure can be expressed as a URI. In order to fulfill that requirement,
DDF
utilizes the Geotools classorg.geotools.styling.
UomOgcMapping
for spatial filters requiring a standard for units of measure for scalar distances. The UomOgcMapping
essentially maps the OGC Symbology Encoding standard URI's to Java Units. This class provides three options for units of measure: - FOOT
- METRE
- PIXEL
DDF
only supports FOOT and METRE since they are the most applicable to scalar distances.Creation
The common way to create a Filter
is to use the Geotools FilterFactoryImpl
object which provides Java implementations for the various types of filters in the Filter Specification. Examples are the easiest way to understand how to properly create a Filter
and a Query
.
Refer to the Geotools javadoc for more information on FilterFactoryImpl
.
The example below illustrates creating a query, and thus an OGC Filter, that does a case-insensitive search for the phrase "mission" in the entire Metacard's text. Note that the PropertyIsLike
OGC Filter is used for this simple contextual query.
Example Creating-Filters-1
org.opengis.filter.FilterFactory filterFactory = new FilterFactoryImpl() ; boolean isCaseSensitive = false ; String wildcardChar = "*" ; // used to match zero or more characters String singleChar = "?" ; // used to match exactly one character String escapeChar = "\\" ; // used to escape the meaning of the wildCard, singleChar, and the escapeChar itself String searchPhrase = "mission" ; org.opengis.filter.Filter propertyIsLikeFilter = filterFactory.like(filterFactory.property(Metacard.ANY_TEXT), searchPhrase, wildcardChar, singleChar, escapeChar, isCaseSensitive); ddf.catalog.operation.QueryImpl query = new QueryImpl( propertyIsLikeFilter );
The example below illustrates creating an absolute temporal query, meaning the query is searching for Metacards whose modified timestamp occurred during a specific time range. Note that this query uses the During
OGC Filter for an absolute temporal query.
Example Creating-Filters-2
org.opengis.filter.FilterFactory filterFactory = new FilterFactoryImpl() ; org.opengis.temporal.Instant startInstant = new org.geotools.temporal.object.DefaultInstant(new DefaultPosition(start)); org.opengis.temporal.Instant endInstant = new org.geotools.temporal.object.DefaultInstant(new DefaultPosition(end)); org.opengis.temporal.Period period = new org.geotools.temporal.object.DefaultPeriod(startInstant, endInstant); String property = Metacard.MODIFIED ; // modified date of a metacard org.opengis.filter.Filter filter = filterFactory.during( filterFactory.property(property), filterFactory.literal(period) ); ddf.catalog.operation.QueryImpl query = new QueryImpl(filter) ;
Contextual Searches
Most contextual searches can be expressed using the PropertyIsLike
Filter. The special characters that have meaning in a PropertyIsLike
Filter are the wildcard, single wildcard, and escape characters (see Example Creating-Filters-1).
PropertyIsLike Special Characters
Character | Description |
---|---|
Wildcard | Matches zero or more characters. |
Single Wildcard | Matches exactly one character. |
Escape | Escapes the meaning of the Wildcard, Single Wildcard, and the Escape character itself |
Characters and words such as AND
, &
, and
, OR
, |
, or
, NOT
, ~
, not
, {
, and }
are treated as literals in a PropertyIsLike
Filter. In order to create equivalent logical queries, a developer must instead use the Logical Operator Filters {AND, OR, NOT}. The Logical Operator filters can be combined together with PropertyIsLike
filters to create a tree that represents the search phrase expression.
Example Creating-Filters-3
org.opengis.filter.FilterFactory filterFactory = new FilterFactoryImpl() ; boolean isCaseSensitive = false ; String wildcardChar = "*" ; // used to match zero or more characters String singleChar = "?" ; // used to match exactly one character String escapeChar = "\\" ; // used to escape the meaning of the wildCard, singleChar, and the escapeChar itself Filter filter = filterFactory.and( filterFactory.like(filterFactory.property(Metacard.METADATA), "mission" , wildcardChar, singleChar, escapeChar, isCaseSensitive), filterFactory.like(filterFactory.property(Metacard.METADATA), "planning" , wildcardChar, singleChar, escapeChar, isCaseSensitive) ); ddf.catalog.operation.QueryImpl query = new QueryImpl( filter );
Tree View of Example Creating-Filters-3
Filters used in
DDF
can always be represented in a tree diagram.XML View of Example Creating-Filters-3
Another way to view this type of Filter is through an XML model as below:
<Filter> <And> <PropertyIsLike wildCard="*" singleChar="?" escapeChar="\"> <PropertyName>metadata</PropertyName> <Literal>mission</Literal> </PropertyIsLike> <PropertyIsLike wildCard="*" singleChar="?" escapeChar="\"> <PropertyName>metadata</PropertyName> <Literal>planning</Literal> </PropertyIsLike> <And> </Filter>
Using the Logical Operators and PropertyIsLike
Filters, a developer can create a whole language of search phrase expressions.
Fuzzy Operation
DDF
only supports one custom function. The Filter specification does not include a fuzzy operator, so a Filter function was created to represent a fuzzy operation. The function and class is calledFuzzyFunction
which is used by clients to flag to Sources when to do a fuzzy search. The syntax expected by providers is similar to the Fuzzy Function. Usage example below.String wildcardChar = "*" ; // used to match zero or more characters String singleChar = "?" ; // used to match exactly one character String escapeChar = "\\" ; // used to escape the meaning of the wildCard, singleChar boolean isCaseSensitive = false ; Filter fuzzyFilter = filterFactory.like( new ddf.catalog.impl.filter.FuzzyFunction( Arrays.asList((Expression) (filterFactory.property(Metacard.ANY_TEXT))), filterFactory.literal("")), searchPhrase, wildcardChar, singleChar, escapeChar, isCaseSensitive); QueryImpl query = new QueryImpl(fuzzyFilter);