001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * Created on May 11, 2005, 6:21 PM
017: */
018: package org.geotools.filter.function;
019:
020: import org.geotools.feature.Feature;
021: import org.geotools.feature.FeatureCollection;
022: import org.geotools.feature.visitor.CalcResult;
023: import org.geotools.feature.visitor.MinVisitor;
024: import org.geotools.filter.AttributeExpression;
025: import org.geotools.filter.Expression;
026: import org.geotools.filter.FunctionExpression;
027: import org.geotools.filter.FunctionExpressionImpl;
028: import org.geotools.filter.IllegalFilterException;
029: import org.geotools.filter.visitor.AbstractFilterVisitor;
030: import java.io.IOException;
031: import java.util.Collections;
032: import java.util.List;
033: import java.util.logging.Level;
034: import java.util.logging.Logger;
035:
036: /**
037: * Calculates the minimum value of an attribute for a given FeatureCollection
038: * and Expression.
039: *
040: * @author James
041: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/filter/function/Collection_MinFunction.java $
042: */
043: public class Collection_MinFunction extends FunctionExpressionImpl
044: implements FunctionExpression {
045: /** The logger for the filter module. */
046: private static final Logger LOGGER = org.geotools.util.logging.Logging
047: .getLogger("org.geotools.filter.function");
048: FeatureCollection previousFeatureCollection = null;
049: Object min = null;
050:
051: /**
052: * Creates a new instance of Collection_MinFunction
053: */
054: public Collection_MinFunction() {
055: super ("Collection_Min");
056: }
057:
058: public int getArgCount() {
059: return 1;
060: }
061:
062: /**
063: * Calculate minimum (using FeatureCalc) - only one parameter is used.
064: *
065: * @param collection collection to calculate the minimum
066: * @param expression Single Expression argument
067: *
068: * @return An object containing the minimum value of the attributes
069: *
070: * @throws IllegalFilterException
071: * @throws IOException
072: */
073: public static CalcResult calculateMin(FeatureCollection collection,
074: Expression expression) throws IllegalFilterException,
075: IOException {
076: MinVisitor minVisitor = new MinVisitor(expression);
077: collection.accepts(minVisitor, null);
078: return minVisitor.getResult();
079: }
080:
081: /**
082: * The provided arguments are evaulated with respect to the
083: * FeatureCollection.
084: *
085: * <p>
086: * For an aggregate function (like min) please use the WFS mandated XPath
087: * syntax to refer to featureMember content.
088: * </p>
089: *
090: * <p>
091: * To refer to all 'X': <code>featureMember/asterisk/X</code>
092: * </p>
093: *
094: * @param args DOCUMENT ME!
095: *
096: * @throws IllegalArgumentException DOCUMENT ME!
097: */
098: public void setParameters(List args) {
099: super .setParameters(args);
100:
101: Expression expr = (Expression) getExpression(0);
102:
103: // if we see "featureMembers/*/ATTRIBUTE" change to "ATTRIBUTE"
104: expr.accept(new AbstractFilterVisitor() {
105: public void visit(AttributeExpression expression) {
106: String xpath = expression.getAttributePath();
107:
108: if (xpath.startsWith("featureMembers/*/")) {
109: xpath = xpath.substring(17);
110: } else if (xpath.startsWith("featureMember/*/")) {
111: xpath = xpath.substring(16);
112: }
113:
114: try {
115: expression.setAttributePath(xpath);
116: } catch (IllegalFilterException e) {
117: // ignore
118: }
119: }
120: });
121: }
122:
123: public Object evaluate(Object feature) {
124: if (feature == null) {
125: return new Integer(0); // no features were visited in the making of this answer
126: }
127: Expression expr = (Expression) getExpression(0);
128: FeatureCollection featureCollection = (FeatureCollection) feature;
129: synchronized (featureCollection) {
130: if (featureCollection != previousFeatureCollection) {
131: previousFeatureCollection = featureCollection;
132: min = null;
133: try {
134: CalcResult result = calculateMin(featureCollection,
135: expr);
136: if (result != null) {
137: min = result.getValue();
138: }
139: } catch (IllegalFilterException e) {
140: LOGGER.log(Level.FINER, e.getLocalizedMessage(), e);
141: } catch (IOException e) {
142: LOGGER.log(Level.FINER, e.getLocalizedMessage(), e);
143: }
144: }
145: }
146: return min;
147: }
148:
149: public void setExpression(Expression e) {
150: setParameters(Collections.singletonList(e));
151: }
152: }
|