/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.query.algebra;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import info.aduna.collections.iterators.Iterators;
/**
* A tuple operator that groups tuples that have a specific set of equivalent
* variable bindings, and that can apply aggregate functions on the grouped
* results.
*
* @author David Huynh
* @author Arjohn Kampman
*/
public class Group extends UnaryTupleOperator {
/*-----------*
* Variables *
*-----------*/
private Set<String> groupBindings = new LinkedHashSet<String>();
private List<GroupElem> groupElements = new ArrayList<GroupElem>();
/*--------------*
* Constructors *
*--------------*/
public Group(TupleExpr arg) {
super(arg);
}
public Group(TupleExpr arg, Iterable<String> groupBindingNames) {
this(arg);
setGroupBindingNames(groupBindingNames);
}
public Group(TupleExpr arg, Iterable<String> groupBindingNames, Iterable<GroupElem> groupElements) {
this(arg, groupBindingNames);
setGroupElements(groupElements);
}
/*---------*
* Methods *
*---------*/
public Set<String> getGroupBindingNames() {
return Collections.unmodifiableSet(groupBindings);
}
public void addGroupBindingName(String bindingName) {
groupBindings.add(bindingName);
}
public void setGroupBindingNames(Iterable<String> bindingNames) {
groupBindings.clear();
Iterators.addAll(bindingNames.iterator(), groupBindings);
}
public List<GroupElem> getGroupElements() {
return Collections.unmodifiableList(groupElements);
}
public void addGroupElement(GroupElem groupElem) {
groupElements.add(groupElem);
}
public void setGroupElements(Iterable<GroupElem> elements) {
this.groupElements.clear();
Iterators.addAll(elements.iterator(), this.groupElements);
}
public Set<String> getAggregateBindingNames() {
Set<String> bindings = new HashSet<String>();
for (GroupElem binding : groupElements) {
bindings.add(binding.getName());
}
return bindings;
}
@Override
public Set<String> getBindingNames() {
Set<String> bindingNames = new LinkedHashSet<String>();
bindingNames.addAll(getGroupBindingNames());
bindingNames.addAll(getAggregateBindingNames());
return bindingNames;
}
public <X extends Exception> void visit(QueryModelVisitor<X> visitor)
throws X
{
visitor.meet(this);
}
@Override
public <X extends Exception> void visitChildren(QueryModelVisitor<X> visitor)
throws X
{
super.visitChildren(visitor);
for (GroupElem ge : groupElements) {
ge.visit(visitor);
}
}
@Override
public void replaceChildNode(QueryModelNode current, QueryModelNode replacement)
{
int index = groupElements.indexOf(current);
if (index >= 0) {
groupElements.set(index, (GroupElem)replacement);
replacement.setParentNode(this);
}
else {
super.replaceChildNode(current, replacement);
}
}
@Override
public Group clone() {
Group clone = (Group)super.clone();
clone.setGroupBindingNames(getGroupBindingNames());
List<GroupElem> elementsClone = new ArrayList<GroupElem>(getGroupElements().size());
for (GroupElem ge : getGroupElements()) {
elementsClone.add(ge.clone());
}
clone.setGroupElements(elementsClone);
return clone;
}
}