InvokeNoArgMethod.java :  » Development » jga-Generic-Algorithms » net » sf » jga » fn » property » Java Open Source

Java Open Source » Development » jga Generic Algorithms 
jga Generic Algorithms » net » sf » jga » fn » property » InvokeNoArgMethod.java
// ============================================================================
// $Id: InvokeNoArgMethod.java,v 1.9 2006/04/26 03:40:37 davidahall Exp $
// Copyright (c) 2003-2005  David A. Hall
// ============================================================================
// The contents of this file are subject to the Common Development and
// Distribution License (CDDL), Version 1.0 (the License); you may not use this 
// file except in compliance with the License.  You should have received a copy
// of the the License along with this file: if not, a copy of the License is 
// available from Sun Microsystems, Inc.
//
// http://www.sun.com/cddl/cddl.html
//
// From time to time, the license steward (initially Sun Microsystems, Inc.) may
// publish revised and/or new versions of the License.  You may not use,  
// distribute, or otherwise make this file available under subsequent versions 
// of the License.
// 
// Alternatively, the contents of this file may be used under the terms of the 
// GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
// case the provisions of the LGPL are applicable instead of those above. If you 
// wish to allow use of your version of this file only under the terms of the 
// LGPL, and not to allow others to use your version of this file under the 
// terms of the CDDL, indicate your decision by deleting the provisions above 
// and replace them with the notice and other provisions required by the LGPL. 
// If you do not delete the provisions above, a recipient may use your version 
// of this file under the terms of either the CDDL or the LGPL.
// 
// This library 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. 
// ============================================================================

package net.sf.jga.fn.property;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import net.sf.jga.fn.BinaryFunctor;
import net.sf.jga.fn.EvaluationException;
import net.sf.jga.fn.UnaryFunctor;
import net.sf.jga.fn.adaptor.ChainBinary;
import net.sf.jga.fn.adaptor.ChainUnary;

/**
 * Functor that invokes a no-arg method named at construction and returns the
 * result or null if the result is void.
 * <p>
 * Note that declaring the return type incorrectly can result in
 * ClassCastExceptions being thrown when the functor is invoked: the compiler
 * cannot check the return type of a reflectively loaded method.
 * <p>
 * Copyright &copy; 2003-2005  David A. Hall
 *
 * @author <a href="mailto:davidahall@users.sourceforge.net">David A. Hall</a>
 **/

public class InvokeNoArgMethod<T,R> extends UnaryFunctor<T,R> {
    
    static final long serialVersionUID = -2651164047444243205L;

    // The name of the method
    private String _methName;

    // The class on which the method is defined
    private Class<T> _objclass;

    // The method being called (lazily populated after deserialization)
    private transient Method _meth;

    /**
     * Builds a InvokeMethod for the given method, which takes no arguments.
     * @throws IllegalArgumentException if the method name is null or empty
     */
    
    public InvokeNoArgMethod(Class<T> objclass, String methName) {
        if (methName == null || methName.length() == 0) {
            String msg = "Must supply method name";
            throw new IllegalArgumentException(msg);
        }

        if (objclass == null) {
            String msg = "Must supply object class";
            throw new IllegalArgumentException(msg);
        }

        _methName = methName;
        _objclass = objclass;
        
        try {
            _meth = objclass.getMethod(_methName, new Class[0]);
        }
        catch (NoSuchMethodException x) {
            String msg = "No such method: "+x.getMessage();
            IllegalArgumentException iax = new IllegalArgumentException(msg);
            iax.initCause(x);
            throw iax;
        }
    }

    /**
     * Builds a InvokeMethod for the given method, which takes no arguments.
     * @throws IllegalArgumentException if the method name is null or empty,
     * or if it is not defined for the given class, or if it takes arguments
     */
    
    public InvokeNoArgMethod(Class<T> objClass, Method method) {
        if (method == null) {
            String msg = "Must supply method";
            throw new IllegalArgumentException(msg);
        }

        if (objClass == null) {
            String msg = "Must supply object class";
            throw new IllegalArgumentException(msg);
        }

        if (method.getParameterTypes().length != 0) {
            String msg = "Method {0} takes arguments";
            Object[] args = { method.getName() };
            throw new IllegalArgumentException(MessageFormat.format(msg, args));
        }
        
        if (!method.getDeclaringClass().isAssignableFrom(objClass)) {
            String msg = "Method {0} not defined for class {1}";
            Object[] args = { method.getName(), objClass.getName() };
            throw new IllegalArgumentException(MessageFormat.format(msg, args));
        }
        
        _objclass = objClass;
        _meth     = method;
        _methName = method.getName();
    }

    /**
     * Returns the name of the property that this functor retrieves.
     */
    public String getMethodName() {
        return _methName;
    }

    /**
     * Returns the type of the method 
     */
    public Class<R> getReturnType() {
        return (Class<R>) _meth.getReturnType();
    }

    /**
     * Lazy loads the method 
     */
    public synchronized Method getMethod() throws NoSuchMethodException {
        if (_meth == null) 
            _meth = _objclass.getMethod(_methName, new Class[0]);

        return _meth;
    }

    // Unary Functor interface

    /**
     * Invokes the method on the given object, and returns the result.
     * @return the result of the designated method of the object
     * @throws EvaluationException if the argument does not have the designated
     *         public property, or if it is not of the correct type. 
     */
    public R fn(T obj) {
        try {
            // @SuppressWarnings
            // There's nothing we can do about this other than warn the users
            // to make sure that they don't use an inappropriate return type
            return (R) getMethod().invoke(obj, new Object[0]);
        }
        catch (NoSuchMethodException x) {
            String msg = "No method {0} for class {1} that takes no arguments";
            Object[] args = new Object[]{_methName,  _objclass.getName()};
            throw new EvaluationException(MessageFormat.format(msg,args), x);
        }
        catch (ClassCastException x) {
            String msg = "ClassCastException: " +_objclass +"." +_methName +"()";
            throw new EvaluationException(msg, x);
        }
        catch (IllegalAccessException x) {
            String msg = _objclass +"." +_methName +" is not accessible";
            throw new EvaluationException(msg, x);
        }
        catch (InvocationTargetException x) {
            String xmsg = x.getMessage();
            String msg = "InvocationException: " +_objclass +"." +_methName
                +"()"+(xmsg != null ? (":"+xmsg) : "");
            throw new EvaluationException(msg, x);
        }
    }

    
    /**
     * Calls the Visitor's <code>visit(InvokeMethod)</code> method, if it
     * implements the nested Visitor interface.
     */
    public void accept(net.sf.jga.fn.Visitor v) {
        if (v instanceof InvokeNoArgMethod.Visitor)
            ((InvokeNoArgMethod.Visitor)v).visit(this);
        else
            v.visit(this);
    }
    
    // Object overrides

    public String toString() {
        return "InvokeNoArgMethod("+_meth+")";
    }
    
   // AcyclicVisitor
    
    /**
     * Interface for classes that may interpret a <b>InvokeMethod</b>
     * function.
     */
    public interface Visitor extends net.sf.jga.fn.Visitor {
        public void visit(InvokeNoArgMethod host);
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.