package org.reldb.rel.v0.values; import java.io.PrintStream; import java.util.Vector; import org.reldb.rel.exceptions.ExceptionFatal; import org.reldb.rel.v0.generator.Generator; import org.reldb.rel.v0.types.*; import org.reldb.rel.v0.vm.Context; public class ValueTuple extends ValueAbstract implements Projectable { private static final long serialVersionUID = 0; private Value[] values; /** Create a new tuple with default attribute values. */ public ValueTuple(Generator generator, TypeTuple type) { super(generator); Heading heading = type.getHeading(); this.values = new Value[heading.getDegree()]; int i = 0; for (Attribute attribute: heading.getAttributes()) this.values[i++] = attribute.getType().getDefaultValue(generator); loaded(generator); } /** Create a new tuple given an array of tuple attribute values. */ public ValueTuple(Generator generator, Value[] values) { super(generator); this.values = values; loaded(generator); } public void loaded(Generator generator) { super.loaded(generator); for (Value value: values) if (value != null) value.loaded(generator); } /** Obtain a serializable clone of this value. */ public Value getSerializableClone() { Value[] newValues = new Value[values.length]; for (int i=0; i<values.length; i++) newValues[i] = values[i].getSerializableClone(); return new ValueTuple(getGenerator(), newValues); } public static ValueTuple getEmptyTuple(Generator generator) { return new ValueTuple(generator, TypeTuple.getEmptyTupleType()); } /** Return the array of ValueS in this tuple. */ public Value[] getValues() { return values; } /** Assign ValueS to this tuple from the source ValueTuple according to an AttributeMap. */ public void assign(AttributeMap map, ValueTuple source) { map.assign(this.values, source); } /** Create a new tuple by projecting this ValueTuple according to an AttributeMap. */ public Value project(AttributeMap map) { return map.project(getGenerator(), this); } /** Create a new tuple by a disjoint join of this and another ValueTuple. */ public ValueTuple joinDisjoint(ValueTuple right) { Value[] valueArray = new Value[values.length + right.values.length]; System.arraycopy(values, 0, valueArray, 0, values.length); System.arraycopy(right.values, 0, valueArray, values.length, right.values.length); return new ValueTuple(getGenerator(), valueArray); } /** Create a new tuple by a join of this and another ValueTuple. Assume that common attributes * have matching values, as (perhaps) determined by isJoinable(). */ public ValueTuple join(JoinMap map, ValueTuple right) { return map.join(getGenerator(), this, right); } /** Create a new tuple by a join of this and another ValueTuple. Throw an exception if * common attributes do not have matching values. */ public ValueTuple joinChecked(JoinMap map, ValueTuple right) { return map.joinChecked(getGenerator(), this, right); } /** Create a new tuple by removing an attribute specified by a given zero-based index. */ public ValueTuple shrink(int attributeIndex) { Value[] valueArray = new Value[values.length - 1]; System.arraycopy(values, 0, valueArray, 0, attributeIndex); System.arraycopy(values, attributeIndex + 1, valueArray, attributeIndex, values.length - attributeIndex - 1); return new ValueTuple(getGenerator(), valueArray); } public String getTypeName() { return "TUPLE"; } /** Output this Value to a PrintStream. */ public void toStream(Context context, Type type, PrintStream p, int depth) { p.print("TUPLE {"); Vector<Attribute> attributes = ((TypeTuple)type).getHeading().getAttributes(); if (values.length != attributes.size()) throw new ExceptionFatal("RS0452: Bad tuple. Heading " + type + " says degree = " + attributes.size() + " but tuple " + toString() + " says degree = " + values.length + "."); int i = 0; for (Attribute attribute: attributes) { if (i > 0) p.print(", "); p.print(attribute.getName() + " "); values[i].toStream(context, attribute.getType(), p, depth + 1); i++; } p.print("}"); } public int hashCode() { int code = 0; for (Value value: values) code += value.hashCode(); return code; } public int compareTo(Value v) { int comparison = 0; for (int i=0; i<values.length; i++) { comparison = values[i].compareTo(((ValueTuple)v).values[i]); if (comparison != 0) break; } return comparison; } public String toString() { String out = null; for (Value value: values) out = ((out == null) ? "" : out + ", ") + ((value == null) ? "null" : value.toString()); return "TUPLE {" + ((out == null) ? "" : out) + "}"; } public String toCSV() { StringBuffer str = new StringBuffer(""); for (Value value: values) { str.append(value.toString() + ","); } str.deleteCharAt(str.length()-1); return str.toString().trim(); } }