package Sequenic.T2.Seq; import java.io.IOException; import java.io.InvalidClassException; import java.io.NotSerializableException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.lang.reflect.InvocationTargetException; import Sequenic.T2.Pool; import Sequenic.T2.Engines.Util; /** * Utilities to (de)Serialize MkValSteps * * @author Jeiel Schalkwijk * */ public final class Externalize_MkValStep { //typeCodes. They are negative, since positive values are reserved for REF. private final static int CONST_NULL = -1; private final static int CONST_NON_NULL = -2; private final static int CREATE_OBJECT = -3; private final static int CREATE_COLLECTION_LIKE = -4; //if REF.index >= Byte.MAX_VALUE (or < 0), use this. private final static int REF_INT = -5; public static void write(MkValStep ms, ObjectOutput out) throws IOException { if(ms==null) { throw new NullPointerException(); } else if(ms instanceof REF) { int i = ((REF)ms).index; if(i>=0 && i=0) return new REF(code); else if(code==REF_INT) return new REF(in.readInt()); else if(code==CONST_NULL) return CONST.nullConst(Class.forName((String) in.readObject())); else if(code==CONST_NON_NULL) return CONST.nonNull(in.readObject()); else if(code==CREATE_OBJECT) return ObsoleteMkValStep.read(true,in); else if(code==CREATE_COLLECTION_LIKE) return ObsoleteMkValStep.read(false,in); else throw new InvalidClassException("Unknown type code for a MkValStep... "+ code); } private static ObsoleteMkValStep externalize(CREATE_OBJECT co) { Class[] paramTypes = co.con.getParameterTypes(); String[] classNames = new String[paramTypes.length+1]; for (int i = 0; i < paramTypes.length; i++) { classNames[i] = paramTypes[i].getName(); } classNames[paramTypes.length] = co.con.getDeclaringClass().getName(); return new ObsoleteMkValStep(StringList.create(classNames), co.params, co.indexOfNewObject, true); } private static ObsoleteMkValStep externalize(CREATE_COLLECTION_LIKE ms) { return new ObsoleteMkValStep(StringList.create(ms.elementType.getName(), ms.collectionType) , ms.elements, ms.size, false); } /** * This class can serialize CREATE_OBJECT and CREATE_COLLECTION_LIKE. * It can also represent Obsolete versions of these MkValSteps. * * See also resolve. * * @author Jeiel Schalkwijk * */ private static final class ObsoleteMkValStep extends MkValStep { /* An array of type names. * * For CREATE_OBJECT this contains: * types = [x.getName() | x in constructor.paramTypes] ++ [constructor.getDeclaredClass.getName] * * FOR CREATE_COLLECTION_LIKE this contains 2 type names: * types = [ElementType.getName(), CollectionType] */ private final StringList types; /* Either the values of the constructor arguments (CREATE_OBJECT) * Or, the values of the elements in the collection (CREATE_COLLECTION_LIKE) */ private final MkValStep[] vals; //The size of the CREATE_COLLECTION_LIKE, or the index of the CREATE_OBJECT private final int size_or_index; //True if this class is an instance of CREATE_OBJECT, //false if it's an instance of CREATE_COLLECTION_LIKE private final boolean isCREATE_OBJECT; private ObsoleteMkValStep(StringList types, MkValStep[] vals, int sizeOrIndex, boolean isCREATE_OBJECT) { this.types = types; this.vals = vals; size_or_index = sizeOrIndex; this.isCREATE_OBJECT = isCREATE_OBJECT; } /** Returns a CREATE_OBJECT or CREATE_COLLECTION_LIKE if possible, * but if the MkValStep is obsolete, it returns this. * * @return */ private MkValStep resolve() { //First recursively resolve the vals for(int i = 0; i