/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2016, 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.feature.visitor; import org.geotools.util.Converters; import org.opengis.filter.expression.Expression; /** * Aggregate functions defined for use with the GeoTools library. * <p> * Aggregates are backed by a {@link FeatureCalc} visitor for direct use with a FeatureCollection * (or use with {@link GroupByVisitor} ). THe {@link #create(Expression)} method is used as a * factory method to configure an appropriate visitor. * <p> * During processing a {@link CalcResult} is used to store intermediate results. Implementations * that handle an aggregate function directly (such as JDBCDataStore) can use can use the wrap * method to generate the expect CalcResult from a calculated raw value. */ public enum Aggregate { AVERAGE { @Override public FeatureCalc create(Expression aggregateAttribute) { return new AverageVisitor(aggregateAttribute); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { return new AverageVisitor.AverageResult( value ); } }, COUNT { @Override public FeatureCalc create(Expression aggregateAttribute) { return new CountVisitor(); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { int count = Converters.convert(value, Integer.class); return new CountVisitor.CountResult( count ); } }, MAX { @Override public FeatureCalc create(Expression aggregateAttribute) { return new MaxVisitor(aggregateAttribute); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { return new MaxVisitor.MaxResult( (Comparable<?>) value ); } }, MEDIAN { @Override public FeatureCalc create(Expression aggregateAttribute) { return new MedianVisitor(aggregateAttribute); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { return new MedianVisitor.MedianResult( value ); } }, MIN { @Override public FeatureCalc create(Expression aggregateAttribute) { return new MinVisitor(aggregateAttribute); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { return new MinVisitor.MinResult( (Comparable<?>) value ); } }, STD_DEV { @Override public FeatureCalc create(Expression expr) { return new StandardDeviationVisitor(expr); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { if (value == null ){ return AbstractCalcResult.NULL_RESULT; } Double deviation = Converters.convert(value, Double.class); return new StandardDeviationVisitor.Result( deviation ); } }, SUM { @Override public FeatureCalc create(Expression expr) { return new SumVisitor(expr); } @Override public CalcResult wrap(Expression aggregateAttribute, Object value) { return new SumVisitor.SumResult(value); } }; /** * Factory method creating a visitor using an aggregate attribute. * * @param expression Expression used to sample collection (often a PropertyName) * @return a new instance of the visitor */ public abstract FeatureCalc create(Expression expression); /** * Wraps a raw value in the appropriate visitor calculation result. The typical usage of this is to wrap values * returned by stores able to handle the visitor (for example the JDBCDataStore). * * @param expression Expression used to sample collection (often a PropertyName) * @param value The raw value to be wrapped * @return value Wrapped in the appropriate visitor calculation result */ public abstract CalcResult wrap(Expression expression, Object value); /** * Helper method that given a visitor name returns the appropriate enum constant. * <p> * The performed match by name is more permissive that the default one. The match will * not be case sensitive and slightly different names can be used (camel case versus snake case). * </p> * @param visitorName the visitor name * @return this enum constant that machs the visitor name */ public static Aggregate valueOfIgnoreCase(String visitorName) { if( "stddev".equalsIgnoreCase(visitorName)){ return Aggregate.STD_DEV; } return valueOf( visitorName.toUpperCase() ); } }