001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.query.impl;
007:
008: import java.util.Arrays;
009: import java.util.Iterator;
010: import java.util.LinkedHashSet;
011: import java.util.List;
012: import java.util.Set;
013:
014: import org.openrdf.model.Value;
015: import org.openrdf.query.Binding;
016: import org.openrdf.query.BindingSet;
017:
018: /**
019: * A List-based implementation of the {@link BindingSet} interface.
020: *
021: * @author Arjohn Kampman
022: */
023: public class ListBindingSet implements BindingSet {
024:
025: /*-----------*
026: * Variables *
027: *-----------*/
028:
029: private List<String> bindingNames;
030:
031: private List<? extends Value> values;
032:
033: /*--------------*
034: * Constructors *
035: *--------------*/
036:
037: /**
038: * Creates a new List-based BindingSet containing the supplied bindings.
039: * <em>The supplied list of binding names is assumed to be constant</em>;
040: * care should be taken that the contents of this list doesn't change after
041: * supplying it to this solution. The number of supplied values must be equal
042: * to the number of the binding names.
043: *
044: * @param names
045: * The binding names.
046: * @param values
047: * The binding values.
048: */
049: public ListBindingSet(List<String> names, Value... values) {
050: this (names, Arrays.asList(values));
051: }
052:
053: /**
054: * Creates a new List-based BindingSet containing the supplied bindings.
055: * <em>The supplied lists are assumed to be constant</em>; care should be
056: * taken that the contents of these lists don't change after supplying them
057: * to this solution. The number of supplied values must be equal to the
058: * number of the binding names.
059: *
060: * @param bindingNames
061: * The binding names.
062: * @param values
063: * The binding values.
064: */
065: public ListBindingSet(List<String> bindingNames,
066: List<? extends Value> values) {
067: assert bindingNames.size() == values.size() : "number of binding names and values not equal";
068:
069: this .bindingNames = bindingNames;
070: this .values = values;
071: }
072:
073: /*---------*
074: * Methods *
075: *---------*/
076:
077: public Set<String> getBindingNames() {
078: return new LinkedHashSet<String>(bindingNames);
079: }
080:
081: public Value getValue(String bindingName) {
082: int idx = bindingNames.indexOf(bindingName);
083:
084: if (idx != -1) {
085: return values.get(idx);
086: }
087:
088: return null;
089: }
090:
091: public Binding getBinding(String bindingName) {
092: Value value = getValue(bindingName);
093:
094: if (value != null) {
095: return new BindingImpl(bindingName, value);
096: }
097:
098: return null;
099: }
100:
101: public boolean hasBinding(String bindingName) {
102: return getValue(bindingName) != null;
103: }
104:
105: public Iterator<Binding> iterator() {
106: return new ListBindingSetIterator();
107: }
108:
109: public int size() {
110: int size = 0;
111:
112: for (Value value : values) {
113: if (value != null) {
114: size++;
115: }
116: }
117:
118: return size;
119: }
120:
121: @Override
122: public boolean equals(Object other) {
123: if (this == other) {
124: return true;
125: }
126:
127: if (other instanceof BindingSet) {
128: int otherSize = 0;
129:
130: // Compare other's bindings to own
131: for (Binding binding : (BindingSet) other) {
132: Value ownValue = getValue(binding.getName());
133:
134: if (!binding.getValue().equals(ownValue)) {
135: // Unequal bindings for this name
136: return false;
137: }
138:
139: otherSize++;
140: }
141:
142: // All bindings have been matched, sets are equal if this solution
143: // doesn't have any additional bindings.
144: int this Size = 0;
145: for (Value value : values) {
146: if (value != null) {
147: this Size++;
148: }
149: }
150:
151: return this Size == otherSize;
152: }
153:
154: return false;
155: }
156:
157: @Override
158: public int hashCode() {
159: int hashCode = 0;
160:
161: for (Binding binding : this ) {
162: hashCode ^= binding.hashCode();
163: }
164:
165: return hashCode;
166: }
167:
168: @Override
169: public String toString() {
170: StringBuilder sb = new StringBuilder(32 * size());
171:
172: sb.append('[');
173:
174: Iterator<Binding> iter = iterator();
175: while (iter.hasNext()) {
176: sb.append(iter.next().toString());
177: if (iter.hasNext()) {
178: sb.append(';');
179: }
180: }
181:
182: sb.append(']');
183:
184: return sb.toString();
185: }
186:
187: /*------------------------------------*
188: * Inner class ListBindingSetIterator *
189: *------------------------------------*/
190:
191: private class ListBindingSetIterator implements Iterator<Binding> {
192:
193: private int index = -1;
194:
195: public ListBindingSetIterator() {
196: findNextElement();
197: }
198:
199: private void findNextElement() {
200: for (index++; index < values.size(); index++) {
201: if (values.get(index) != null) {
202: break;
203: }
204: }
205: }
206:
207: public boolean hasNext() {
208: return index < values.size();
209: }
210:
211: public Binding next() {
212: Binding result = new BindingImpl(bindingNames.get(index),
213: values.get(index));
214: findNextElement();
215: return result;
216: }
217:
218: public void remove() {
219: throw new UnsupportedOperationException();
220: }
221: }
222: }
|