/**
* Copyright (c) Codice Foundation
*
* 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.
*
* 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 org.codice.ddf.spatial.ogc.csw.catalog.endpoint.mappings;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.namespace.QName;
import org.codice.ddf.spatial.ogc.csw.catalog.common.CswConstants;
import org.codice.ddf.spatial.ogc.csw.catalog.common.CswRecordMetacardType;
import org.geotools.feature.NameImpl;
import org.geotools.filter.AttributeExpressionImpl;
import org.geotools.filter.FilterFactoryImpl;
import org.geotools.styling.UomOgcMapping;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.opengis.filter.Filter;
import org.opengis.filter.Or;
import org.opengis.filter.PropertyIsBetween;
import org.opengis.filter.PropertyIsEqualTo;
import org.opengis.filter.PropertyIsGreaterThan;
import org.opengis.filter.PropertyIsGreaterThanOrEqualTo;
import org.opengis.filter.PropertyIsLessThan;
import org.opengis.filter.PropertyIsLessThanOrEqualTo;
import org.opengis.filter.PropertyIsLike;
import org.opengis.filter.PropertyIsNotEqualTo;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BBOX;
import org.opengis.filter.spatial.Beyond;
import org.opengis.filter.spatial.DWithin;
import org.opengis.filter.spatial.Within;
import org.opengis.filter.temporal.After;
import org.opengis.filter.temporal.Before;
import org.opengis.filter.temporal.BinaryTemporalOperator;
import org.opengis.filter.temporal.TEquals;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import ddf.catalog.data.Metacard;
public class TestCswRecordMapperFilterVisitor {
private static final String UNMAPPED_PROPERTY = "not_mapped_to_anything";
private static FilterFactoryImpl factory;
private static Expression attrExpr;
private static Expression created;
private static CswRecordMapperFilterVisitor visitor;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
factory = new FilterFactoryImpl();
attrExpr = factory.property(new NameImpl(
new QName(CswConstants.DUBLIN_CORE_SCHEMA, UNMAPPED_PROPERTY,
CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX)));
created = new AttributeExpressionImpl(new NameImpl(
new QName(CswConstants.DUBLIN_CORE_SCHEMA, Metacard.CREATED,
CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX)));
visitor = new CswRecordMapperFilterVisitor();
}
@Test
public void testVisitWithUnmappedName() {
CswRecordMapperFilterVisitor visitor = new CswRecordMapperFilterVisitor();
PropertyName propertyName = (PropertyName) visitor.visit(attrExpr, null);
assertThat(propertyName.getPropertyName(), equalTo(UNMAPPED_PROPERTY));
}
@Test
public void testVisitWithBoundingBoxProperty() {
AttributeExpressionImpl propName = new AttributeExpressionImpl(new NameImpl(
new QName(CswConstants.DUBLIN_CORE_SCHEMA, CswRecordMetacardType.OWS_BOUNDING_BOX,
CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX)));
CswRecordMapperFilterVisitor visitor = new CswRecordMapperFilterVisitor();
PropertyName propertyName = (PropertyName) visitor.visit(propName, null);
assertThat(propertyName.getPropertyName(), equalTo(Metacard.ANY_GEO));
}
@Test
public void testVisitWithMappedName() {
AttributeExpressionImpl propName = new AttributeExpressionImpl(new NameImpl(
new QName(CswConstants.DUBLIN_CORE_SCHEMA, CswRecordMetacardType.CSW_ALTERNATIVE,
CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX)));
CswRecordMapperFilterVisitor visitor = new CswRecordMapperFilterVisitor();
PropertyName propertyName = (PropertyName) visitor.visit(propName, null);
assertThat(propertyName.getPropertyName(), equalTo(Metacard.TITLE));
assertThat(propertyName.getPropertyName(),
not(equalTo(CswRecordMetacardType.CSW_ALTERNATIVE)));
}
@Test
public void testVisitBeyond() {
GeometryFactory geoFactory = new GeometryFactory();
double val = 30;
Expression pt1 = factory.literal(geoFactory.createPoint(new Coordinate(4, 5)));
Expression pt2 = factory.literal(geoFactory.createPoint(new Coordinate(6, 7)));
Beyond filter = factory.beyond(pt1, pt2, val, "kilometers");
Beyond duplicate = (Beyond) visitor.visit(filter, null);
assertThat(duplicate.getExpression1(), equalTo(pt1));
assertThat(duplicate.getExpression2(), equalTo(pt2));
assertThat(duplicate.getDistanceUnits(), equalTo(UomOgcMapping.METRE.name()));
assertThat(duplicate.getDistance(), equalTo(1000 * val));
}
@Test
public void testVisitBBox() {
BBOX filter = factory.bbox(attrExpr, 0, 0, 10, 20, "EPSG:4269");
String polygon = "POLYGON ((0 0, 0 20, 10 20, 10 0, 0 0))";
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(Within.class));
Within duplicate = (Within) obj;
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2().toString(), equalTo(polygon));
}
@Test
public void testVisitDWithin() {
GeometryFactory geoFactory = new GeometryFactory();
double val = 10;
Expression pt1 = factory.literal(geoFactory.createPoint(new Coordinate(4, 5)));
Expression pt2 = factory.literal(geoFactory.createPoint(new Coordinate(6, 7)));
DWithin filter = factory.dwithin(pt1, pt2, val, "meters");
DWithin duplicate = (DWithin) visitor.visit(filter, null);
assertThat(duplicate.getExpression1(), equalTo(pt1));
assertThat(duplicate.getExpression2(), equalTo(pt2));
assertThat(duplicate.getDistanceUnits(), equalTo(UomOgcMapping.METRE.name()));
assertThat(duplicate.getDistance(), equalTo(val));
}
@Test
public void testVisitPropertyIsBetween() {
Expression lower = factory.literal(4);
Expression upper = factory.literal(7);
PropertyIsBetween filter = factory.between(attrExpr, lower, upper);
PropertyIsBetween duplicate = (PropertyIsBetween) visitor.visit(filter, null);
assertThat(duplicate.getExpression(), equalTo(attrExpr));
assertThat(duplicate.getLowerBoundary(), equalTo(lower));
assertThat(duplicate.getUpperBoundary(), equalTo(upper));
}
@Test
public void testVisitPropertyIsEqualTo() {
Expression val = factory.literal("foo");
PropertyIsEqualTo filter = factory.equals(attrExpr, val);
PropertyIsEqualTo duplicate = (PropertyIsEqualTo) visitor.visit(filter, null);
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
assertTrue(duplicate.isMatchingCase());
}
@Test
public void testVisitPropertyIsEqualToCaseInsensitive() {
Expression val = factory.literal("foo");
PropertyIsEqualTo filter = factory.equal(attrExpr, val, false);
PropertyIsEqualTo duplicate = (PropertyIsEqualTo) visitor.visit(filter, null);
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
assertFalse(duplicate.isMatchingCase());
}
@Test
public void testVisitPropertyIsNotEqualToCaseInsensitive() {
Expression val = factory.literal("foo");
PropertyIsNotEqualTo filter = factory.notEqual(attrExpr, val, false);
PropertyIsNotEqualTo duplicate = (PropertyIsNotEqualTo) visitor.visit(filter, null);
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
assertFalse(duplicate.isMatchingCase());
}
@Test
public void testVisitPropertyIsGreaterThan() {
Expression val = factory.literal(8);
PropertyIsGreaterThan filter = factory.greater(attrExpr, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(PropertyIsGreaterThan.class));
PropertyIsGreaterThan duplicate = (PropertyIsGreaterThan) obj;
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
}
@Ignore("not supported by solr provider")
@Test
public void testVisitPropertyIsGreaterThanTemporal() {
Expression val = factory.literal(new Date());
PropertyIsGreaterThan filter = factory.greater(created, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(After.class));
After duplicate = (After) obj;
assertThat(duplicate.getExpression1(), equalTo(created));
assertThat(duplicate.getExpression2(), equalTo(val));
}
@Test
public void testVisitPropertyIsGreaterThanOrEqualTo() {
Expression val = factory.literal(8);
PropertyIsGreaterThanOrEqualTo filter = factory.greaterOrEqual(attrExpr, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(PropertyIsGreaterThanOrEqualTo.class));
PropertyIsGreaterThanOrEqualTo duplicate = (PropertyIsGreaterThanOrEqualTo) obj;
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
}
@Ignore("not supported by solr provider")
@Test
public void testVisitPropertyIsGreaterThanOrEqualToTemporal() {
Expression val = factory.literal(new Date());
PropertyIsGreaterThanOrEqualTo filter = factory.greaterOrEqual(created, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(Or.class));
Or duplicate = (Or) obj;
for (Filter child : duplicate.getChildren()) {
BinaryTemporalOperator binary = (BinaryTemporalOperator) child;
assertThat(binary, anyOf(instanceOf(TEquals.class), instanceOf(After.class)));
assertThat(binary.getExpression1(), equalTo(created));
assertThat(binary.getExpression2(), equalTo(val));
}
}
@Test
public void testVisitPropertyIsLessThan() {
Expression val = factory.literal(8);
PropertyIsLessThan filter = factory.less(attrExpr, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(PropertyIsLessThan.class));
PropertyIsLessThan duplicate = (PropertyIsLessThan) obj;
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
}
@Test
public void testVisitPropertyIsLessThanTemporal() {
Expression val = factory.literal(new Date());
PropertyIsLessThan filter = factory.less(created, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(Before.class));
Before duplicate = (Before) obj;
assertThat(duplicate.getExpression1(), equalTo(created));
assertThat(duplicate.getExpression2(), equalTo(val));
}
@Test
public void testVisitPropertyIsLessThanOrEqualTo() {
Expression val = factory.literal(8);
PropertyIsLessThanOrEqualTo filter = factory.lessOrEqual(attrExpr, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(PropertyIsLessThanOrEqualTo.class));
PropertyIsLessThanOrEqualTo duplicate = (PropertyIsLessThanOrEqualTo) obj;
assertThat(duplicate.getExpression1(), equalTo(attrExpr));
assertThat(duplicate.getExpression2(), equalTo(val));
}
@Ignore("not supported by solr provider")
@Test
public void testVisitPropertyIsLessThanOrEqualToTemporal() {
Expression val = factory.literal(new Date());
PropertyIsLessThanOrEqualTo filter = factory.lessOrEqual(created, val);
Object obj = visitor.visit(filter, null);
assertThat(obj, instanceOf(Or.class));
Or duplicate = (Or) obj;
List<Class<? extends BinaryTemporalOperator>> classes = new ArrayList<Class<? extends BinaryTemporalOperator>>();
for (Filter child : duplicate.getChildren()) {
BinaryTemporalOperator binary = (BinaryTemporalOperator) child;
assertThat(binary, anyOf(instanceOf(TEquals.class), instanceOf(Before.class)));
classes.add(binary.getClass());
assertThat(binary.getExpression1(), equalTo(created));
assertThat(binary.getExpression2(), equalTo(val));
}
}
@Test
public void testLiteralWithMappableType() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
String dateString = formatter.format(date);
Literal val = factory.literal(dateString);
Literal literal = (Literal) visitor.visit(val, created);
assertThat(literal.getValue(), instanceOf(Date.class));
assertThat((Date) literal.getValue(), equalTo(date));
}
@Test
public void testLiteralWithUnknownType() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
String dateString = formatter.format(date);
Literal val = factory.literal(dateString);
Literal literal = (Literal) visitor.visit(val, attrExpr);
assertThat(literal.getValue(), instanceOf(String.class));
assertThat((String) literal.getValue(), equalTo(dateString));
}
@Test
public void testLiteralWithNoType() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
String dateString = formatter.format(date);
Literal val = factory.literal(dateString);
Literal literal = (Literal) visitor.visit(val, null);
assertThat(literal.getValue(), instanceOf(String.class));
assertThat((String) literal.getValue(), equalTo(dateString));
}
@Test
public void testSourceIdFilter() {
Expression val = factory.literal("source1");
Expression val2 = factory.literal("source2");
Expression sourceExpr = factory.property(Metacard.SOURCE_ID);
PropertyIsEqualTo filter = factory.equal(sourceExpr, val, false);
Filter filter2 = factory.equal(sourceExpr, val2, false);
Filter likeFilter = factory.like(attrExpr, "something");
Filter sourceFilter = factory.or(filter, filter2);
Filter totalFilter = factory.and(sourceFilter, likeFilter);
Object obj = totalFilter.accept(visitor, null);
assertThat(obj, instanceOf(PropertyIsLike.class));
PropertyIsLike duplicate = (PropertyIsLike) obj;
assertThat(duplicate.getExpression(), equalTo(attrExpr));
assertThat(duplicate.getLiteral(), equalTo("something"));
assertThat(visitor.getSourceIds().size(), is(2));
}
}