package hep.aida.ref.xml;
import hep.aida.ICloud1D;
import hep.aida.ICloud2D;
import hep.aida.ICloud3D;
import hep.aida.IDataPointSet;
import hep.aida.IFunction;
import hep.aida.IHistogram1D;
import hep.aida.IHistogram2D;
import hep.aida.IHistogram3D;
import hep.aida.IManagedObject;
import hep.aida.IProfile1D;
import hep.aida.IProfile2D;
import hep.aida.ITuple;
import hep.aida.ref.*;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Creates a proxy object for AIDA IManagedObject,
* which can be stored in a tree. This proxy objects
* are to be used with AidaXMLStore and "zip" format only.
*
* @author The AIDA Team at SLAC
*/
public class AidaObjectProxy {
public static IManagedObject createProxy(AidaXMLStore store, String path, String type) {
Class proxyClass = getClassForType(type);
Class[] interfaces = { IManagedObject.class, ObjectProvider.class, proxyClass };
InvocationHandler handler = new AidaProxyInvocationHandler(store, path);
Object proxyObject = Proxy.newProxyInstance(AidaObjectProxy.class.getClassLoader(), interfaces, handler);
//System.out.println("\n*** Proxy :: name="+((IManagedObject) proxyObject).name()+", type="+((IManagedObject) proxyObject).type()+", path="+path);
return (IManagedObject) proxyObject;
}
public interface ObjectProvider {
public IManagedObject getManagedObject();
}
private static Class getClassForType(String nodeType) {
Class clazz = IManagedObject.class;
if (nodeType.toLowerCase().indexOf("icloud1d") >= 0) clazz = ICloud1D.class;
else if (nodeType.toLowerCase().indexOf("icloud2d") >= 0) clazz = ICloud2D.class;
else if (nodeType.toLowerCase().indexOf("icloud3d") >= 0) clazz = ICloud3D.class;
else if (nodeType.toLowerCase().indexOf("idatapointset") >= 0) clazz = IDataPointSet.class;
else if (nodeType.toLowerCase().indexOf("ifunction") >= 0) clazz = IFunction.class;
else if (nodeType.toLowerCase().indexOf("ihistogram1d") >= 0) clazz = IHistogram1D.class;
else if (nodeType.toLowerCase().indexOf("ihistogram2d") >= 0) clazz = IHistogram2D.class;
else if (nodeType.toLowerCase().indexOf("ihistogram3d") >= 0) clazz = IHistogram3D.class;
else if (nodeType.toLowerCase().indexOf("iprofile1d") >= 0) clazz = IProfile1D.class;
else if (nodeType.toLowerCase().indexOf("iprofile2d") >= 0) clazz = IProfile2D.class;
else if (nodeType.toLowerCase().indexOf("ituple") >= 0) clazz = ITuple.class;
return clazz;
}
private static class AidaProxyInvocationHandler implements InvocationHandler {
private String name;
private String path;
private AidaXMLStore store;
private SoftReference backend;
AidaProxyInvocationHandler(AidaXMLStore store, String path) {
this.path = path;
this.store = store;
String tmpPath = path;
int index = tmpPath.lastIndexOf(".");
if (index >= 0) {
tmpPath = tmpPath.substring(0, index);
}
this.name = AidaUtils.parseName(tmpPath);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
int nArgs = args == null ? 0 : args.length;
if (nArgs ==0) {
if ("name" .equals(methodName)) return name;
if ("hashCode".equals(methodName)) return new Integer(path.hashCode());
if ("toString".equals(methodName)) return name;
if ("type" .equals(methodName)) return ManagedObject.typeForClass(proxy.getClass());
} else if (nArgs == 1) {
if ("equals" .equals(methodName)) return Boolean.valueOf(proxy == args[0]);
}
if (backend == null || backend.get() == null) {
//System.out.println("Conversion of "+name+" caused by call to "+methodName);
//RuntimeException e = new RuntimeException();
//e.printStackTrace();
IManagedObject mo = store.readManagedObject(path);
backend = new SoftReference(mo);
}
if ("getManagedObject".equals(methodName)) return (IManagedObject) backend.get();
return method.invoke((IManagedObject) backend.get(), args);
}
}
}