package org.basex.query.item; import static org.basex.query.QueryText.*; import static org.basex.query.util.Err.*; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.iter.ValueIter; import org.basex.util.InputInfo; /** * Sequence, containing at least two items. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public abstract class Seq extends Value { /** Length. */ final long size; /** * Constructor. * @param s size */ Seq(final long s) { this(s, AtomType.SEQ); } /** * Constructor, specifying a type. * @param s size * @param t type */ Seq(final long s, final Type t) { super(t); size = s; } /** * Returns a value representation of the specified items. * @param v value * @param s size * @return resulting item or sequence */ public static Value get(final Item[] v, final int s) { return s == 0 ? Empty.SEQ : s == 1 ? v[0] : new ItemSeq(v, s); } @Override public final long size() { return size; } @Override public final Item item(final QueryContext ctx, final InputInfo ii) throws QueryException { throw XPSEQ.thrw(ii, this); } @Override public final Item test(final QueryContext ctx, final InputInfo ii) throws QueryException { return ebv(ctx, ii); } @Override public final ValueIter iter() { return new ValueIter() { int c; @Override public Item get(final long i) { return itemAt(i); } @Override public Item next() { return c < size ? itemAt(c++) : null; } @Override public boolean reset() { c = 0; return true; } @Override public long size() { return size; } @Override public Value value() { return Seq.this; } }; } @Override public final int hash(final InputInfo ii) throws QueryException { // final hash function because equivalent sequences *must* produce the // same hash value, otherwise they get lost in hash maps. // example: hash(RangeSeq(1 to 3)) == hash(ItrSeq(1, 2, 3)) // == hash(ItemSeq(Itr(1), Itr(2), Itr(3))) int h = 1; for(long v = Math.min(size, 5); --v >= 0;) h = 31 * h + itemAt(v).hash(ii); return h; } @Override public String toString() { final StringBuilder sb = new StringBuilder(PAR1); for(int i = 0; i < size; ++i) { sb.append(i != 0 ? SEP : "").append(itemAt(i)); if(sb.length() <= 32 || i + 1 == size) continue; // output is chopped to prevent too long error strings sb.append(SEP + DOTS); break; } return sb.append(PAR2).toString(); } }