/** * 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 org.codice.ddf.spatial.ogc.csw.catalog.endpoint.mappings; 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.closeTo; import static org.hamcrest.Matchers.is; 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.endpoint.CswQueryFactoryTest; import org.geotools.feature.NameImpl; import org.geotools.filter.AttributeExpressionImpl; import org.geotools.filter.FilterFactoryImpl; import org.geotools.referencing.CRS; 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.Intersects; 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.During; import org.opengis.filter.temporal.TEquals; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import ddf.catalog.data.Metacard; import ddf.catalog.data.MetacardType; import ddf.catalog.data.types.Core; import ddf.catalog.filter.proxy.builder.GeotoolsFilterBuilder; import ddf.catalog.impl.filter.FuzzyFunction; 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; private static MetacardType metacardType; private static List<MetacardType> mockMetacardTypeList; @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, Core.CREATED, CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX))); metacardType = CswQueryFactoryTest.getCswMetacardType(); mockMetacardTypeList = new ArrayList<>(); mockMetacardTypeList.add(metacardType); visitor = new CswRecordMapperFilterVisitor(metacardType, mockMetacardTypeList); } @Test public void testVisitWithUnmappedName() { CswRecordMapperFilterVisitor visitor = new CswRecordMapperFilterVisitor(metacardType, mockMetacardTypeList); PropertyName propertyName = (PropertyName) visitor.visit(attrExpr, null); assertThat(propertyName.getPropertyName(), is(UNMAPPED_PROPERTY)); } @Test public void testVisitWithBoundingBoxProperty() { AttributeExpressionImpl propName = new AttributeExpressionImpl(new NameImpl(new QName( CswConstants.DUBLIN_CORE_SCHEMA, CswConstants.OWS_BOUNDING_BOX, CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX))); CswRecordMapperFilterVisitor visitor = new CswRecordMapperFilterVisitor(metacardType, mockMetacardTypeList); PropertyName propertyName = (PropertyName) visitor.visit(propName, null); assertThat(propertyName.getPropertyName(), is(Metacard.ANY_GEO)); } @Test public void testVisitWithMappedName() { AttributeExpressionImpl propName = new AttributeExpressionImpl(new NameImpl(new QName( CswConstants.DUBLIN_CORE_SCHEMA, CswConstants.CSW_ALTERNATIVE, CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX))); CswRecordMapperFilterVisitor visitor = new CswRecordMapperFilterVisitor(metacardType, mockMetacardTypeList); PropertyName propertyName = (PropertyName) visitor.visit(propName, null); assertThat(propertyName.getPropertyName(), is(Core.TITLE)); assertThat(propertyName.getPropertyName(), not(is(CswConstants.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(), is(pt1)); assertThat(duplicate.getExpression2(), is(pt2)); assertThat(duplicate.getDistanceUnits(), is(UomOgcMapping.METRE.name())); assertThat(duplicate.getDistance(), is(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(), is(attrExpr)); assertThat(duplicate.getExpression2() .toString(), is(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(), is(pt1)); assertThat(duplicate.getExpression2(), is(pt2)); assertThat(duplicate.getDistanceUnits(), is(UomOgcMapping.METRE.name())); assertThat(duplicate.getDistance(), is(val)); } @Test public void testIntersectsUtm() throws FactoryException, TransformException { double lon = 33.45; double lat = 25.22; double easting = 545328.48; double northing = 2789384.24; CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:32636"); GeometryFactory geoFactory = new GeometryFactory(); Geometry utmPoint = geoFactory.createPoint(new Coordinate(easting, northing)); utmPoint.setUserData(sourceCRS); Expression pt1 = factory.literal(geoFactory.createPoint(new Coordinate(1, 2))); Expression pt2 = factory.literal(utmPoint); Intersects filter = factory.intersects(pt1, pt2); visitor.visit(filter, null); assertThat(pt2, instanceOf(Literal.class)); Literal literalExpression = (Literal) pt2; assertThat(literalExpression.getValue(), instanceOf(Geometry.class)); Geometry geometry = (Geometry) literalExpression.getValue(); assertThat(geometry.getCoordinates()[0].x, closeTo(lon, .00001)); assertThat(geometry.getCoordinates()[0].y, closeTo(lat, .00001)); } @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(), is(attrExpr)); assertThat(duplicate.getLowerBoundary(), is(lower)); assertThat(duplicate.getUpperBoundary(), is(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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(val)); assertThat(duplicate.isMatchingCase(), is(true)); } @Test public void testVisitPropertyIsFuzzy() { visitor = new CswRecordMapperFilterVisitor(metacardType, mockMetacardTypeList); Expression val1 = factory.property("fooProperty"); Expression val2 = factory.literal("fooLiteral"); //PropertyIsFuzzy maps to a propertyIsLike filter with a fuzzy function GeotoolsFilterBuilder builder = new GeotoolsFilterBuilder(); PropertyIsLike fuzzySearch = (PropertyIsLike) builder.attribute(val1.toString()) .is() .like() .fuzzyText(val2.toString()); PropertyIsLike visitedFilter = (PropertyIsLike) visitor.visit(fuzzySearch, null); assertThat(visitedFilter.getExpression(), is(instanceOf(FuzzyFunction.class))); assertThat(visitedFilter.getLiteral(), is(val2.toString())); } @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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(val)); assertThat(duplicate.isMatchingCase(), is(false)); } @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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(val)); assertThat(duplicate.isMatchingCase(), is(false)); } @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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(val)); } @Test public void testVisitPropertyIsGreaterThanTemporal() { Expression val = factory.literal(new Date(System.currentTimeMillis() - 1000)); Expression test = new AttributeExpressionImpl(new NameImpl(new QName(CswConstants.DUBLIN_CORE_SCHEMA, "TestDate", CswConstants.DUBLIN_CORE_NAMESPACE_PREFIX))); PropertyIsGreaterThan filter = factory.greater(test, val); Object obj = visitor.visit(filter, null); assertThat(obj, instanceOf(During.class)); During duplicate = (During) obj; assertThat(duplicate.getExpression1(), is(test)); assertThat(duplicate.getExpression2(), is(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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(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(), is(created)); assertThat(binary.getExpression2(), is(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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(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(), is(created)); assertThat(duplicate.getExpression2(), is(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(), is(attrExpr)); assertThat(duplicate.getExpression2(), is(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; for (Filter child : duplicate.getChildren()) { BinaryTemporalOperator binary = (BinaryTemporalOperator) child; assertThat(binary, anyOf(instanceOf(TEquals.class), instanceOf(Before.class))); assertThat(binary.getExpression1(), is(created)); assertThat(binary.getExpression2(), is(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(literal.getValue(), is(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(literal.getValue(), is(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(literal.getValue(), is(dateString)); } @Test public void testSourceIdFilter() { Expression val = factory.literal("source1"); Expression val2 = factory.literal("source2"); Expression sourceExpr = factory.property(Core.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(), is(attrExpr)); assertThat(duplicate.getLiteral(), is("something")); assertThat(visitor.getSourceIds() .size(), is(2)); } }