// Copyright (c) 2006, Oracle. All rights reserved.
package oracle.toplink.essentials.extension.spatial;
import java.util.Vector;
import oracle.toplink.essentials.expressions.*;
import oracle.toplink.essentials.internal.expressions.FunctionExpression;
import oracle.toplink.essentials.internal.helper.ClassConstants;
import oracle.toplink.essentials.internal.helper.NonSynchronizedVector;
/**
* PUBLIC:
* <b>Purpose</b>: Provide a definition for spatial expression operators and a
* factory for constructing expressions for usage in queries.<p>
*
* Oracle DB 10.2 Spatial Documentation {link}http://download-west.oracle.com/docs/cd/B19306_01/appdev.102/b14255/toc.htm{link}
*
* @author Doug Clarke
* @since TopLink Essentials v2b41
*/
public enum SpatialOperator {
/**
* SDO_WITHIN_DISTANCE(geometry1, geometry2, params)
* Determines if two geometries are within a specified distance from one another.
*/
WITHIN_DISTANCE("MDSYS.SDO_WITHIN_DISTANCE", 3, "TRUE"),
/**
* SDO_RELATE(geometry1, geometry2, params)
* Determines whether or not two geometries interact in a specified way.
*/
RELATE("MDSYS.SDO_RELATE", 3, "TRUE"),
/**
* SDO_FILTER(geometry1, geometry2, params)
* Specifies which geometries may interact with a given geometry.
*/
FILTER("MDSYS.SDO_FILTER", 3, "TRUE"),
/**
* SDO_NN(geometry1, geometry2, params)
* Determines the nearest neighbor geometries to a geometry
*/
NN("MDSYS.SDO_NN", 3, "TRUE"),
/**
* SDO_NN_DISTANCE(nnOpIndex)
* Returns the distance of an object returned by the NN operator.
*/
NN_DISTANCE("MDSYS.SDO_NN_DISTANCE", 1),
// Convenience Operators for SDO_RELATE Operations
ANYINTERACT("MDSYS.SDO_ANYINTERACT", 2),
CONTAINS("MDSYS.SDO_CONTAINS", 2),
COVEREDBY("MDSYS.SDO_COVEREDBY", 2),
COVERS("MDSYS.SDO_COVERS", 2),
EQUAL("MDSYS.SDO_EQUAL", 2),
INSIDE("MDSYS.SDO_INSIDE", 2),
ON("MDSYS.SDO_ON", 2),
OVERLAPBDYDISJOINT("MDSYS.SDO_OVERLAPBDYDISJOINT", 2),
OVERLAPBDYINTERSECT("MDSYS.SDO_OVERLAPBDYINTERSECT", 2),
OVERLAPS("MDSYS.SDO_OVERLAPS", 2),
TOUCH("MDSYS.SDO_TOUCH", 2),
/**
* SDO_GEOM.RELATE(geomtry1, mask, geometry2, tolerance)
* Determines how two objects interact.
*/
GEOM_RELATE("SDO_GEOM.RELATE", 4),
;
private final String operatorName;
private final ExpressionOperator operator;
private final int numberofArguments;
/**
* Value used for comparison of the VARCHAR returned from the operator/function.
* In many cases 'TRUE' is returned so the expression must additionally do
* a comparison value for this to get a boolean value for use in the overall
* selection criteria.
*/
private final String defaultResultCompareValue;
SpatialOperator(String name, int numberofArgs,
String defaultResultCompareValue) {
this.operatorName = name;
this.numberofArguments = numberofArgs;
this.defaultResultCompareValue = defaultResultCompareValue;
this.operator = createOperator(name, numberofArgs);
}
SpatialOperator(String name, int numberofArgs) {
this(name, numberofArgs, null);
}
/**
* Construct the singleton expression operator required for building of
* function expresssions which are used in the selection criteria of queries
*/
public static ExpressionOperator createOperator(String operatorName,
int numArgs) {
ExpressionOperator op = new ExpressionOperator();
op.setType(ExpressionOperator.FunctionOperator);
Vector v = NonSynchronizedVector.newInstance(numArgs + 1);
v.addElement(operatorName + "(");
for (int argCount = 1; argCount < numArgs; argCount++) {
v.addElement(", ");
}
v.addElement(")");
op.printsAs(v);
op.bePrefix();
op.setNodeClass(ClassConstants.FunctionExpression_Class);
return op;
}
public String getOperatorName() {
return this.operatorName;
}
public int getNumberOfArguments() {
return this.numberofArguments;
}
public String getDefaultResultCompareValue() {
return this.defaultResultCompareValue;
}
public ExpressionOperator getOperator() {
return this.operator;
}
/**
* Build an expression for the most common spatial operator format.
*
* @param geom1 expression referenceing a geometry attribute
* @param geom2 an expression for a second geometry or a JGeometry instance
* @param params a populated SpatialParameters or NULL
*
* @return an Expression representing the spatial operator for use in the
* selection criteria of a named or dynamic TopLink query
*/
public Expression buildExpression(Expression geom1, Object geom2,
SpatialParameters params) {
return buildExpression(geom1.getBuilder(),
new Object[] { geom1, geom2, params == null ?
null :
params.toString() });
}
/**
* Helper method to simplify building an expression where no result comaprison
* to a boolean is required or the default comparison to TRUE is wanted.
*/
public Expression buildExpression(ExpressionBuilder builder,
Object[] arguments) {
return buildExpression(builder, arguments,
getDefaultResultCompareValue());
}
/**
* Construct an expression using the operator and adding all of the provided
* arguments.
*
* @param builder base ExpressionBuilder for the query
* @param arguments an array of values matching the defined operator
* @param resultCompareValue specifies if the operator requires comparison to a
* boolean value and what that value is. If null the operator's
* requiredBooleanComparison value is used.
*
* @return an Expression for use in a named or dynamic query
*/
public Expression buildExpression(ExpressionBuilder builder,
Object[] arguments,
String resultCompareValue) {
if (arguments == null || arguments.length != getNumberOfArguments()) {
throw new IllegalArgumentException("");
}
return buildExpression(builder, getOperator(), arguments,
resultCompareValue);
}
public static Expression buildExpression(ExpressionBuilder builder,
ExpressionOperator operator,
Object[] arguments,
String resultCompareValue) {
FunctionExpression expression = new FunctionExpression();
expression.setBaseExpression(builder);
for (int index = 0; index < arguments.length; index++) {
expression.addChild(Expression.from(arguments[index], builder));
}
expression.setOperator(operator);
Expression resultExp = expression;
if (resultCompareValue != null) {
resultExp = resultExp.equal(resultCompareValue);
}
return resultExp;
}
/**
* Create an expression using adynamically created operator. This method is
* intended for use when the set of operators supported does not include one
* that is required or a custom operator is in use.
*/
public static Expression buildExpression(ExpressionBuilder builder,
String operatorName,
Object[] arguments,
String resultCompareValue) {
ExpressionOperator operator =
createOperator(operatorName, arguments.length);
return buildExpression(builder, operator, arguments,
resultCompareValue);
}
}