org.geotools.feature.visitor.GroupByVisitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gt-main Show documentation
Show all versions of gt-main Show documentation
The main module contains the GeoTools public interfaces that are used by
other GeoTools modules (and GeoTools applications). Where possible we make
use industry standard terms as provided by OGC and ISO standards.
The formal GeoTools public api consists of gt-metadata, jts and the gt-main module.
The main module contains the default implementations that are available provided
to other GeoTools modules using our factory system. Factories are obtained from
an appropriate FactoryFinder, giving applications a chance configure the factory
used using the Factory Hints facilities.
FilterFactory ff = CommonFactoryFinder.getFilterFactory();
Expression expr = ff.add( expression1, expression2 );
If you find yourself using implementation specific classes chances are you doing it wrong:
Expression expr = new AddImpl( expression1, expressiom2 );
/*
* 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureVisitor;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.expression.Expression;
import org.opengis.util.ProgressListener;
/** Group features by one or several attributes and applies an aggregator visitor to each group. */
public class GroupByVisitor implements FeatureCalc, FeatureAttributeVisitor {
private final Aggregate aggregate;
private final Expression expression;
private final FeatureCalc visitorProtoType;
private final List groupByAttributes;
private final InMemoryGroupBy inMemoryGroupBy = new InMemoryGroupBy();
private CalcResult optimizationResult = CalcResult.NULL_RESULT;
public GroupByVisitor(
Aggregate aggregateVisitor,
Expression expression,
List groupByAttributes,
ProgressListener progressListener) {
this.aggregate = aggregateVisitor;
this.expression = expression;
this.groupByAttributes = groupByAttributes;
visitorProtoType = aggregateVisitor.create(expression);
}
public boolean wasOptimized() {
return optimizationResult != null && optimizationResult != CalcResult.NULL_RESULT;
}
public boolean wasVisited() {
return !inMemoryGroupBy.groupByIndexes.isEmpty();
}
/**
* This method computes and returns the group by visitor result. If the computation was
* optimized the optimization result is returned otherwise the result is computed in memory. If
* for some reason an optimization result exists and there are visited features, an in memory
* computation is performed and is merged with the existing optimization results.
*
* @return group by visitor result
*/
@Override
public CalcResult getResult() {
// do a in memory computation for any visited feature
Map, CalcResult> results = inMemoryGroupBy.visit();
// create the result, if no feature was visited this will be an empty result that can be
// safely merged
GroupByResult result = new GroupByResult(results, aggregate, groupByAttributes);
if (optimizationResult == CalcResult.NULL_RESULT) {
// there is no optimization result so we just return the created one
return result;
}
// an optimization result exists, we merge both
return optimizationResult.merge(result);
}
@Override
public void visit(Feature feature) {
inMemoryGroupBy.index((SimpleFeature) feature);
}
public Expression getExpression() {
return expression;
}
public FeatureVisitor getAggregateVisitor() {
return visitorProtoType;
}
public List getGroupByAttributes() {
return groupByAttributes;
}
/**
* Methods that allow optimizations to directly set the group by visitor result instead of
* computing it visiting all the features. Aggregate visitor results are wrapped with the
* appropriate feature calculation type.
*
* @param value the group by visitor result
*/
public void setValue(List value) {
Map, CalcResult> results = new HashMap<>();
for (GroupByRawResult groupByRawResult : value) {
// wrap the aggregate visitor result with the appropriate feature calculation type
results.put(
groupByRawResult.groupByValues,
aggregate.wrap(expression, groupByRawResult.visitorValue));
}
// create a new group by result using the raw values returned by the optimization
GroupByResult newResult = new GroupByResult(results, aggregate, groupByAttributes);
if (optimizationResult == CalcResult.NULL_RESULT) {
// if no current result we simply return the new one
optimizationResult = newResult;
} else {
// if a result already exists we merge it with the new one
optimizationResult = optimizationResult.merge(newResult);
}
}
/** Helper class that should be used by optimizations to set the results. */
public static class GroupByRawResult {
final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy