package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.rascalmpl.interpreter.TypeReifier;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.IMap;
import org.rascalmpl.value.INode;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.IValueFactory;
import org.rascalmpl.value.exceptions.FactTypeUseException;
import org.rascalmpl.value.impl.AbstractValueFactoryAdapter;
import org.rascalmpl.value.io.BinaryValueReader;
import org.rascalmpl.value.io.BinaryValueWriter;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeFactory;
import org.rascalmpl.value.type.TypeStore;
import org.rascalmpl.values.uptr.RascalValueFactory;
import org.nustaq.serialization.FSTBasicObjectSerializer;
import org.nustaq.serialization.FSTClazzInfo;
import org.nustaq.serialization.FSTClazzInfo.FSTFieldInfo;
import org.nustaq.serialization.FSTObjectInput;
import org.nustaq.serialization.FSTObjectOutput;
/**
* FSTSerializableIValue acts as a serializer and wrapper for IValues
* - On writing a FSTSerializableIValue oject is written
* - On reading, the wrapped IValue is returned.
*
*/
@SuppressWarnings("deprecation")
public class FSTSerializableIValue extends FSTBasicObjectSerializer implements Serializable {
private static final long serialVersionUID = 6704614265562953320L;
private transient static IValueFactory vf;
private transient static TypeStore store;
private transient static TypeReifier tr;
private transient static ByteArrayOutputStream byteStream;
private transient static BinaryValueWriter binaryWriter;
private transient static BinaryValueReader binaryReader;
private transient static Type valueType;
public static void initSerialization(IValueFactory vfactory, TypeStore ts){
vf = vfactory;
store = ts;
store.extendStore(RascalValueFactory.getStore());
tr = new TypeReifier(vf);
byteStream = new ByteArrayOutputStream(); // TODO should we remove it as well?
binaryWriter = new BinaryValueWriter();
binaryReader = new BinaryValueReader();
valueType = TypeFactory.getInstance().valueType();
}
private transient IValue value;
/**
* Constructor used for registration of this serializer
*/
public FSTSerializableIValue() {
}
/**
* Constructor used to wrap an IValue to be serialized
*/
public FSTSerializableIValue(IValue value) {
this.value = value;
}
IValue getValue(){
return value;
}
@Override
public void writeObject(FSTObjectOutput out, Object toWrite,
FSTClazzInfo clzInfo, FSTFieldInfo arg3, int arg4)
throws IOException {
byteStream.reset();
binaryWriter.write(((FSTSerializableIValue)toWrite).getValue(), byteStream, false);
byte[] bytes = byteStream.toByteArray();
out.writeObject(bytes);
}
@Override
public void readObject(FSTObjectInput in, Object toRead, FSTClazzInfo clzInfo, FSTClazzInfo.FSTFieldInfo referencedBy)
{
System.out.println("FSTSerializableIValue.readObject");
}
@Override
public Object instantiate(@SuppressWarnings("rawtypes") Class objectClass, FSTObjectInput in, FSTClazzInfo serializationInfo, FSTClazzInfo.FSTFieldInfo referencee, int streamPosition)
{
FSTSerializableIValue res = null;
try {
byte[] bytes = (byte[]) in.readObject();
ByteArrayInputStream bs = new ByteArrayInputStream(bytes);
IValue v = binaryReader.read(new RascalValuesValueFactory(), store, valueType, bs);
bs.close();
// TODO: why is this not handled by RascalValuesValueFactory????
if(v.getType().isNode()){
INode nd = (INode) v;
if(nd.getName().equals("type")){
//System.out.println("FSTSerializableIValue.instantiate: " + v);
java.util.Map<Type,Type> bindings = new HashMap<Type,Type>();
bindings.put(RascalValueFactory.TypeParam, tr.symbolToType((IConstructor) nd.get(0), (IMap) nd.get(1)));
v = vf.constructor(RascalValueFactory.Type_Reified.instantiate(bindings), nd.get(0), nd.get(1));
}
}
in.registerObject(v,streamPosition,serializationInfo, referencee);
return v;
} catch (FactTypeUseException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
private class RascalValuesValueFactory extends AbstractValueFactoryAdapter {
public RascalValuesValueFactory() {
super(vf);
}
@Override
public INode node(String name, IValue... children) {
// System.out.println("node1: " + name);
IConstructor res = specializeType(name, children);
return res != null ? res: vf.node(name, children);
}
@Override
public INode node(String name, Map<String, IValue> annotations, IValue... children) throws FactTypeUseException {
// System.out.println("node2: " + name);
IConstructor res = specializeType(name, children);
return res != null ? res: vf.node(name, annotations, children);
}
@Override
public INode node(String name, IValue[] children, Map<String, IValue> keyArgValues) throws FactTypeUseException {
// System.out.println("node3: " + name);
IConstructor res = specializeType(name, children);
return res != null ? res: vf.node(name, children, keyArgValues);
}
private IConstructor specializeType(String name, IValue... children) {
if ("type".equals(name)
//&& children.length == 2
//&& children[0].getType().isSubtypeOf(Factory.Type_Reified.getFieldType(0))
//&& children[1].getType().isSubtypeOf(Factory.Type_Reified.getFieldType(1))
) {
java.util.Map<Type,Type> bindings = new HashMap<Type,Type>();
bindings.put(RascalValueFactory.TypeParam, tr.symbolToType((IConstructor) children[0], (IMap) children[1]));
return vf.constructor(RascalValueFactory.Type_Reified.instantiate(bindings), children[0], children[1]);
}
return null;
}
@Override
public IConstructor constructor(Type constructor, IValue[] children,
Map<String, IValue> keyArgValues) {
System.out.println("constructor1: " + constructor.getName());
IConstructor res = specializeType(constructor.getName(), children);
return res != null ? res: super.constructor(constructor, children, keyArgValues);
}
@Override
public IConstructor constructor(Type constructor, Map<String, IValue> annotations, IValue... children)
throws FactTypeUseException {
System.out.println("constructor2: " + constructor.getName());
IConstructor res = specializeType(constructor.getName(), children);
return res != null ? res: super.constructor(constructor, children, annotations);
}
//
//
// @Override
// public INode node(String name, IValue[] children,
// Map<String, IValue> keyArgValues) throws FactTypeUseException {
// System.out.println("node: " + name);
// IConstructor res = specializeType(name, children, keyArgValues);
// return res != null ? res: vf.node(name, children, keyArgValues);
// }
//
// public IConstructor specializeType(String name, IValue[] children,
// Map<String, IValue> keyArgValues) {
// System.out.println("specializeType: " + name);
// if(name.equals("type")
// && children.length == 2
// && children[0].getType().isSubtypeOf(Factory.Type_Reified.getFieldType(0))
// && children[1].getType().isSubtypeOf(Factory.Type_Reified.getFieldType(1))) {
//
// java.util.Map<Type,Type> bindings = new HashMap<Type,Type>();
// bindings.put(Factory.TypeParam, tr.symbolToType((IConstructor) children[0], (IMap) children[1]));
//
// return vf.constructor(Factory.Type_Reified.instantiate(bindings), children[0], children[1]);
// }
// return null;
// }
}
}