blob: e69a421aad25d72fda4cae53dde4f78c40b13448 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Jesper Moller, and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jesper Moller - initial API and implementation
* Jesper Steen Moller - bug 340933 - Migrate to new XPath2 API
*******************************************************************************/
package org.eclipse.wst.xml.xpath2.api;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.ListIterator;
import org.eclipse.wst.xml.xpath2.api.typesystem.ItemType;
import org.eclipse.wst.xml.xpath2.processor.internal.types.SimpleAtomicItemTypeImpl;
import org.eclipse.wst.xml.xpath2.processor.internal.types.builtin.BuiltinTypeLibrary;
import org.eclipse.wst.xml.xpath2.processor.internal.types.builtin.SingleItemSequence;
/**
* @since 2.0
*/
public class ResultBuffer {
private ArrayList<Item> values = new ArrayList<Item>();
public ResultSequence getSequence() {
if (values.size() == 0) return EMPTY;
if (values.size() == 1) return wrap(values.get(0));
return new ArrayResultSequence(values.toArray(new Item[values.size()]));
}
public void clear() {
values.clear();
}
public ResultBuffer add(Item at) {
values.add(at);
return this;
}
public ResultBuffer append(Item at) {
values.add(at);
return this;
}
public ResultBuffer concat(ResultSequence rs) {
values.addAll(collectionWrapper(rs));
return this;
}
public static final class SingleResultSequence implements ResultSequence {
public SingleResultSequence(Item at) {
value = at;
}
private final Item value;
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#getLength()
*/
public int size() {
return 1;
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#getItem(int)
*/
public Item item(int index) {
if (index != 0) throw new IndexOutOfBoundsException("Length is one, you looked up number "+ index);
return value;
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#first()
*/
public Item first() {
return item(0);
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#getItem(int)
*/
public Object value(int index) {
if (index != 0) throw new IndexOutOfBoundsException("Length is one, you looked up number "+ index);
return value.getNativeValue();
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#empty()
*/
public boolean empty() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#first()
*/
public Object firstValue() {
return value.getNativeValue();
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#iterator()
*/
public Iterator iterator() {
return new Iterator() {
boolean seenIt = false;
public final void remove() {
throw new UnsupportedOperationException("ResultSequences are immutable");
}
public final Object next() {
if (! seenIt) {
seenIt = true;
return value;
}
throw new IllegalStateException("This iterator is at its end");
}
public final boolean hasNext() {
return !seenIt;
}
};
}
public ItemType itemType(int index) {
return item(index).getItemType();
}
public ItemType sequenceType() {
return value.getItemType();
}
}
public static final class ArrayResultSequence implements ResultSequence {
private final Item[] results;
public ArrayResultSequence(Item results[]) {
this.results = results;
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#getLength()
*/
public int size() {
return results.length;
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#getItem(int)
*/
public Item item(int index) {
if (index < 0 && index >= results.length) throw new IndexOutOfBoundsException("Index " + index + " is out of alllowed bounds (less that " + results.length);
return results[index];
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#empty()
*/
public boolean empty() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#first()
*/
public Object firstValue() {
return item(0).getNativeValue();
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#first()
*/
public Item first() {
return item(0);
}
/* (non-Javadoc)
* @see org.eclipse.wst.xml.xpath2.api.ResultSequence#iterator()
*/
public Iterator iterator() {
return new Iterator() {
int nextIndex = 0;
public final void remove() {
throw new UnsupportedOperationException("ResultSequences are immutable");
}
public final Object next() {
if (nextIndex < results.length) {
return results[nextIndex++];
}
throw new IllegalStateException("This iterator is at its end");
}
public final boolean hasNext() {
return nextIndex < results.length;
}
};
}
public ItemType itemType(int index) {
if (index < 0 && index >= results.length) throw new IndexOutOfBoundsException("Index " + index + " is out of alllowed bounds (less that " + results.length);
return results[index].getItemType();
}
public ItemType sequenceType() {
return new SimpleAtomicItemTypeImpl(BuiltinTypeLibrary.XS_ANYTYPE, ItemType.OCCURRENCE_ONE_OR_MANY);
}
public Object value(int index) {
return item(index).getNativeValue();
}
}
public int size() {
return values.size();
}
public ListIterator iterator() {
return values.listIterator();
}
public void prepend(ResultSequence rs) {
values.addAll(0, collectionWrapper(rs));
}
private Collection<Item> collectionWrapper(final ResultSequence rs) {
// This is a dummy collections, solely exists for faster inserts into our array
return new Collection<Item>() {
public boolean add(Item arg0) {
return false;
}
public boolean addAll(Collection arg0) {
return false;
}
public void clear() {
}
public boolean contains(Object arg0) {
return false;
}
public boolean containsAll(Collection arg0) {
return false;
}
public boolean isEmpty() {
return rs.empty();
}
public Iterator/*<Item>*/ iterator() {
return rs.iterator();
}
public boolean remove(Object arg0) {
return false;
}
public boolean removeAll(Collection arg0) {
return false;
}
public boolean retainAll(Collection arg0) {
return false;
}
public int size() {
return rs.size();
}
public Object[] toArray() {
return toArray(new Item[size()]);
}
public Object[] toArray(Object[] arg0) {
if (arg0.length < size())
arg0 = new Item[size()];
for (int i = 0; i< size(); ++i) {
arg0[i] = rs.item(i);
}
return arg0;
}
};
}
public final static ResultSequence EMPTY = new ResultSequence() {
public int size() {
return 0;
}
public Item item(int index) {
throw new IndexOutOfBoundsException("Sequence is empty!");
}
public boolean empty() {
return true;
}
public ItemType itemType(int index) {
throw new IndexOutOfBoundsException("Sequence is empty!");
}
public ItemType sequenceType() {
return new SimpleAtomicItemTypeImpl(BuiltinTypeLibrary.XS_ANYTYPE, ItemType.OCCURRENCE_ONE_OR_MANY);
}
public Object value(int index) {
throw new IndexOutOfBoundsException("Sequence is empty!");
}
public Object firstValue() {
throw new IndexOutOfBoundsException("Sequence is empty!");
}
public Item first() {
throw new IndexOutOfBoundsException("Sequence is empty!");
}
public Iterator iterator() {
return new Iterator() {
public void remove() {
throw new UnsupportedOperationException("ResultSequences are immutable");
}
public Object next() {
throw new IllegalStateException("This ResultSequence is empty");
}
public boolean hasNext() {
return false;
}
};
}
};
public Collection<Item> getCollection() {
return this.values;
}
public ResultBuffer concat(Collection/*<Item>*/ others) {
this.values.addAll(others);
return this;
}
public static ResultSequence wrap(Item item) {
if (item instanceof SingleItemSequence)
return (SingleItemSequence)item;
return new SingleResultSequence(item);
}
public Item item(int index) {
return values.get(index);
}
public void addAt(int pos, Item element) {
values.add(pos, element);
}
}