Package org.geotools.data.transform

Source Code of org.geotools.data.transform.ExpressionTypeEvaluator

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2012, 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.data.transform;

import org.geotools.filter.function.FilterFunction_Convert;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.feature.type.GeometryType;
import org.opengis.filter.capability.FunctionName;
import org.opengis.filter.expression.Add;
import org.opengis.filter.expression.BinaryExpression;
import org.opengis.filter.expression.Divide;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.ExpressionVisitor;
import org.opengis.filter.expression.Function;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.Multiply;
import org.opengis.filter.expression.NilExpression;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.expression.Subtract;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
* Utility class that tries to figure out the resulting type of an expression against a given
* feature type by using static analysis.
*
* @author Andrea Aime - GeoSolutions
*/
class ExpressionTypeEvaluator implements ExpressionVisitor {

    private SimpleFeatureType schema;
    private CoordinateReferenceSystem crs;

    public ExpressionTypeEvaluator(SimpleFeatureType schema) {
        this.schema = schema;
    }
   
    /**
     * Returns the coordinate reference system of the last encontered geometry property.
     * Unless a filter function that reprojects geometries is used, that's also the crs of the eventual
     * output, in case it's a Geometry, that is.
     * 
     * @return
     */
    public CoordinateReferenceSystem getCoordinateReferenceSystem() {
        return this.crs;
    }

    @Override
    public Object visit(NilExpression expression, Object extraData) {
        return null;
    }

    @Override
    public Object visit(Function f, Object extraData) {
        FunctionName fn = f.getFunctionName();
        if (fn != null && fn.getReturn() != null && fn.getReturn().getType() != Object.class) {
            return fn.getReturn().getType();
        } else if (f instanceof FilterFunction_Convert) {
            // special case for the convert function, which has the return type as
            // a parameter
            return f.getParameters().get(1).evaluate(null, Class.class);
        }

        return null;
    }

    @Override
    public Object visit(Literal expression, Object extraData) {
        if (expression.getValue() == null) {
            return null;
        } else {
            return expression.getValue().getClass();
        }
    }

    @Override
    public Object visit(PropertyName expression, Object extraData) {
        AttributeDescriptor result = expression.evaluate(schema, AttributeDescriptor.class);
        if (result == null) {
            throw new IllegalArgumentException(
                    "Original feature type does not have a property named "
                            + expression.getPropertyName());
        }

        if(result instanceof GeometryDescriptor) {
            this.crs = ((GeometryDescriptor) result).getCoordinateReferenceSystem();
        }
        return result.getType().getBinding();
    }

    private Object visitMathExpression(BinaryExpression expression) {
        Expression ex1 = expression.getExpression1();
        Expression ex2 = expression.getExpression2();

        Class c1 = getMathOperandType(ex1);
        Class c2 = getMathOperandType(ex2);

        if (c1 == Integer.class && c2 == Integer.class) {
            return Integer.class;
        } else if ((c1 == Integer.class || c1 == Long.class)
                && (c2 == Integer.class || c2 == Long.class)) {
            return Long.class;
        } else {
            return Double.class;
        }
    }

    private Class getMathOperandType(Expression expression) {
        Class result = (Class) expression.accept(this, null);

        // not a number, if a literal see if its contents can be cast to one
        if (!(Number.class.isAssignableFrom(result)) && expression instanceof Literal) {
            Double value = expression.evaluate(null, Double.class);
            if (value != null) {
                if (value.longValue() == value.doubleValue()) {
                    // integer type, keep it simple, int or long
                    if ((value < Integer.MAX_VALUE) && value > Integer.MIN_VALUE) {
                        result = Integer.class;
                    } else {
                        result = Long.class;
                    }
                }
            } else {
                result = Double.class;
            }
        }

        return result;
    }

    @Override
    public Object visit(Multiply expression, Object extraData) {
        return visitMathExpression(expression);
    }

    @Override
    public Object visit(Add expression, Object extraData) {
        return visitMathExpression(expression);
    }

    @Override
    public Object visit(Divide expression, Object extraData) {
        return visitMathExpression(expression);
    }

    @Override
    public Object visit(Subtract expression, Object extraData) {
        return visitMathExpression(expression);
    }
}
TOP

Related Classes of org.geotools.data.transform.ExpressionTypeEvaluator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.