// $Id: ModifyOperation.java,v 1.2 1998/07/24 09:30:53 oliva Exp $

/* Copyright 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
 *
 * This file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

import BR.unicamp.Guarana.*;

/**
 * This program shows how a MetaObject can create Operations targeted
 * at base-level Objects it reflects upon.  It assumes it will be
 * associated with instances of ModifyOperationBase.  If method
 * toString is invoked and field callSuper is true, method toString of
 * class Object will be executed instead of the one defined in the
 * subclass.  Note that callSuper is private but, nevertheless, the
 * MetaObject can have access to it using its OperationFactory.
 *
 * @author Alexandre Oliva
 * @version $Revision: 1.2 $
 */
public class ModifyOperation extends MetaObject {
    static final java.lang.reflect.Method toString;
    static final java.lang.reflect.Field callSuper;
    static {
	try { toString =
		  Object.class.getDeclaredMethod("toString", new Class[0]);
	} catch (NoSuchMethodException e) { toString = null; }
	try { callSuper =
		  ModifyOperationBase.class.getDeclaredField("callSuper");
	} catch (NoSuchFieldException e) { callSuper = null; } 
    }
    OperationFactory opf = null;
    public void initialize(final OperationFactory opf, final Object o)
    { this.opf = opf; }
    public Result handle(final Operation op, final Object ob) {
	System.out.println("Operation: " + op);
	if (op.isMethodInvocation()) try {
	    final java.lang.reflect.Method m = op.getMethod();
	    if (!toString.equals(m) && m.getName().equals("toString")
		&& opf.read(callSuper).perform().getBooleanValue()) {
		Operation newOp = opf.invoke(toString, new Object[0], op);
		System.out.println("Replaced with: " + newOp);
		return Result.operation(newOp, Result.inspectResultMode);
	    }
	} catch (IllegalAccessException e) { }
	return Result.inspectResult;
    }
    public Result handle(final Result res, final Object ob)
    { System.out.println("Result: " + res); return null; }
    public static void main(String[ ] argv) {
	final Object oFalse = new ModifyOperationBase(false);
	Guarana.reconfigure(oFalse, null, new ModifyOperation());
	System.out.println("oFalse: " + oFalse);
	final Object oTrue = new ModifyOperationBase(true);
	Guarana.reconfigure(oTrue, null, new ModifyOperation());
	System.out.println("oTrue: " + oTrue);
    }
}
