package nl.ipo.cds.etl.filtering;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import nl.ipo.cds.etl.GenericFeature;
import org.deegree.commons.tom.TypedObjectNode;
import org.deegree.commons.tom.primitive.BaseType;
import org.deegree.commons.tom.primitive.PrimitiveType;
import org.deegree.commons.tom.primitive.PrimitiveValue;
import org.deegree.filter.FilterEvaluationException;
import org.deegree.filter.XPathEvaluator;
import org.deegree.filter.expression.ValueReference;
import org.deegree.geometry.Geometry;
import org.deegree.geometry.multi.MultiPolygon;
import org.deegree.geometry.multi.MultiSurface;
import org.deegree.geometry.primitive.Polygon;
import org.deegree.geometry.primitive.Surface;
public class GenericFeatureXPathEvaluator implements XPathEvaluator<GenericFeature> {
@Override
public TypedObjectNode[] eval (final GenericFeature context, final ValueReference valueRef) throws FilterEvaluationException {
final String[] parts = parseExpression (valueRef.getAsText ());
if (parts.length == 0 || parts.length > 2) {
return new TypedObjectNode[0];
}
final String name = parts[0];
final String propertyName = parts.length > 1 ? parts[1] : null;
if (!context.hasProperty (name)) {
return new TypedObjectNode[0];
}
final Object value = context.get (name);
if (value instanceof String) {
return wrapTom (value ((String)value, BaseType.STRING));
} else if (value instanceof Boolean) {
return wrapTom (value ((Boolean)value, BaseType.BOOLEAN));
} else if (value instanceof BigDecimal) {
return wrapTom (value ((BigDecimal)value, BaseType.DECIMAL));
} else if (value instanceof BigInteger) {
return wrapTom (value ((BigInteger)value, BaseType.INTEGER));
} else if (value instanceof Double) {
return wrapTom (value ((Double)value, BaseType.DOUBLE));
} else if (value instanceof Float) {
final double val = (Float)value;
return wrapTom (value (val, BaseType.DOUBLE));
} else if (value instanceof Integer) {
return wrapTom (value ((Integer)value, BaseType.INTEGER));
} else if (value instanceof Date) {
final org.deegree.commons.tom.datetime.Date d = new org.deegree.commons.tom.datetime.Date (new java.util.Date (((Date)value).getTime ()), null);
return wrapTom (value (d, BaseType.DATE));
} else if (value instanceof Timestamp) {
final org.deegree.commons.tom.datetime.DateTime dt = new org.deegree.commons.tom.datetime.DateTime (new java.util.Date (((Timestamp)value).getTime ()), null);
return wrapTom (value (dt, BaseType.DATE_TIME));
} else if (value instanceof Time) {
final org.deegree.commons.tom.datetime.Time t = new org.deegree.commons.tom.datetime.Time (new java.util.Date (((Time)value).getTime ()), null);
return wrapTom (value (t, BaseType.TIME));
} else if ((value instanceof Geometry) && "area".equals (propertyName)) {
return wrapTom (value (getArea ((Geometry)value), BaseType.DOUBLE));
} else if (value instanceof Geometry) {
return wrapTom ( (Geometry)value );
} else if (value == null) {
return new TypedObjectNode[] { null };
} else {
throw new IllegalStateException (String.format ("Unknown feature attribute type `%s`", value == null ? "null" : value.getClass ().getCanonicalName ()));
}
}
private double getArea (final Geometry geometry) {
if (geometry instanceof Polygon) {
return ((Polygon)geometry).getArea (null).getValueAsDouble ();
} else if (geometry instanceof MultiPolygon) {
final MultiPolygon multi = (MultiPolygon)geometry;
double area = 0;
for (final Polygon poly: multi) {
area += poly.getArea (null).getValueAsDouble ();
}
return area;
} else if (geometry instanceof Surface) {
return ((Surface)geometry).getArea (null).getValueAsDouble ();
} else if (geometry instanceof MultiSurface) {
@SuppressWarnings("unchecked")
final MultiSurface<Surface> geom = (MultiSurface<Surface>)geometry;
double area = 0;
for (final Surface surface: geom) {
area += surface.getArea (null).getValueAsDouble ();
}
return area;
} else {
return 0;
}
}
@Override
public String getId (final GenericFeature context) {
return context.getId ();
}
private static PrimitiveValue value (final Object value, final BaseType baseType) {
return new PrimitiveValue (value, new PrimitiveType (baseType));
}
private static TypedObjectNode[] wrapTom (final TypedObjectNode ... value) {
return value;
}
private static String[] parseExpression (final String xpath) {
if (xpath == null || xpath.isEmpty ()) {
return new String[0];
}
final String[] parts = xpath.split ("\\/");
final String[] result = new String[parts.length];
for (int i = 0; i < parts.length; ++ i) {
final String part = parts[i];
final int offset = part.indexOf (':');
if (offset >= 0) {
result[i] = part.substring (offset + 1);
} else {
result[i] = part;
}
}
return result;
}
}