// $Id: example1.java,v 1.2 1998/04/11 11:36:54 oliva Exp $

import BR.unicamp.Guarana.*;

/** A few examples of reflexive behavior

    @author Alexandre Oliva
    @version $Revision: 1.2 $
*/
public class example1 {
    static class myMetaObject extends MetaObject {
	public Result handle(final Operation op, final Object ob) {
	    System.out.println("Got operation: "+op);
	    return Result.inspectResult;
	}
	public Result handle(final Result res, final Object ob) {
	    System.out.println("Got result: "+res);
	    return null;
	}
	public void handle(final Message msg, final Object ob) {
	    System.out.println("Got message: "+msg+" for object "+
			       Guarana.toString(ob));
	}
	public MetaObject configure(final Object newObject,
				    final Object object) {
	    if (newObject instanceof myObject) {
		System.out.println("Propagating meta-configuration to "+
				   Guarana.toString(newObject));
		return this;
	    }
	    System.out.println("Not propagating meta-configuration to "+
			       Guarana.toString(newObject));
	    return null;
	}
	public MetaObject reconfigure(final Object object,
				      final MetaObject prev,
				      final MetaObject next) {
	    System.out.println("Rejecting reconfiguration request for "+
			       Guarana.toString(object));
	    return this;
	}
	public void initialize(final OperationFactory fact,
			       final Object obj) {
	    System.out.println("Initializing meta-object for object "+
			       Guarana.toString(obj));
	    try {
		System.out.println("Trying to assign 2 to object's field `i'");
		fact.write(obj.getClass().getDeclaredFields()[0],
			   new Integer(2)).perform();
	    } catch (IllegalAccessException t) {
		System.out.println("Expected failure: "+t);
		System.out.println("meta-object was not associated with base-level object yet.");
	    } catch (ArrayIndexOutOfBoundsException t) {
		System.out.println("Expected failure: "+t);
		System.out.println("couldn't find any fields in object "+
				   Guarana.toString(obj));
	    } catch (Throwable t) {
		System.out.println("Failed: "+t);
	    }
	}
	public void release(final Object obj) {
	    /* will be invoked at reconfigure request, even if
	     * reconfiguration doesn't actually take place. */
	    System.out.println("Releasing object "+obj);
	}
    }
  
    public static class myObject {
	int i;
	myObject createAnother() {
	    return new myObject();
	}
    }

    public static void main(String[] argv) {
	final myObject o = new myObject();
	final MetaObject m = new myMetaObject();
	Guarana.reconfigure(o, null, m);
	synchronized(o) {
	    System.out.println(o.i);
	    o.i = 1;
	    System.out.println(o.i);
	}
	final Object[] a = new Object[3];
	Guarana.reconfigure(a, null, m);
	Guarana.reconfigure(myObject.class, null, new myMetaObject());
	synchronized(a) {
	    System.out.println(a.length);
	    a[0] = a[1] = o;
	    System.out.println(a[1]);
	}
	System.out.println(o.hashCode());
	System.out.println(o.equals(o));
	final myObject o2 = o.createAnother();
	Guarana.reconfigure(myObject.class, null, new myMetaObject());
    }
}
