Package er.extensions.foundation

Source Code of er.extensions.foundation.ERXMulticastingDelegate

package er.extensions.foundation;

import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation._NSDelegate;


/**
* <p>By design, WebObjects' classes that accept a delegate only accept a single object.  ERXMulticastingDelegate allows multiple
* delegate objects to be aggregated and presented as a single delegate object.</p>
*
* <p>Delegates are called in the order they are added.  Methods are called until one of the delegates handles the message.
* Delegate methods that have a Object or boolean return type are called until one returns a non-null response that is not the default value.
* Delegate methods that have a void return type are always called.</p>
*
* <p>Here is an example if you have multiple delegates that you want to set up.</p>
* <pre>
* ERXDatabaseContextMulticastingDelegate multiDelegate = new ERXDatabaseContextMulticastingDelegate();
* multiDeletegate.addDelegate(new ERXDatabaseContextDelegate());
* multiDeletegate.addDelegate(new ERXEntityDependencyOrderingDelegate());
* EODatabaseContext.setDefaultDelegate(multiDelegate);
* </pre>
*
* <p>Here is a usage example to handle the case where a deletegate may already be set</p>
* <pre>
* Object newDelegate = new ERXEntityDependencyOrderingDelegate();
* ERXDatabaseContextMulticastingDelegate multiDelegate;
* if (EODatabaseContext.defaultDelegate() == null) {
*     multiDelegate = new ERXDatabaseContextMulticastingDelegate();
* }
* else {
*     if (EODatabaseContext.defaultDelegate() instanceof ERXDatabaseContextMulticastingDelegate) {
*            multiDelegate = (ERXDatabaseContextMulticastingDelegate)EODatabaseContext.defaultDelegate();
*     }
*     else {
*         multiDelegate = new ERXDatabaseContextMulticastingDelegate();
*         multiDelegate.addDelegate(EODatabaseContext.defaultDelegate());
*     }
* }
* multiDelegate.addDelegate(newDelegate);
* EODatabaseContext.setDefaultDelegate(multiDelegate);
* </pre>
*
* <p>This class needs to be implemented for each delegate interface.  All methods on the interface should be implemented
* and should call one of the perform... or booleanPerform... methods on this class.  See ERXDatabaseContextMulticastingDelegate
* for example usage. One result of this implementation is that delegates can be added and removed at any time.</p>
*
* @author chill
*/
public abstract class ERXMulticastingDelegate {

    private NSMutableArray delegates = new NSMutableArray();


    /**
     * Adds <code>delegate</code> at the end of the chain.  It becomes the last delegate called.
     *
     * @param delegate Object to add as one of the delegates called
     */
    public void addDelegate(Object delegate) {
      synchronized (delegates) {
          if (hasDelegate(delegate)) {
            throw new IllegalArgumentException("Delegate is already included");
          }
         
            _NSDelegate delegateObject = new _NSDelegate(getClass(), delegate);
            delegates.addObject(delegateObject);
        }
    }
   

    /**
     * Adds <code>delegate</code> at the start of the chain.  It becomes the first delegate called.
     *
     * @param delegate Object to add as one of the delegates called
     */
    public void addDelegateAtStart(Object delegate) {
      synchronized (delegates) {
          if (hasDelegate(delegate)) {
            throw new IllegalArgumentException("Delegate is already included");
          }
         
          _NSDelegate delegateObject = new _NSDelegate(getClass(), delegate);
          delegates.insertObjectAtIndex(delegateObject, 0);
      }
    }
   
   
    /**
     * Removes <code>delegate</code> from the delegates called.
     *
     * @param delegate Object to remove as one of the delegates called
     */
    public void removeDelegate(Object delegate) {
      synchronized (delegates) {
          if ( ! hasDelegate(delegate)) {
            throw new IllegalArgumentException("Delegate is not present");
          }
         
          for (int i = 0; i < delegates.count(); i++) {
            _NSDelegate delegateObject = (_NSDelegate)delegates.objectAtIndex(i);
            if (delegateObject.delegate().equals(delegate))
            {
              delegates.removeObjectAtIndex(i);
              break;
            }
          }
        }
    }
   

