AnalyticAggregator
Objects that implement the AnalyticFunction interface are not
responsible for maintaining or using the partition, order by, or window clauses.
It is AnalyticAggregator's responsibility. Because the
Analytic class needs to know all of the
partition, order by, and window clauses for every AnalyticFunction, it
only accepts AnalyticAggregators. The AnalyticAggregator
class does the following:
- Implements AnalyticFunction.
- Wraps an AnalyticFunction that is supplied to it. It delegates
all AnalyticFunction calls to the wrapped function.
- Maintains references to a PartitionClause, an OrderByClause,
and a WindowClause.
Builder Class
The AnalyticAggregator class defines a static nested class "Builder"
that follows the Builder pattern. This Builder class builds an
AnalyticAggregator that can be supplied to the Analytic
class. It has some methods that can be used to control how the resultant
AnalyticAggregator behaves.
- setAnalyticFunction(AnalyticFunction func) - This method is
required, or build() will throw an Exception. This method supplies
the AnalyticFunction that the AnalyticAggregator will
wrap.
- setPartition(PartitionClause partition) - This method is optional
and supplies a PartitionClause. Create a PartitionClause
by supplying a List of properties.
PartitionClause partition = new PartitionClause(Arrays.asList("prop1", "prop2"));
Separate partitions of data have no effect on each other's processing.
- setOrderBy(OrderByClause orderBy) - This method is optional and
supplies an OrderByClause. Create a OrderByClause
by supplying a List of OrderByElements.
OrderByClause orderBy = new OrderByClause(Arrays.asList(
new OrderByElement("prop3"),
new OrderByElement("prop4 DESC NULLS LAST")
));
Data is iterated, and the sliding window is populated, in the order specified by
the OrderByClause.
- setWindow(WindowClause window) - This method is optional and
supplies a WindowClause. Create a WindowClause
by supplying a mode and optional window boundaries.
WindowClause window1 = new WindowClause(WindowClause.Type.ROWS, 2, 3);
The window window1 describes a sliding window that contains data going
back 2 rows and going forward 3 rows. A value of 0 means the current
row, and a value of null means unbounded.
WindowClause window2 = new WindowClause(WindowClause.Type.RANGE, null, 0);
The window window2 describes a sliding window that contains data going
back indefinitely (to the beginning of the partition) and stopping at a value that
is the same as the the current row. If values for the bounds are supplied that
aren't 0 or null, then the OrderByClause is
restricted to exactly one numeric element, so that differences may be calculated to
determine the start or end of the window. Note that if a WindowClause
is not supplied, then it defaults to range(, 0), i.e. "all values from
the beginning of the partition through the value of the current row". Also, some
AnalyticFunctions may not take a
user-given window clause and may supply their own.
- build() - This method builds an AnalyticAggregator
object that can be used to perform the actual analytic operations. This method
should be called last, after all of the desired "setter" methods above have been
called.
Each setter method above returns the same Builder object, so that calls may be
chained, e.g.
AnalyticAggregator ana = new AnalyticAggregator.Builder()
.setAnalyticFunction(anaFunc)
.setPartition(partition)
.setOrderBy(orderBy)
.setWindow(window)
.build();
Factory Method
The AnalyticAggregator class defines a static Factory Method called getAnalytic
that takes as its only argument an analytic specification string,
in the format (no newlines):
ananame(property) [partitionBy(prop1[, prop2, ...])]
[orderBy(prop1 [ASC|DESC] [NULLS [FIRST|LAST]] [, prop2 ... ]]
[[rows|range]([start], [end])]
where "ananame" is name of the AnalyticFunction class, minus any suffix such as
"Aggregator", "AnalyticAggregator", or "Analytic", and "property" is the property
string normally sent to the AnalyticFunction's constructor. This method assumes
the following suffixes, in order, until it finds the proper class:
- AnalyticAggregator - This is given the highest precedence, to
allow a subclass of an Aggregator that doesn't implement
AnalyticFunction to be supplied, to take precedence over a same-named
Aggregator. E.g.
MaxAnalyticAggregator takes
precedence over MaxAggregator here.
- Aggregator - This is given the second highest precedence, to allow
an Aggregator to implement AnalyticFunction without
needing to subclass it just to provide a different name. Most
built-in Aggregators are like
this.
- Analytic - This given the lowest precedence, to permit
analytic-only AnalyticFunctions to be created. Such names won't be
found by Aggregator.getAggregator because they are not intended for
aggregate use -- only analytic use. Most built-in
AnalyticFunctions are like this.
This factory method is an alternative to directly instantiating AnalyticAggregators
in code. It may return an existing, unused AnalyticAggregator that is already in
the internal cache. Such a cached AnalyticAggregator would be the desired type and
have the same property, partition clause, order by clause, and window clause to
process.