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: package org.geotools.feature.visitor;
017:
018: import org.geotools.factory.CommonFactoryFinder;
019: import org.geotools.feature.Feature;
020: import org.geotools.feature.FeatureType;
021: import org.geotools.filter.FilterFactoryFinder;
022: import org.geotools.filter.IllegalFilterException;
023: import org.opengis.filter.FilterFactory;
024: import org.opengis.filter.expression.Expression;
025:
026: /**
027: * Calculates the minimum value of an attribute.
028: *
029: * @author Cory Horner, Refractions
030: *
031: * @since 2.2.M2
032: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/feature/visitor/MinVisitor.java $
033: */
034: public class MinVisitor implements FeatureCalc {
035: private Expression expr;
036: Comparable minvalue;
037: Comparable curvalue;
038: boolean visited = false;
039:
040: public MinVisitor(String attributeTypeName) {
041: FilterFactory factory = CommonFactoryFinder
042: .getFilterFactory(null);
043: expr = factory.property(attributeTypeName);
044: }
045:
046: public MinVisitor(int attributeTypeIndex, FeatureType type)
047: throws IllegalFilterException {
048: FilterFactory factory = CommonFactoryFinder
049: .getFilterFactory(null);
050: expr = factory.property(type.getAttributeType(
051: attributeTypeIndex).getName());
052: }
053:
054: public MinVisitor(String attrName, FeatureType type)
055: throws IllegalFilterException {
056: FilterFactory factory = CommonFactoryFinder
057: .getFilterFactory(null);
058: expr = factory.property(type.getAttributeType(attrName)
059: .getName());
060: }
061:
062: public MinVisitor(Expression expr) throws IllegalFilterException {
063: this .expr = expr;
064: }
065:
066: /**
067: * Visitor function, which looks at each feature and finds the minimum.
068: *
069: * @param feature the feature to be visited
070: */
071: public void visit(Feature feature) {
072: Object attribValue = expr.evaluate(feature);
073:
074: if (attribValue == null) {
075: return; //attribute is null, therefore skip
076: }
077:
078: curvalue = (Comparable) attribValue;
079: if ((!visited) || (curvalue.compareTo(minvalue) < 0)) {
080: minvalue = curvalue;
081: visited = true;
082: }
083: }
084:
085: /**
086: * Get the min value.
087: *
088: * @return Minimum value
089: *
090: * @throws IllegalStateException DOCUMENT ME!
091: */
092: public Comparable getMin() {
093: /**
094: * Return the minimum value derived from the collection
095: */
096: if (!visited) {
097: throw new IllegalStateException(
098: "Must visit before min value is ready!");
099: }
100:
101: return minvalue;
102: }
103:
104: public void reset() {
105: /**
106: * Reset the count and current minimum
107: */
108: this .visited = false;
109: this .minvalue = new Integer(0);
110: }
111:
112: public CalcResult getResult() {
113: if (!visited) {
114: throw new IllegalStateException(
115: "Must visit before min value is ready!");
116: }
117:
118: return new MinResult(minvalue);
119: }
120:
121: public Expression getExpression() {
122: return expr;
123: }
124:
125: /**
126: * Overwrites the result stored by the visitor. This should only be used by
127: * optimizations which will tell the visitor the answer rather than
128: * visiting all features.
129: *
130: * <p></p>
131: * For 'min', the value stored is of type 'Comparable'.
132: *
133: * @param result
134: */
135: public void setValue(Object result) {
136: visited = true;
137: minvalue = (Comparable) result;
138: }
139:
140: public static class MinResult extends AbstractCalcResult {
141: private Comparable minValue;
142:
143: public MinResult(Comparable newMinValue) {
144: minValue = newMinValue;
145: }
146:
147: public Object getValue() {
148: Comparable min = (Comparable) minValue;
149:
150: return min;
151: }
152:
153: public boolean isCompatible(CalcResult targetResults) {
154: //list each calculation result which can merge with this type of result
155: if (targetResults instanceof MinResult) {
156: return true;
157: }
158:
159: return false;
160: }
161:
162: public CalcResult merge(CalcResult resultsToAdd) {
163: if (!isCompatible(resultsToAdd)) {
164: throw new IllegalArgumentException(
165: "Parameter is not a compatible type");
166: }
167:
168: if (resultsToAdd instanceof MinResult) {
169: //take the smaller of the 2 values
170: Comparable toAdd = (Comparable) resultsToAdd.getValue();
171: Comparable newMin = minValue;
172:
173: if (newMin.getClass() != toAdd.getClass()) { //2 different data types, therefore convert
174: Class bestClass = CalcUtil.bestClass(new Object[] {
175: toAdd, newMin });
176: if (bestClass != toAdd.getClass())
177: toAdd = (Comparable) CalcUtil.convert(toAdd,
178: bestClass);
179: if (bestClass != newMin.getClass())
180: newMin = (Comparable) CalcUtil.convert(newMin,
181: bestClass);
182: }
183: if (newMin.compareTo(toAdd) > 0) {
184: newMin = toAdd;
185: }
186:
187: return new MinResult(newMin);
188: } else {
189: throw new IllegalArgumentException(
190: "The CalcResults claim to be compatible, but the appropriate merge method has not been implemented.");
191: }
192: }
193: }
194: }
|