/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.widget.searchandfilter.client.util;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.geomajas.command.dto.SearchByLocationRequest;
import org.geomajas.gwt.client.map.MapModel;
import org.geomajas.gwt.client.map.layer.VectorLayer;
import org.geomajas.gwt.client.util.GeometryConverter;
import org.geomajas.gwt.client.widget.MapWidget;
import org.geomajas.widget.searchandfilter.search.dto.AndCriterion;
import org.geomajas.widget.searchandfilter.search.dto.AttributeCriterion;
import org.geomajas.widget.searchandfilter.search.dto.Criterion;
import org.geomajas.widget.searchandfilter.search.dto.GeometryCriterion;
import org.geomajas.widget.searchandfilter.search.dto.OrCriterion;
import com.google.gwt.core.client.GWT;
/**
* @author Kristof Heirwegh
*/
public final class CriterionUtils {
private static final List<Criterion> ACTIVELAYERFILTERCRITERIONS = new ArrayList<Criterion>();
/**
* Utility class
*/
private CriterionUtils() {
}
public static void clearLayerFilters(MapWidget mapWidget) {
for (VectorLayer layer : mapWidget.getMapModel().getVectorLayers()) {
if (layer.getFilter() != null) {
layer.setFilter(null);
}
}
ACTIVELAYERFILTERCRITERIONS.clear();
}
public static void setLayerFilter(final MapWidget mapWidget, final Criterion criterion) {
Map<String, String> filters = criterionToFilters(criterion, mapWidget.getMapModel());
if (filters != null && !filters.isEmpty()) {
List<VectorLayer> vls = mapWidget.getMapModel().getVectorLayers();
for (String serverLayerId : filters.keySet()) {
for (VectorLayer vl : vls) {
if (serverLayerId.equals(vl.getServerLayerId())) {
vl.setFilter(filters.get(serverLayerId));
GWT.log("Setting layerfilter: " + serverLayerId + " - " + filters.get(serverLayerId));
}
}
}
}
ACTIVELAYERFILTERCRITERIONS.add(criterion);
}
/**
* This does the same as dtoConverterservice but uses strings for filters instead of (serverside) filter objects.
*
* @param criterion
* @param mapCrs
*/
public static Map<String, String> criterionToFilters(Criterion criterion, MapModel mapModel) {
if (criterion != null) {
if (criterion instanceof AttributeCriterion) {
return attributeCriterionToFilters((AttributeCriterion) criterion);
} else if (criterion instanceof GeometryCriterion) {
return geometryCriterionToFilters((GeometryCriterion) criterion, mapModel);
} else if (criterion instanceof AndCriterion) {
return andCriterionToFilters((AndCriterion) criterion, mapModel);
} else if (criterion instanceof OrCriterion) {
return orCriterionToFilters((OrCriterion) criterion, mapModel);
} else {
return null;
}
} else {
return new LinkedHashMap<String, String>();
}
}
// ----------------------------------------------------------
private static Map<String, String> attributeCriterionToFilters(AttributeCriterion criterion) {
Map<String, String> filters = new LinkedHashMap<String, String>();
String filter = criterion.getAttributeName() + " " + criterion.getOperator() + " ";
if (criterion.getValue() != null
&& ((criterion.getValue().contains("\"") || criterion.getValue().contains(" ") || !criterion.getValue()
.matches("(\\.|\\-|[0-9])*")) || "LIKE".equalsIgnoreCase(criterion.getOperator()))
&& ((!"DURING".equals(criterion.getOperator().toUpperCase())
&& !"BEFORE".equals(criterion.getOperator().toUpperCase()) && !"AFTER".equals(criterion
.getOperator().toUpperCase())))) {
filter += "\'" + criterion.getValue().replaceAll("\\*", "%") + "\'";
} else {
filter += criterion.getValue();
}
filters.put(criterion.getServerLayerId(), filter);
return filters;
}
private static Map<String, String> geometryCriterionToFilters(GeometryCriterion criterion, MapModel mapModel) {
Map<String, String> filters = new LinkedHashMap<String, String>();
org.geomajas.gwt.client.spatial.geometry.Geometry mapGeom = GeometryConverter.toGwt(criterion.getGeometry());
String wktGeom = mapGeom.toWkt();
String method;
switch (criterion.getOperator()) {
case SearchByLocationRequest.QUERY_INTERSECTS:
method = "INTERSECTS";
break;
case SearchByLocationRequest.QUERY_CONTAINS:
method = "CONTAINS";
break;
case SearchByLocationRequest.QUERY_TOUCHES:
method = "TOUCHES";
break;
case SearchByLocationRequest.QUERY_WITHIN:
method = "WITHIN";
break;
default:
return null;
}
for (String serverLayerId : criterion.getServerLayerIds()) {
VectorLayer vl = findVectorLayer(mapModel, serverLayerId);
if (vl != null) {
String geomAttName = vl.getLayerInfo().getFeatureInfo().getGeometryType().getName();
filters.put(serverLayerId, method + "(" + geomAttName + ", " + wktGeom + ")");
}
}
return filters;
}
private static Map<String, String> andCriterionToFilters(AndCriterion criterion, MapModel mapModel) {
Map<String, String> filters = new LinkedHashMap<String, String>();
for (Criterion critter : criterion.getCriteria()) {
combineFilters(filters, criterionToFilters(critter, mapModel), " AND ");
}
return filters;
}
private static Map<String, String> orCriterionToFilters(OrCriterion criterion, MapModel mapModel) {
Map<String, String> filters = new LinkedHashMap<String, String>();
for (Criterion critter : criterion.getCriteria()) {
combineFilters(filters, criterionToFilters(critter, mapModel), " OR ");
}
return filters;
}
private static void combineFilters(Map<String, String> keep, Map<String, String> add, String method) {
if (add.size() != 0) {
for (Entry<String, String> entry : add.entrySet()) {
if (keep.containsKey(entry.getKey())) {
keep.put(entry.getKey(), "(" + keep.get(entry.getKey()) + method + entry.getValue() + ")");
} else {
keep.put(entry.getKey(), entry.getValue());
}
}
}
}
private static VectorLayer findVectorLayer(MapModel mapModel, String serverLayerId) {
List<VectorLayer> vls = mapModel.getVectorLayersByServerId(serverLayerId);
if (vls != null && vls.size() > 0) {
return vls.get(0);
} else {
return null;
}
}
public static boolean isActiveLayerFilter(Criterion criterion) {
return ACTIVELAYERFILTERCRITERIONS.contains(criterion);
}
}