/* * Copyright 2014, Tuplejump Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.tuplejump.stargate.lucene.query.function; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.tuplejump.stargate.lucene.Options; import com.tuplejump.stargate.lucene.Type; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.impl.Utf8Generator; import org.codehaus.jackson.io.IOContext; import org.codehaus.jackson.util.BufferRecycler; import org.codehaus.jackson.util.ByteArrayBuilder; import org.mvel2.compiler.ExecutableStatement; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collection; /** * User: satya */ public class Group { public static final ThreadLocal<BufferRecycler> bufferThreadLocal = new ThreadLocal<BufferRecycler>() { @Override protected BufferRecycler initialValue() { return new BufferRecycler(); } }; Options options; AggregateFactory[] aggregatesToCalculate; String[] groupByFields; Multimap<Tuple, Aggregate> groups = ArrayListMultimap.create(); ExecutableStatement[] groupByExpressions; public Group(Options options, AggregateFactory[] aggregatesToCalculate, String[] groupByFields, ExecutableStatement[] groupByExpressions) { this.options = options; this.aggregatesToCalculate = aggregatesToCalculate; this.groupByExpressions = groupByExpressions; this.groupByFields = groupByFields; } public void addTuple(Tuple tuple) { Tuple key = tuple.project(groupByFields, groupByExpressions); Collection<Aggregate> groupValue = groups.get(key); if (groupValue.isEmpty()) { for (AggregateFactory aggregateFactory : aggregatesToCalculate) { Type valueType = AggregateFunction.getLuceneType(options, aggregateFactory.getField()); Aggregate aggregate = aggregateFactory.getAggregate(valueType); aggregate.aggregate(tuple); groups.put(key, aggregate); } } else { for (Aggregate aggregate : groupValue) { aggregate.aggregate(tuple); } } } public ByteBuffer toByteBuffer() throws IOException { BufferRecycler bufferRecycler = bufferThreadLocal.get(); ByteArrayBuilder bytes = new ByteArrayBuilder(bufferRecycler); IOContext ioContext = new IOContext(bufferRecycler, bytes, false); JsonGenerator gen = new Utf8Generator(ioContext, 0, null, bytes); gen.enable(JsonGenerator.Feature.QUOTE_FIELD_NAMES); gen.enable(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS); gen.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); writeJson(gen); gen.flush(); bytes.flush(); bytes.close(); return ByteBuffer.wrap(bytes.toByteArray()); } public void writeJson(JsonGenerator gen) throws IOException { gen.writeStartObject(); gen.writeFieldName("groups"); gen.writeStartArray(); for (Tuple tuple : groups.keySet()) { gen.writeStartObject(); gen.writeFieldName("group"); tuple.writeJson(gen); gen.writeFieldName("aggregations"); gen.writeStartArray(); Collection<Aggregate> aggregates = groups.get(tuple); for (Aggregate aggregate : aggregates) { aggregate.writeJson(gen); } gen.writeEndArray(); gen.writeEndObject(); } gen.writeEndArray(); gen.writeEndObject(); } }