diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java b/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java index f7fe3e49f0a..ef84edfb729 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java @@ -18,31 +18,84 @@ */ package org.elasticsearch.search.aggregations; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; + +import static java.util.Collections.unmodifiableMap; /** - * Represents a set of computed addAggregation. + * Represents a set of {@link Aggregation}s */ -public interface Aggregations extends Iterable { +public abstract class Aggregations implements Iterable { + + protected List aggregations = Collections.emptyList(); + protected Map aggregationsAsMap; + + protected Aggregations() { + } + + protected Aggregations(List aggregations) { + this.aggregations = aggregations; + } + + /** + * Iterates over the {@link Aggregation}s. + */ + @Override + public final Iterator iterator() { + return aggregations.stream().map((p) -> (Aggregation) p).iterator(); + } /** * The list of {@link Aggregation}s. */ - List asList(); + public final List asList() { + return Collections.unmodifiableList(aggregations); + } /** * Returns the {@link Aggregation}s keyed by aggregation name. */ - Map asMap(); + public final Map asMap() { + return getAsMap(); + } /** * Returns the {@link Aggregation}s keyed by aggregation name. */ - Map getAsMap(); + public final Map getAsMap() { + if (aggregationsAsMap == null) { + Map newAggregationsAsMap = new HashMap<>(aggregations.size()); + for (Aggregation aggregation : aggregations) { + newAggregationsAsMap.put(aggregation.getName(), aggregation); + } + this.aggregationsAsMap = unmodifiableMap(newAggregationsAsMap); + } + return aggregationsAsMap; + } /** * Returns the aggregation that is associated with the specified name. */ - A get(String name); + @SuppressWarnings("unchecked") + public final A get(String name) { + return (A) asMap().get(name); + } + + @Override + public final boolean equals(Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + return aggregations.equals(((Aggregations) obj).aggregations); + } + + @Override + public final int hashCode() { + return Objects.hash(getClass(), aggregations); + } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java b/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java index c835c47c148..64c9e4794c3 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java @@ -27,27 +27,18 @@ import org.elasticsearch.search.aggregations.InternalAggregation.ReduceContext; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; import static java.util.Collections.emptyMap; -import static java.util.Collections.unmodifiableMap; /** * An internal implementation of {@link Aggregations}. */ -public class InternalAggregations implements Aggregations, ToXContent, Streamable { +public final class InternalAggregations extends Aggregations implements ToXContent, Streamable { public static final InternalAggregations EMPTY = new InternalAggregations(); - private List aggregations = Collections.emptyList(); - - private Map aggregationsAsMap; - private InternalAggregations() { } @@ -55,55 +46,7 @@ public class InternalAggregations implements Aggregations, ToXContent, Streamabl * Constructs a new addAggregation. */ public InternalAggregations(List aggregations) { - this.aggregations = aggregations; - } - - /** - * Iterates over the {@link Aggregation}s. - */ - @Override - public Iterator iterator() { - return aggregations.stream().map((p) -> (Aggregation) p).iterator(); - } - - /** - * The list of {@link Aggregation}s. - */ - @Override - public List asList() { - return aggregations.stream().map((p) -> (Aggregation) p).collect(Collectors.toList()); - } - - /** - * Returns the {@link Aggregation}s keyed by map. - */ - @Override - public Map asMap() { - return getAsMap(); - } - - /** - * Returns the {@link Aggregation}s keyed by map. - */ - @Override - public Map getAsMap() { - if (aggregationsAsMap == null) { - Map newAggregationsAsMap = new HashMap<>(); - for (InternalAggregation aggregation : aggregations) { - newAggregationsAsMap.put(aggregation.getName(), aggregation); - } - this.aggregationsAsMap = unmodifiableMap(newAggregationsAsMap); - } - return aggregationsAsMap; - } - - /** - * @return the aggregation of the specified name. - */ - @SuppressWarnings("unchecked") - @Override - public A get(String name) { - return (A) asMap().get(name); + super(aggregations); } /** @@ -118,21 +61,16 @@ public class InternalAggregations implements Aggregations, ToXContent, Streamabl } // first we collect all aggregations of the same type and list them together - Map> aggByName = new HashMap<>(); for (InternalAggregations aggregations : aggregationsList) { - for (InternalAggregation aggregation : aggregations.aggregations) { - List aggs = aggByName.get(aggregation.getName()); - if (aggs == null) { - aggs = new ArrayList<>(aggregationsList.size()); - aggByName.put(aggregation.getName(), aggs); - } - aggs.add(aggregation); + for (Aggregation aggregation : aggregations.aggregations) { + List aggs = aggByName.computeIfAbsent( + aggregation.getName(), k -> new ArrayList<>(aggregationsList.size())); + aggs.add((InternalAggregation)aggregation); } } // now we can use the first aggregation of each list to handle the reduce of its list - List reducedAggregations = new ArrayList<>(); for (Map.Entry> entry : aggByName.entrySet()) { List aggregations = entry.getValue(); @@ -142,41 +80,33 @@ public class InternalAggregations implements Aggregations, ToXContent, Streamabl return new InternalAggregations(reducedAggregations); } - /** The fields required to write this addAggregation to xcontent */ - static class Fields { - public static final String AGGREGATIONS = "aggregations"; - } - @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { if (aggregations.isEmpty()) { return builder; } - builder.startObject(Fields.AGGREGATIONS); + builder.startObject("aggregations"); toXContentInternal(builder, params); return builder.endObject(); } /** - * Directly write all the addAggregation without their bounding object. Used by sub-addAggregation (non top level addAggregation) + * Directly write all the aggregations without their bounding object. Used by sub-aggregations (non top level aggs) */ public XContentBuilder toXContentInternal(XContentBuilder builder, Params params) throws IOException { for (Aggregation aggregation : aggregations) { - ((InternalAggregation) aggregation).toXContent(builder, params); + ((InternalAggregation)aggregation).toXContent(builder, params); } return builder; } + public static InternalAggregations readAggregations(StreamInput in) throws IOException { InternalAggregations result = new InternalAggregations(); result.readFrom(in); return result; } - public static InternalAggregations readOptionalAggregations(StreamInput in) throws IOException { - return in.readOptionalStreamable(InternalAggregations::new); - } - @Override public void readFrom(StreamInput in) throws IOException { aggregations = in.readList(stream -> in.readNamedWriteable(InternalAggregation.class)); @@ -186,20 +116,8 @@ public class InternalAggregations implements Aggregations, ToXContent, Streamabl } @Override + @SuppressWarnings("unchecked") public void writeTo(StreamOutput out) throws IOException { - out.writeNamedWriteableList(aggregations); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || getClass() != obj.getClass()) { - return false; - } - return aggregations.equals(((InternalAggregations) obj).aggregations); - } - - @Override - public int hashCode() { - return Objects.hash(getClass(), aggregations); + out.writeNamedWriteableList((List)aggregations); } }