/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* 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
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.catalog.pubsub.predicate;
import java.util.Iterator;
import java.util.Map;
import org.geotools.geometry.jts.WKTReader2;
import org.osgi.service.event.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import ddf.catalog.data.Metacard;
import ddf.catalog.pubsub.criteria.geospatial.GeospatialEvaluationCriteria;
import ddf.catalog.pubsub.criteria.geospatial.GeospatialEvaluationCriteriaImpl;
import ddf.catalog.pubsub.criteria.geospatial.GeospatialEvaluator;
import ddf.catalog.pubsub.internal.PubSubConstants;
public class GeospatialPredicate implements Predicate {
private static final Logger LOGGER = LoggerFactory.getLogger(GeospatialPredicate.class);
private Geometry geoCriteria;
private String geoOperation;
private double distance;
/**
* Instantiates a new geospatial predicate.
*
* @param wkt
* A string of well known text.
* @param geoOperation
* the geo operation
*/
public GeospatialPredicate(String wkt, String geoOperation, double distance) {
this.geoOperation = geoOperation;
this.distance = distance;
try {
WKTReader2 wktreader = new WKTReader2();
this.geoCriteria = wktreader.read(wkt);
} catch (Exception e) {
LOGGER.debug("Exception reading WKT", e);
}
}
public GeospatialPredicate(Geometry geo, String geoOperation, double distance) {
this.geoOperation = geoOperation;
this.distance = distance;
this.geoCriteria = geo;
}
public static boolean isGeospatial(Map geoCriteria, String geoOperation) {
Iterator it = geoCriteria.values()
.iterator();
boolean hasCriteria = false;
while (it.hasNext()) {
Object item = it.next();
if (item != null && !item.toString()
.equals("")) {
hasCriteria = true;
}
}
return hasCriteria && !geoCriteria.isEmpty();
}
public boolean matches(Event properties) {
Metacard entry = (Metacard) properties.getProperty(PubSubConstants.HEADER_ENTRY_KEY);
Map<String, Object> contextualMap = (Map<String, Object>) properties.getProperty(
PubSubConstants.HEADER_CONTEXTUAL_KEY);
String operation = (String) properties.getProperty(PubSubConstants.HEADER_OPERATION_KEY);
LOGGER.debug("operation = {}", operation);
if (contextualMap != null) {
String metadata = (String) contextualMap.get("METADATA");
// If deleting a catalog entry and the entry's location data is NULL is only the word
// "deleted" (i.e., the
// source is deleting the catalog entry and did not send any location data with the
// delete event), then
// cannot apply any geospatial filtering - just send the event on to the subscriber
if (PubSubConstants.DELETE.equals(operation) && PubSubConstants.METADATA_DELETED.equals(
metadata)) {
LOGGER.debug(
"Detected a DELETE operation where metadata is just the word 'deleted', so send event on to subscriber");
return true;
}
}
GeospatialEvaluationCriteria gec;
try {
gec = new GeospatialEvaluationCriteriaImpl(geoCriteria,
geoOperation,
entry.getLocation(),
distance);
return GeospatialEvaluator.evaluate(gec);
} catch (ParseException e) {
LOGGER.debug("Error parsing WKT string. Unable to compare geos. Returning false.");
return false;
}
}
public Geometry getGeoCriteria() {
return geoCriteria;
}
public String getGeoOperation() {
return geoOperation;
}
public double getDistance() {
return distance;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("\tgeoCriteria = " + geoCriteria + "\n");
sb.append("\tgeoOperation = " + geoOperation + "\n");
sb.append("\tdistance = " + distance + "\n");
return sb.toString();
}
}