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.AttributeType;
020: import org.geotools.feature.Feature;
021: import org.geotools.feature.FeatureType;
022: import org.geotools.feature.visitor.AverageVisitor.AverageResult;
023: import org.geotools.feature.visitor.CountVisitor.CountResult;
024: import org.geotools.filter.IllegalFilterException;
025: import org.opengis.filter.FilterFactory;
026: import org.opengis.filter.expression.Expression;
027:
028: /**
029: * Calculates the Sum of an attribute (of a FeatureVisitor)
030: *
031: * @author Cory Horner, Refractions
032: *
033: * @since 2.2.M2
034: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/feature/visitor/SumVisitor.java $
035: */
036: public class SumVisitor implements FeatureCalc {
037: private Expression expr;
038: SumStrategy strategy;
039:
040: public SumVisitor(int attributeTypeIndex, FeatureType type)
041: throws IllegalFilterException {
042: FilterFactory factory = CommonFactoryFinder
043: .getFilterFactory(null);
044: AttributeType attributeType = type
045: .getAttributeType(attributeTypeIndex);
046: expr = factory.property(attributeType.getName());
047: createStrategy(attributeType.getType());
048: }
049:
050: public SumVisitor(String attrName, FeatureType type)
051: throws IllegalFilterException {
052: FilterFactory factory = CommonFactoryFinder
053: .getFilterFactory(null);
054: AttributeType attributeType = type.getAttributeType(attrName);
055: expr = factory.property(attributeType.getName());
056: createStrategy(attributeType.getType());
057: }
058:
059: public SumVisitor(Expression expr) throws IllegalFilterException {
060: this .expr = expr;
061: }
062:
063: /**
064: * Factory method
065: *
066: * @param type The Class of the attributeType
067: *
068: * @return The correct strategy class (which returns the correct data type)
069: */
070: private static SumStrategy createStrategy(Class type) {
071: if (type == Integer.class) {
072: return new IntegerSumStrategy();
073: } else if (type == Double.class) {
074: return new DoubleSumStrategy();
075: } else if (type == Long.class) {
076: return new LongSumStrategy();
077: } else if (type == Float.class) {
078: return new FloatSumStrategy();
079: }
080:
081: return null;
082: }
083:
084: public void visit(Feature feature) {
085: Object value = expr.evaluate(feature);
086:
087: if (strategy == null) {
088: strategy = createStrategy(value.getClass());
089: }
090:
091: strategy.add(value);
092: }
093:
094: public Expression getExpression() {
095: return expr;
096: }
097:
098: public Object getSum() {
099: return strategy.getResult();
100: }
101:
102: public void setValue(Object newSum) {
103: strategy = createStrategy(newSum.getClass());
104: strategy.add(newSum);
105: }
106:
107: public void reset() {
108: strategy = null;
109: }
110:
111: public CalcResult getResult() {
112: return new SumResult(strategy);
113: }
114:
115: interface SumStrategy {
116: public void add(Object value);
117:
118: public Object getResult();
119: }
120:
121: static class DoubleSumStrategy implements SumStrategy {
122: double number = 0;
123:
124: public void add(Object value) {
125: number += ((Number) value).doubleValue();
126: }
127:
128: public Object getResult() {
129: return new Double(number);
130: }
131: }
132:
133: static class FloatSumStrategy implements SumStrategy {
134: float number = 0;
135:
136: public void add(Object value) {
137: number += ((Number) value).floatValue();
138: }
139:
140: public Object getResult() {
141: return new Float(number);
142: }
143: }
144:
145: static class LongSumStrategy implements SumStrategy {
146: long number = 0;
147:
148: public void add(Object value) {
149: number += ((Number) value).longValue();
150: }
151:
152: public Object getResult() {
153: return new Long(number);
154: }
155: }
156:
157: static class IntegerSumStrategy implements SumStrategy {
158: int number = 0;
159:
160: public void add(Object value) {
161: number += ((Number) value).intValue();
162: }
163:
164: public Object getResult() {
165: return new Integer(number);
166: }
167: }
168:
169: public static class SumResult extends AbstractCalcResult {
170: private SumStrategy sum;
171:
172: public SumResult(SumStrategy newSum) {
173: sum = newSum;
174: }
175:
176: public Object getValue() {
177: return sum.getResult();
178: }
179:
180: public boolean isCompatible(CalcResult targetResults) {
181: if (targetResults instanceof SumResult)
182: return true;
183: if (targetResults instanceof CountResult)
184: return true;
185: return false;
186: }
187:
188: public CalcResult merge(CalcResult resultsToAdd) {
189: if (!isCompatible(resultsToAdd)) {
190: throw new IllegalArgumentException(
191: "Parameter is not a compatible type");
192: }
193:
194: if (resultsToAdd instanceof SumResult) {
195: //create a new strategy object of the correct dataType
196: Number[] sums = new Number[2];
197: sums[0] = (Number) sum.getResult();
198: sums[1] = (Number) resultsToAdd.getValue();
199: SumStrategy newSum = createStrategy(CalcUtil.getObject(
200: sums).getClass());
201: //add the two sums
202: newSum.add(sums[0]);
203: newSum.add(sums[1]);
204: return new SumResult(newSum);
205: } else if (resultsToAdd instanceof CountResult) {
206: //SumResult + CountResult = AverageResult
207: int count = resultsToAdd.toInt();
208: AverageResult newResult = new AverageResult(count, sum
209: .getResult());
210:
211: return newResult;
212: } else {
213: throw new IllegalArgumentException(
214: "The CalcResults claim to be compatible, but the appropriate merge method has not been implemented.");
215: }
216: }
217: }
218: }
|