/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library 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;
* version 2.1 of the License.
*
* This library 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.
*/
package org.geotools.geometry.xml;
import java.util.Map;
import java.util.HashMap;
import java.util.logging.Logger;
import junit.framework.Assert;
import org.geotools.geometry.iso.UnsupportedDimensionException;
import org.geotools.geometry.iso.root.GeometryImpl;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Geometry;
import org.opengis.geometry.TransfiniteSet;
/**
* @author <a href="mailto:joel@lggi.com">Joel Skelton</a>
*
* @source $URL$
*/
public class GeometryTestOperation extends Assert {
private String operation;
private String arg1;
private String arg2;
private String arg3;
private Object expectedResult;
private Object actualResult;
private Map<String, OperationHandler> operationMap;
private static final Logger LOG = org.geotools.util.logging.Logging.getLogger("org.geotools.geometry");
/**
* Constructor
* @param operation the operation to perform
* @param arg1 first argument
* @param arg2 second argument
* @param arg3 third argument
* @param expectedResult the passing result of the operation
*/
public GeometryTestOperation(String operation, String arg1, String arg2, String arg3, Object expectedResult) {
this.operation = operation;
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
this.expectedResult = expectedResult;
this.actualResult = null;
setupOperationMap();
}
/**
* Returns the operation to be performed.
*
* @return String operation
*/
public String getOperation() {
return operation;
}
/**
* Sets the expected result.
*
* @param expectedResult
*/
public void setExpectedResult(Object expectedResult) {
this.expectedResult = expectedResult;
}
private void setupOperationMap() {
operationMap = new HashMap<String, OperationHandler>();
OperationHandler noOpHandler = new NoOp();
operationMap.put("contains", new ContainsOp());
operationMap.put("convexhull", new ConvexHullOp());
operationMap.put("difference", new DifferenceOp());
operationMap.put("getboundary", new BoundaryOp());
operationMap.put("getCentroid", new CentroidOp());
operationMap.put("getInteriorPoint", new RepresentativePointOp());
operationMap.put("intersection", new IntersectionOp());
operationMap.put("intersects", new IntersectsOp());
operationMap.put("within", new IntersectsOp());
operationMap.put("isSimple", new IsSimpleOp());
operationMap.put("symdifference", new SymmetricDifferenceOp());
operationMap.put("union", new UnionOp());
operationMap.put("relate", new RelateOp());
operationMap.put("isWithinDistance", new WithinDistanceOp());
operationMap.put("distance", new DistanceOp());
operationMap.put("disjoint", new DisjointOp());
}
protected Object getExpectedResult() {
return expectedResult;
}
private Geometry setGeomArg(String s, Geometry a, Geometry b) {
if (s.equalsIgnoreCase("a")) {
return a;
} else if (s.equalsIgnoreCase("b")) {
return b;
} else {
return null;
}
}
/**
* Performs the contained operation
* @param a argument object a
* @param b argument object b
* @return
*/
public boolean run(Geometry a, Geometry b) {
boolean result = false;
result = operationMap.get(operation).doOperation(a, b);
return result;
}
/**
* The interface used for operation handlers
*/
private abstract class OperationHandler {
boolean doOperation(Geometry a, Geometry b) {
return false;
}
protected boolean compareTransfiniteSetResult(TransfiniteSet result) {
if (expectedResult == null && result == null) {
return true;
}
if (expectedResult instanceof TransfiniteSet) {
TransfiniteSet expect = (TransfiniteSet)expectedResult;
return result.equals(expect);
} else {
return false;
}
}
protected boolean compareDirectPositionResult(DirectPosition result) {
if (expectedResult instanceof DirectPosition) {
DirectPosition expect = (DirectPosition)expectedResult;
return result.equals(expect);
} else {
return false;
}
}
}
/**
* Class defining a null operation
*/
private class NoOp extends OperationHandler {
public boolean doOperation(Geometry a, Geometry b) {
return false;
}
}
/**
* Class defining the "contains" operation
*/
private class ContainsOp extends OperationHandler {
/**
* The actual working method of the operation.
* @param a Geometry object
* @param b Geometry Object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Boolean expected = (Boolean)expectedResult;
Geometry geom1 = setGeomArg(arg1, a, b);
Geometry geom2 = setGeomArg(arg2, a, b);
actualResult = geom1.contains(geom2);
return actualResult == expected;
}
}
/**
* Class defining the "intersects" operation
*/
private class IntersectsOp extends OperationHandler {
/**
* The actual working method of the operation.
* @param a Geometry object
* @param b Geometry Object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Boolean expected = (Boolean)expectedResult;
Geometry geom1 = setGeomArg(arg1, a, b);
Geometry geom2 = setGeomArg(arg2, a, b);
actualResult = geom1.intersects(geom2);
return actualResult == expected;
}
}
/**
* Class defining the "within" operation
*/
private class WithinOp extends OperationHandler {
/**
* The actual working method of the operation.
* @param a Geometry object
* @param b Geometry Object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Boolean expected = (Boolean)expectedResult;
GeometryImpl geom1 = (GeometryImpl) setGeomArg(arg1, a, b);
GeometryImpl geom2 = (GeometryImpl) setGeomArg(arg2, a, b);
actualResult = geom1.within(geom2);
return actualResult == expected;
}
}
/**
* Class defining the "intersects" operation
*/
private class IsSimpleOp extends OperationHandler {
/**
* The actual working method of the operation.
* @param a Geometry object
* @param b Geometry Object (not used)
* @return a boolean indicating whether object A is simple
*/
public boolean doOperation(Geometry a, Geometry b) {
Boolean expected = (Boolean)expectedResult;
Geometry geom1 = setGeomArg(arg1, a, b);
actualResult = geom1.isSimple();
return actualResult == expected;
}
}
/**
* Class defining the "intersects" operation
*/
private class IntersectionOp extends OperationHandler {
/**
* performs the intersection on the two arguments
* @param a Geometry object
* @param b Geometry Object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
Geometry geom2 = setGeomArg(arg2, a, b);
TransfiniteSet result = geom1.intersection(geom2);
actualResult = result;
return compareTransfiniteSetResult(result);
}
}
/**
* Class defining the boundary operation
*/
private class BoundaryOp extends OperationHandler {
/**
* Calculates the boundary of object A
* @param a Geometry object
* @param b Geometry Object (not used)
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
TransfiniteSet result = geom1.getBoundary();
actualResult = result;
return compareTransfiniteSetResult(result);
}
}
/**
* Class defining the centroid operation
*/
private class CentroidOp extends OperationHandler {
/**
* Calculates the centroid of object A
* @param a Geometry object
* @param b Geometry Object (not used)
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
DirectPosition result = geom1.getCentroid();
actualResult = result;
return compareDirectPositionResult(result);
}
}
/**
* Class defining the representitivepoint operation
*/
private class RepresentativePointOp extends OperationHandler {
/**
* Calculates a representative point for object A
* @param a Geometry object
* @param b Geometry Object (not used)
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
DirectPosition result = geom1.getRepresentativePoint();
actualResult = result;
return compareDirectPositionResult(result);
}
}
/**
* Class defining the convex hull operation
*/
private class ConvexHullOp extends OperationHandler {
/**
* Calculates the convex hull of object A
* @param a Geometry object
* @param b Geometry Object (not used)
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
TransfiniteSet result = geom1.getConvexHull();
actualResult = result;
return compareTransfiniteSetResult(result);
}
}
/**
* Class defining the difference operation
*/
private class DifferenceOp extends OperationHandler {
/**
* Calculates the difference of objects A and B (A - B)
* @param a Geometry object
* @param b Geometry object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
Geometry geom2 = setGeomArg(arg2, a, b);
TransfiniteSet result = geom1.difference(geom2);
actualResult = result;
return compareTransfiniteSetResult(result);
}
}
/**
* Class defining the symdifference operation
*/
private class SymmetricDifferenceOp extends OperationHandler {
/**
* Calculates the symmetric difference of objects A and B (A - B)
* @param a Geometry object
* @param b Geometry object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
Geometry geom2 = setGeomArg(arg2, a, b);
TransfiniteSet result = geom1.symmetricDifference(geom2);
actualResult = result;
return compareTransfiniteSetResult(result);
}
}
/**
* Class defining the union operation
*/
private class UnionOp extends OperationHandler {
/**
* Calculates the union of objects A and B (A + B)
* @param a Geometry object
* @param b Geometry object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
Geometry geom1 = setGeomArg(arg1, a, b);
Geometry geom2 = setGeomArg(arg2, a, b);
TransfiniteSet result = geom1.union(geom2);
actualResult = result;
return compareTransfiniteSetResult(result);
}
}
/**
* Class defining the relate operation
*/
private class RelateOp extends OperationHandler {
/**
* Calculates the relation of objects A and B (A + B)
* @param a Geometry object
* @param b Geometry object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
GeometryImpl geom1 = (GeometryImpl) setGeomArg(arg1, a, b);
GeometryImpl geom2 = (GeometryImpl) setGeomArg(arg2, a, b);
boolean result = false;
try {
result = geom1.relate(geom2, arg3);
} catch (UnsupportedDimensionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
actualResult = result;
return (actualResult == expectedResult);
}
}
/**
* Class defining the distance operation
*/
private class WithinDistanceOp extends OperationHandler {
/**
* Calculates the relation of objects A and B (A + B)
* @param a Geometry object
* @param b Geometry object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
GeometryImpl geom1 = (GeometryImpl) setGeomArg(arg1, a, b);
GeometryImpl geom2 = (GeometryImpl) setGeomArg(arg2, a, b);
double result = Double.NaN;
result = geom1.distance(geom2);
// return if the result is <= the max distance
actualResult = (result <= Double.parseDouble(arg3));
return (actualResult == expectedResult);
}
}
/**
* Class defining the distance operation
*/
private class DistanceOp extends OperationHandler {
/**
* Calculates the relation of objects A and B (A + B)
* @param a Geometry object
* @param b Geometry object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
GeometryImpl geom1 = (GeometryImpl) setGeomArg(arg1, a, b);
GeometryImpl geom2 = (GeometryImpl) setGeomArg(arg2, a, b);
double result = Double.NaN;
result = geom1.distance(geom2);
actualResult = result;
return (Double.compare(result, (Double) expectedResult) == 0);
}
}
/**
* Class defining the "disjoint" operation
*/
private class DisjointOp extends OperationHandler {
/**
* performs the disjoint on the two arguments
* @param a Geometry object
* @param b Geometry Object
* @return a boolean indicating whether the result matched the expectation
*/
public boolean doOperation(Geometry a, Geometry b) {
GeometryImpl geom1 = (GeometryImpl) setGeomArg(arg1, a, b);
GeometryImpl geom2 = (GeometryImpl) setGeomArg(arg2, a, b);
boolean result = geom1.disjoint(geom2);
actualResult = result;
return (actualResult == expectedResult);
}
}
/**
* Returns a string describing the operation for logging
* @return a formatted string
*/
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append( operation );
if( arg1 != null ){
buf.append( " arg1=");
buf.append( arg1 );
}
if( arg2 != null ){
buf.append( " arg2=");
buf.append( arg2 );
}
if( arg3 != null ){
buf.append( " arg3=");
buf.append( arg3 );
}
buf.append( " expected ");
buf.append( expectedResult );
return buf.toString();
}
public void runTest(Geometry a, Geometry b) {
OperationHandler ophand = operationMap.get(operation);
assertNotNull("Test Suite Error: No Operation Handler setup for operation: " + operation, ophand);
boolean test = ophand.doOperation(a, b);
assertTrue(toString() + " but was " + actualResult, test);
}
protected Object getActualResult() {
return actualResult;
}
}