package org.reldb.rel.v0.values; import java.io.PrintStream; import org.reldb.rel.exceptions.*; import org.reldb.rel.v0.generator.Generator; import org.reldb.rel.v0.storage.RelDatabase; import org.reldb.rel.v0.types.Type; import org.reldb.rel.v0.types.TypeAlpha; import org.reldb.rel.v0.types.userdefined.Possrep; import org.reldb.rel.v0.types.userdefined.PossrepComponent; import org.reldb.rel.v0.vm.Context; public class ValueAlpha extends ValueAbstract { private static final long serialVersionUID = 0; private String initialTypeName; private String typeName; private Value[] internal; private int possrepNumber; private volatile boolean hasBeenSerializablyCloned = false; // Create new user-defined value. public ValueAlpha(Generator generator, TypeAlpha type, Value v[], int possrepNumber) { super(generator); // TODO - rewrite this constructor to deal with multiple inheritance. initialTypeName = type.getTypeName(); typeName = initialTypeName; this.possrepNumber = possrepNumber; internal = new Value[type.getComponentCount()]; Possrep possrep = type.getPossrep(possrepNumber); int possrepComponentCount = possrep.getComponentCount(); if (v.length != possrepComponentCount) throw new ExceptionFatal("RS0384: select parameter count != POSSREP component count."); for (int componentIndex = 0; componentIndex < possrepComponentCount; componentIndex++) internal[possrep.getComponent(componentIndex).getComponentIndex()] = v[componentIndex]; } // Create default user-defined value. public ValueAlpha(Generator generator, TypeAlpha type) { super(generator); initialTypeName = type.getTypeName(); typeName = initialTypeName; internal = new Value[type.getComponentCount()]; this.possrepNumber = -1; } /** Obtain a serializable clone of this value. */ public Value getSerializableClone() { // TODO - this is vastly questionable; replace it. Needed to prevent failures due (probably) to failing comparisons to self. if (hasBeenSerializablyCloned) return this; for (int i=0; i<internal.length; i++) internal[i] = (internal[i]==null) ? null : internal[i].getSerializableClone(); hasBeenSerializablyCloned = true; return this; } public void loaded(Generator generator) { super.loaded(generator); for (Value v: internal) if (v != null) v.loaded(generator); } public void setMST(TypeAlpha mst) { if (!typeName.equals(mst.getTypeName())) { typeName = mst.getTypeName(); possrepNumber = 0; } } public int hashCode() { int code = 0; for (Value v: internal) if (v != null) code += v.hashCode(); return code; } @Override public String getTypeName() { return typeName; } public Value getComponentValue(int offsetInValue) { return internal[offsetInValue]; } public void setComponentValue(int offsetInValue, Value value) { internal[offsetInValue] = value; } private void noConversions() { throw new ExceptionSemantic("RS0269: Cannot convert a " + typeName + " to a primitive value."); } /** Convert this to a primitive boolean. */ public boolean booleanValue() { noConversions(); return false; } /** Convert this to a primitive long. */ public long longValue() { noConversions(); return 0; } /** Convert this to a primitive double. */ public double doubleValue() { noConversions(); return 0.0; } /** Convert this to a primitive string. */ public String stringValue() { String out = null; for (int i=0; i<internal.length; i++) out = ((out == null) ? "" : out + ", ") + ((internal[i] == null) ? "null" : internal[i].toString()); return ((out == null) ? "" : out); } public boolean equals(Object o) { throw new ExceptionFatal("RS0385: Bogus 'equals' performed on ALPHA!"); } public int compareTo(Value v) { // TODO - rewrite this compareTo to deal with multiple inheritance boolean allNull = true; int comparison = 0; for (int i=0; i<internal.length; i++) { Value v1 = internal[i]; Value v2 = ((ValueAlpha)v).internal[i]; if (v1 == null && v2 == null) comparison = 0; else if (v1 != null && v2 == null) comparison = 1; else if (v1 == null && v2 != null) comparison = -1; else { comparison = v1.compareTo(v2); allNull = false; } if (comparison != 0) break; } // Handle the case of types with no elements if (comparison == 0 && allNull) return getTypeName().compareTo(v.getTypeName()); return comparison; } public String toString() { String out = "{"; for (int i=0; i<internal.length; i++) { if (i>0) out += "|"; out += (internal[i] == null) ? "<null>" : internal[i].toString(); } return out + "}"; } /** Return the MST of this value. */ public Type getType(RelDatabase database) { Generator generator = getGenerator(); Type mst = database.loadType(generator, typeName); if (mst == null) { mst = database.loadType(generator, initialTypeName); setMST((TypeAlpha)mst); } if (mst == null) throw new ExceptionFatal("RS0387: Unable to load MST " + initialTypeName); return mst; } /** Output this Value to a PrintStream. */ public void toStream(Context context, Type contextualType, PrintStream p, int depth) { if (contextualType == null) throw new ExceptionFatal("RS0388: contextualType is null."); TypeAlpha udt; int possrepIndex = -1; Type type = getType(context.getVirtualMachine().getRelDatabase()); if (type == null) { udt = (TypeAlpha)contextualType; if (udt.getPossrepCount() <= 0) possrepIndex = -1; else possrepIndex = 0; } else { udt = (TypeAlpha)type; possrepIndex = possrepNumber; } if (possrepIndex == -1) p.print(udt.getTypeName() + "()"); else { Possrep possrep; while ((possrep = udt.getPossrep(possrepIndex)) == null) { TypeAlpha superudt = udt.getSupertype(); if (superudt == null) { p.print(udt.getTypeName() + "()"); return; } udt = superudt; } p.print(((possrep.getName() == null) ? udt.getTypeName() : possrep.getName()) + "("); for (int i=0; i < possrep.getComponentCount(); i++) { if (i > 0) p.print(", "); PossrepComponent component = possrep.getComponent(i); Value v = internal[component.getComponentIndex()]; if (v != null) v.toStream(context, component.getType(), p, depth + 1); else { p.print("\"[null-" + udt.getTypeName() + "-null]\""); System.out.println("ValueAlpha: invalid component at " + component.getComponentIndex() + " size of internal is " + internal.length + " type is " + udt.getTypeName()); for (int x=0; x<internal.length; x++) System.out.println("ValueAlpha: internal[" + x + "] is " + internal[x]); } } p.print(")"); } } }