    /**
     * Returns <code>true</code> if delegate is represented in delegates().
     *
     * @param delegate Object to test for membership in delegates()
     * @return <code>true</code> if delegate is represented in delegates()
     */
    public boolean hasDelegate(Object delegate) {
      synchronized (delegates) {
          for (int i = 0; i < delegates.count(); i++) {
            _NSDelegate delegateObject = (_NSDelegate)delegates.objectAtIndex(i);
            if (delegateObject.delegate().equals(delegate))
            {
              return true;
            }
          }
          return false;
      }
    }
   
   
    /**
     * This method returns an array of <code>com.webobjects.foundation._NSDelegate</code>, <b>not</b>
     * the delegate objects originally added by calling addDelegate...  Call <code>delegate()</code>
     * on the elements in this list to examine the delegate objects originally added by calling addDelegate...
     *
     * @return the delegates in the order they will be called
     */
    public NSArray delegates() {
      synchronized (delegates) {
        return delegates.immutableClone();
      }
    }
   

    /**
     * Use this to set the delegate order if the addDelegate... methods are not sufficient.
     * <code>orderedDelegates</code> should be a re-arrangement of the list returned by <code>delegates()</code>.
     *
     * @param orderedDelegates array of <code>com.webobjects.foundation._NSDelegate</code> in the order in which delegates should be called
     */
    public void setDelegateOrder(NSArray orderedDelegates) {
      synchronized (delegates) {
          for (int i = 0; i < orderedDelegates.count(); i++) {
              if ( ! (orderedDelegates.objectAtIndex(i) instanceof _NSDelegate)) {
                  throw new IllegalArgumentException("Object of class " + orderedDelegates.objectAtIndex(i).getClass().getName() +
                          " must be instanceof _NSDelegate");
              }
          }
          delegates = orderedDelegates.mutableClone();
      }
    }


    /**
     * This is the central method for dispatching messages to the delegates aggregated by this object.
     * The other perform... and booleanPerform... methods simply call this method.
     *
     * @param methodName the name of the delegate method to call
     * @param args 0 or more arguments to pass to the delegate method
     * @param defaultResult the value to return if none of the delegates implement this method
     * @return value returned by the last delegate called
     */
    protected Object perform(String methodName, Object args[], Object defaultResult) {
        Object result = null;
      synchronized (delegates) {
            for (int i = 0; (result == null || result.equals(defaultResult)) && i < delegates.count(); i++) {
                _NSDelegate delegate = (_NSDelegate) delegates.objectAtIndex(i);
                if (delegate.respondsTo(methodName)) {
                    result = delegate.perform(methodName, args);
                }
            }
      }

        return result == null ? defaultResult : result;
    }


    protected Object perform(String methodName, Object defaultResult)
    {
        return perform(methodName, new Object[0], defaultResult);
    }


    protected Object perform(String methodName, Object arg, Object defaultResult)
    {
        return perform(methodName, new Object[] {arg}, defaultResult);
    }


    protected Object perform(String methodName, Object arg1, Object arg2, Object defaultResult)
    {
        return perform(methodName, new Object[] {arg1, arg2}, defaultResult);
    }


    protected Object perform(String methodName, Object arg1, Object arg2, Object arg3, Object defaultResult)
    {
        return perform(methodName, new Object[] {arg1, arg2, arg3}, defaultResult);
    }



    protected Object perform(String methodName, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object defaultResult)
    {
        return perform(methodName, new Object[] {arg1, arg2, arg3, arg4, arg5}, defaultResult);
    }
   

    protected boolean booleanPerform(String methodName, boolean defaultResult)
    {
        return booleanPerform(methodName, new Object[0], defaultResult);
    }


    protected boolean booleanPerform(String methodName, Object arg, boolean defaultResult)
    {
        return booleanPerform(methodName, new Object[] {arg}, defaultResult);
    }


    protected boolean booleanPerform(String methodName, Object arg1, Object arg2, boolean defaultResult)
    {

        return booleanPerform(methodName, new Object[] {arg1, arg2}, defaultResult);
    }


    protected boolean booleanPerform(String methodName, Object arg1, Object arg2, Object arg3, boolean defaultResult)
    {
        return booleanPerform(methodName, new Object[] {arg1, arg2, arg3}, defaultResult);
    }


    protected boolean booleanPerform(String methodName, Object args[], boolean defaultResult)
    {
        Boolean result = (Boolean) perform(methodName, args, Boolean.valueOf(defaultResult));
        return result != null ? result.booleanValue() : false;
    }

}
TOP

Related Classes of er.extensions.foundation.ERXMulticastingDelegate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.