/* * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.query.impl; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.openrdf.model.Value; import org.openrdf.query.Binding; import org.openrdf.query.BindingSet; /** * A List-based implementation of the {@link BindingSet} interface. * * @author Arjohn Kampman */ public class ListBindingSet implements BindingSet { /*-----------* * Variables * *-----------*/ private List<String> bindingNames; private List<? extends Value> values; /*--------------* * Constructors * *--------------*/ /** * Creates a new List-based BindingSet containing the supplied bindings. * <em>The supplied list of binding names is assumed to be constant</em>; * care should be taken that the contents of this list doesn't change after * supplying it to this solution. The number of supplied values must be equal * to the number of the binding names. * * @param names * The binding names. * @param values * The binding values. */ public ListBindingSet(List<String> names, Value... values) { this(names, Arrays.asList(values)); } /** * Creates a new List-based BindingSet containing the supplied bindings. * <em>The supplied lists are assumed to be constant</em>; care should be * taken that the contents of these lists don't change after supplying them * to this solution. The number of supplied values must be equal to the * number of the binding names. * * @param bindingNames * The binding names. * @param values * The binding values. */ public ListBindingSet(List<String> bindingNames, List<? extends Value> values) { assert bindingNames.size() == values.size() : "number of binding names and values not equal"; this.bindingNames = bindingNames; this.values = values; } /*---------* * Methods * *---------*/ public Set<String> getBindingNames() { return new LinkedHashSet<String>(bindingNames); } public Value getValue(String bindingName) { int idx = bindingNames.indexOf(bindingName); if (idx != -1) { return values.get(idx); } return null; } public Binding getBinding(String bindingName) { Value value = getValue(bindingName); if (value != null) { return new BindingImpl(bindingName, value); } return null; } public boolean hasBinding(String bindingName) { return getValue(bindingName) != null; } public Iterator<Binding> iterator() { return new ListBindingSetIterator(); } public int size() { int size = 0; for (Value value : values) { if (value != null) { size++; } } return size; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (other instanceof BindingSet) { int otherSize = 0; // Compare other's bindings to own for (Binding binding : (BindingSet)other) { Value ownValue = getValue(binding.getName()); if (!binding.getValue().equals(ownValue)) { // Unequal bindings for this name return false; } otherSize++; } // All bindings have been matched, sets are equal if this solution // doesn't have any additional bindings. int thisSize = 0; for (Value value : values) { if (value != null) { thisSize++; } } return thisSize == otherSize; } return false; } @Override public int hashCode() { int hashCode = 0; for (Binding binding : this) { hashCode ^= binding.hashCode(); } return hashCode; } @Override public String toString() { StringBuilder sb = new StringBuilder(32 * size()); sb.append('['); Iterator<Binding> iter = iterator(); while (iter.hasNext()) { sb.append(iter.next().toString()); if (iter.hasNext()) { sb.append(';'); } } sb.append(']'); return sb.toString(); } /*------------------------------------* * Inner class ListBindingSetIterator * *------------------------------------*/ private class ListBindingSetIterator implements Iterator<Binding> { private int index = -1; public ListBindingSetIterator() { findNextElement(); } private void findNextElement() { for (index++; index < values.size(); index++) { if (values.get(index) != null) { break; } } } public boolean hasNext() { return index < values.size(); } public Binding next() { Binding result = new BindingImpl(bindingNames.get(index), values.get(index)); findNextElement(); return result; } public void remove() { throw new UnsupportedOperationException(); } } }