001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.query.algebra;
007:
008: import java.util.ArrayList;
009: import java.util.Collections;
010: import java.util.HashSet;
011: import java.util.LinkedHashSet;
012: import java.util.List;
013: import java.util.Set;
014:
015: import info.aduna.collections.iterators.Iterators;
016:
017: /**
018: * A tuple operator that groups tuples that have a specific set of equivalent
019: * variable bindings, and that can apply aggregate functions on the grouped
020: * results.
021: *
022: * @author David Huynh
023: * @author Arjohn Kampman
024: */
025: public class Group extends UnaryTupleOperator {
026:
027: /*-----------*
028: * Variables *
029: *-----------*/
030:
031: private Set<String> groupBindings = new LinkedHashSet<String>();
032:
033: private List<GroupElem> groupElements = new ArrayList<GroupElem>();
034:
035: /*--------------*
036: * Constructors *
037: *--------------*/
038:
039: public Group(TupleExpr arg) {
040: super (arg);
041: }
042:
043: public Group(TupleExpr arg, Iterable<String> groupBindingNames) {
044: this (arg);
045: setGroupBindingNames(groupBindingNames);
046: }
047:
048: public Group(TupleExpr arg, Iterable<String> groupBindingNames,
049: Iterable<GroupElem> groupElements) {
050: this (arg, groupBindingNames);
051: setGroupElements(groupElements);
052: }
053:
054: /*---------*
055: * Methods *
056: *---------*/
057:
058: public Set<String> getGroupBindingNames() {
059: return Collections.unmodifiableSet(groupBindings);
060: }
061:
062: public void addGroupBindingName(String bindingName) {
063: groupBindings.add(bindingName);
064: }
065:
066: public void setGroupBindingNames(Iterable<String> bindingNames) {
067: groupBindings.clear();
068: Iterators.addAll(bindingNames.iterator(), groupBindings);
069: }
070:
071: public List<GroupElem> getGroupElements() {
072: return Collections.unmodifiableList(groupElements);
073: }
074:
075: public void addGroupElement(GroupElem groupElem) {
076: groupElements.add(groupElem);
077: }
078:
079: public void setGroupElements(Iterable<GroupElem> elements) {
080: this .groupElements.clear();
081: Iterators.addAll(elements.iterator(), this .groupElements);
082: }
083:
084: public Set<String> getAggregateBindingNames() {
085: Set<String> bindings = new HashSet<String>();
086:
087: for (GroupElem binding : groupElements) {
088: bindings.add(binding.getName());
089: }
090:
091: return bindings;
092: }
093:
094: @Override
095: public Set<String> getBindingNames() {
096: Set<String> bindingNames = new LinkedHashSet<String>();
097:
098: bindingNames.addAll(getGroupBindingNames());
099: bindingNames.addAll(getAggregateBindingNames());
100:
101: return bindingNames;
102: }
103:
104: public <X extends Exception> void visit(QueryModelVisitor<X> visitor)
105: throws X {
106: visitor.meet(this );
107: }
108:
109: @Override
110: public <X extends Exception> void visitChildren(
111: QueryModelVisitor<X> visitor) throws X {
112: super .visitChildren(visitor);
113:
114: for (GroupElem ge : groupElements) {
115: ge.visit(visitor);
116: }
117: }
118:
119: @Override
120: public void replaceChildNode(QueryModelNode current,
121: QueryModelNode replacement) {
122: int index = groupElements.indexOf(current);
123: if (index >= 0) {
124: groupElements.set(index, (GroupElem) replacement);
125: replacement.setParentNode(this );
126: } else {
127: super .replaceChildNode(current, replacement);
128: }
129: }
130:
131: @Override
132: public Group clone() {
133: Group clone = (Group) super .clone();
134:
135: clone.setGroupBindingNames(getGroupBindingNames());
136:
137: List<GroupElem> elementsClone = new ArrayList<GroupElem>(
138: getGroupElements().size());
139: for (GroupElem ge : getGroupElements()) {
140: elementsClone.add(ge.clone());
141: }
142:
143: clone.setGroupElements(elementsClone);
144:
145: return clone;
146: }
147: }
|