/*
* Copyright (c) 2011-2015 EPFL DATA Laboratory
* Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE)
*
* All rights reserved.
*
* 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 ch.epfl.data.squall.operators;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.commons.lang.ArrayUtils;
import ch.epfl.data.squall.storage.BasicStore;
import ch.epfl.data.squall.types.Type;
import ch.epfl.data.squall.visitors.OperatorVisitor;
public class MultiAggregateOperator extends OneToOneOperator implements AggregateOperator {
private static Logger LOG = Logger.getLogger(MultiAggregateOperator.class);
private static final long serialVersionUID = 1L;
private final List<AggregateOperator> _opList;
public MultiAggregateOperator(List<AggregateOperator> opList, Map map) {
_opList = opList;
}
@Override
public void accept(OperatorVisitor ov) {
ov.visit(this);
}
@Override
public void clearStorage() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public List<String> getContent() {
throw new RuntimeException(
"Preaggregation with MultiAggregateOperator does not work yet.");
}
@Override
public DistinctOperator getDistinct() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public List getExpressions() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public List getGroupByColumns() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public ProjectOperator getGroupByProjection() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
private int getNumGroupByColumns(AggregateOperator agg) {
int result = 0;
final List<Integer> groupByColumns = agg.getGroupByColumns();
if (groupByColumns != null)
result += groupByColumns.size();
final ProjectOperator groupByProjection = agg.getGroupByProjection();
if (groupByProjection != null)
result += groupByProjection.getExpressions().size();
return result;
}
@Override
public int getNumTuplesProcessed() {
for (final AggregateOperator agg : _opList)
return agg.getNumTuplesProcessed();
// the result of the first operator, but this is the same for all
// the AggregateOperators
return 0;
}
@Override
public BasicStore getStorage() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public Type getType() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public boolean hasGroupBy() {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public boolean isBlocking() {
return true;
}
@Override
public String printContent() {
final StringBuilder sb = new StringBuilder();
int i = 0;
for (final AggregateOperator agg : _opList) {
sb.append("\nAggregation ").append(i).append("\n")
.append(agg.printContent());
i++;
}
return sb.toString();
}
@Override
public List<String> processOne(List<String> tuple, long lineageTimestamp) {
// this will work only if they have the same groupBy
// otherwise the result of process is not important at all
final List<String> result = new ArrayList<String>();
int i = 0;
for (final AggregateOperator agg : _opList) {
final List<List<String>> current = agg.process(tuple, lineageTimestamp);
// AggregateOperator should return only one tuple
if (current.size() != 1) {
LOG.warn("The aggregate operator " + agg + " returned zero or more than one tuple:" + current);
}
if (i == 0)
result.addAll(current.get(0));
else {
// for all beside the first result we exclude the groupBy
// columns
// because of preaggra(gations, there might be multiple groupBy
// columns (it's not A-B|res, but A|B|res)
// we know that all of them are at the beginning
final int numGB = getNumGroupByColumns(agg);
result.addAll(current.get(0).subList(numGB, current.get(0).size()));
}
i++;
}
return result;
}
@Override
public Object runAggregateFunction(Object value, List tuple) {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public Object runAggregateFunction(Object value1, Object value2) {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public AggregateOperator setDistinct(DistinctOperator distinct) {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public AggregateOperator setGroupByColumns(int... hashIndexes) {
return setGroupByColumns(Arrays
.asList(ArrayUtils.toObject(hashIndexes)));
}
@Override
public AggregateOperator setGroupByColumns(List groupByColumns) {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public AggregateOperator setGroupByProjection(ProjectOperator projection) {
throw new UnsupportedOperationException(
"You are not supposed to call this method from MultiAggregateOperator.");
}
@Override
public AggregateOperator SetWindowSemantics(int windowRangeInSeconds,
int windowSlideInSeconds) {
throw new RuntimeException("Not implemented yet");
}
@Override
public int[] getWindowSemanticsInfo() {
throw new RuntimeException("Not implemented yet");
}
@Override
public AggregateOperator SetWindowSemantics(int windowRangeInSeconds) {
throw new RuntimeException("Not implemented yet");
}
}