All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.bonita.util.Chainer Maven / Gradle / Ivy

/**
 * Copyright (C) 2007  Bull S. A. S.
 * Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * 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.
 * See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA  02110-1301, USA.
 **/
package org.ow2.bonita.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * Generic chainer.
 * 
 * This {@link InvocationHandler} allows chaining of void only 
 * method invocations.
 * 
 * If an exception is raised during the invocation of a void 
 * method in the chain, then the forwarding is stopped, and the exception will 
 * be raised up.
 * 
 * Note that if a non-void method is invoked, an 
 * {@link IllegalArgumentException} is thrown.
 * 
 * @author Pierre Vigneras
 * @date Feb 11, 2008
 */
public class Chainer implements InvocationHandler {
  // Object methods, should be handled specially here! We don't want 
  // them to be forwarded, but still, we want to reply to them!.
  // See Proxy javadoc for details for list of Object methods that are
  // normally forwarded.
  private static final Method TOSTRING_METHOD;
  private static final Method EQUALS_METHOD;
  private static final Method HASHCODE_METHOD;

  static {
    Method tostringMethodTmp = null;
    Method equalsMethodTmp = null;
    Method hashcodeMethodTmp = null;
    try {
      tostringMethodTmp = Object.class.getMethod("toString");
      equalsMethodTmp = Object.class.getMethod("equals", Object.class);
      hashcodeMethodTmp = Object.class.getMethod("hashCode");
    } catch (NoSuchMethodException nsme) {
      throw new ExceptionInInitializerError("Ouch! Can't find Object method!");
    }
    TOSTRING_METHOD = tostringMethodTmp;
    EQUALS_METHOD = equalsMethodTmp;
    HASHCODE_METHOD = hashcodeMethodTmp;
  }



  private final List chain = Collections.synchronizedList(new LinkedList());
  public void add(final T element) {
    chain.add(element);
  }

  public void add(final int i, final T element) {
    chain.add(i, element);
  }

  public T remove(final int i) {
    return chain.remove(i);
  }

  public T get(final int i) {
    return chain.get(i);
  }

  public boolean contains(final T element) {
    return chain.contains(element);
  }

  public List getAsList() {
    return new LinkedList(chain);
  }


  /* (non-Javadoc)
   * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
   */
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (method.getReturnType().equals(Void.TYPE)) {
      for (T t : chain) {
        try {
          method.invoke(t, args);
        } catch (InvocationTargetException e) {
          throw e.getCause();
        }
      }
      return null;
    }
    if (method.equals(TOSTRING_METHOD)) {
      return "ChainerProxy: " + chain; 
    } else if (method.equals(HASHCODE_METHOD)) {
      return this.hashCode() + chain.hashCode();
    } else if (method.equals(EQUALS_METHOD)) {
      if (Proxy.isProxyClass(proxy.getClass())) {
        final InvocationHandler invocationHandler = Proxy.getInvocationHandler(proxy);
        return this.equals(invocationHandler);
      }
    }
    throw new IllegalArgumentException("Only void method can be chained!");

  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy