Package er.extensions.eof

Source Code of er.extensions.eof.ERXDatabaseContextMulticastingDelegate

package er.extensions.eof;

import java.lang.reflect.Method;

import com.webobjects.eoaccess.EOAdaptorChannel;
import com.webobjects.eoaccess.EODatabase;
import com.webobjects.eoaccess.EODatabaseChannel;
import com.webobjects.eoaccess.EODatabaseContext;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOFetchSpecification;
import com.webobjects.eocontrol.EOGlobalID;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSForwardException;

import er.extensions.foundation.ERXMulticastingDelegate;


/**
* Subclass of <code>er.extensions.foundation.ERXMulticastingDelegate</code> that implements
* <code>com.webobjects.eoaccess.EODatabaseContext.Delegate</code>. Use this to aggregate multiple delegate objects
* for <code>EODatabaseContext.Delegate</code>
*
* @see er.extensions.foundation.ERXMulticastingDelegate
* @see com.webobjects.eoaccess.EODatabaseContext.Delegate
* @author chill
*/
public class ERXDatabaseContextMulticastingDelegate extends ERXMulticastingDelegate {

    private Method orderAdaptorOperations;
    private Method currentEditingContext;
   
   
    public ERXDatabaseContextMulticastingDelegate() {
        super();
        try {
            orderAdaptorOperations = EODatabaseContext.class.getDeclaredMethod("orderAdaptorOperations", new Class[] {});
            orderAdaptorOperations.setAccessible(true);
           
            currentEditingContext = EODatabaseChannel.class.getDeclaredMethod("currentEditingContext", new Class[] {});
            currentEditingContext.setAccessible(true);
        }
        catch (Exception e) {
            throw NSForwardException._runtimeExceptionForThrowable(e);
        }
    }
   


    /**
     * <p>Convenience method to add <code>newDelegate</code> as the last delegate called for
     * <code>EODatabaseContext.defaultDelegate()</code>.  There are three cases to handle:</p>
     * <ol>
     * <li>If there is no default delegate defined, an <code>ERXDatabaseContextMulticastingDelegate</code>
     * is created as the default delegate, and <code>newDelegate</code> added.</li>
     *
     * <li>If there is a default delegate defined, and it is a <code>ERXDatabaseContextMulticastingDelegate</code>,
     * <code>newDelegate</code> is added at the end of the delegate chain.</li>
     *
     * <li>If there is a default delegate defined, and it is not a <code>ERXDatabaseContextMulticastingDelegate</code>,
     * an <code>ERXDatabaseContextMulticastingDelegate</code> is created as the default delegate, the existing delegate is
     * added, then <code>newDelegate</code> is added at the end of the delegate chain.</li>
     * </ol>
     *
     * @param newDelegate object to include as delegate
     */
    public static void addDefaultDelegate(Object newDelegate) {
        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);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextDidFetchObjects(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.foundation.NSArray, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eocontrol.EOEditingContext)
     */
    public void databaseContextDidFetchObjects(EODatabaseContext dbCtxt, NSArray array, EOFetchSpecification fetchSpec, EOEditingContext ec) {
        perform("databaseContextDidFetchObjects", new Object[] {dbCtxt, array, fetchSpec, ec}, null);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextDidSelectObjects(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eoaccess.EODatabaseChannel)
     */
    public void databaseContextDidSelectObjects(EODatabaseContext dbCtxt, EOFetchSpecification fetchSpec, EODatabaseChannel dbChannel) {
        perform("databaseContextDidSelectObjects", new Object[] {dbCtxt, fetchSpec, dbChannel}, null);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextFailedToFetchObject(com.webobjects.eoaccess.EODatabaseContext, java.lang.Object, com.webobjects.eocontrol.EOGlobalID)
     */
    public boolean databaseContextFailedToFetchObject(EODatabaseContext dbCtxt, Object object, EOGlobalID gid) {
        return booleanPerform("databaseContextFailedToFetchObject", new Object[] {dbCtxt, object, gid}, false);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextNewPrimaryKey(com.webobjects.eoaccess.EODatabaseContext, java.lang.Object, com.webobjects.eoaccess.EOEntity)
     */
    public NSDictionary databaseContextNewPrimaryKey(EODatabaseContext dbCtxt, Object object, EOEntity entity) {
        return (NSDictionary)perform("databaseContextNewPrimaryKey", new Object[] {dbCtxt, object, entity}, null);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldFetchArrayFault(com.webobjects.eoaccess.EODatabaseContext, java.lang.Object)
     */
    public boolean databaseContextShouldFetchArrayFault(EODatabaseContext dbCtxt, Object object) {
        return booleanPerform("databaseContextShouldFetchArrayFault", new Object[] {dbCtxt, object}, true);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldFetchObjectFault(com.webobjects.eoaccess.EODatabaseContext, java.lang.Object)
     */
    public boolean databaseContextShouldFetchObjectFault(EODatabaseContext dbCtxt, Object object) {
        return booleanPerform("databaseContextShouldFetchObjectFault", new Object[] {dbCtxt, object}, true);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldFetchObjects(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eocontrol.EOEditingContext)
     */
    public NSArray databaseContextShouldFetchObjects(EODatabaseContext dbCtxt, EOFetchSpecification fetchSpec, EOEditingContext ec) {
        return (NSArray)perform("databaseContextShouldFetchObjects", new Object[] {dbCtxt, fetchSpec, ec}, null);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldHandleDatabaseException(com.webobjects.eoaccess.EODatabaseContext, java.lang.Throwable)
     */
    public boolean databaseContextShouldHandleDatabaseException(EODatabaseContext dbCtxt, Throwable exception) {
        return booleanPerform("databaseContextShouldHandleDatabaseException", new Object[] {dbCtxt, exception}, true);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldInvalidateObjectWithGlobalID(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOGlobalID, com.webobjects.foundation.NSDictionary)
     */
    public boolean databaseContextShouldInvalidateObjectWithGlobalID(EODatabaseContext dbCtxt, EOGlobalID gid, NSDictionary dic) {
        return booleanPerform("databaseContextShouldInvalidateObjectWithGlobalID", new Object[] {dbCtxt, gid, dic}, true);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldLockObjectWithGlobalID(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOGlobalID, com.webobjects.foundation.NSDictionary)
     */
    public boolean databaseContextShouldLockObjectWithGlobalID(EODatabaseContext dbCtxt, EOGlobalID gid, NSDictionary dic) {
        return booleanPerform("databaseContextShouldLockObjectWithGlobalID", new Object[] {dbCtxt, gid, dic}, true);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldRaiseExceptionForLockFailure(com.webobjects.eoaccess.EODatabaseContext, java.lang.Throwable)
     */
    public boolean databaseContextShouldRaiseExceptionForLockFailure(EODatabaseContext dbCtxt, Throwable exception) {
        return booleanPerform("databaseContextShouldRaiseExceptionForLockFailure", new Object[] {dbCtxt, exception}, true);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldSelectObjects(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eoaccess.EODatabaseChannel)
     */
    public boolean databaseContextShouldSelectObjects(EODatabaseContext dbCtxt, EOFetchSpecification fetchSpec, EODatabaseChannel dbChannel) {
        return booleanPerform("databaseContextShouldSelectObjects", new Object[] {dbCtxt, fetchSpec, dbChannel}, true);
    }


  /**
    * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldUpdateCurrentSnapshot(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.foundation.NSDictionary, com.webobjects.foundation.NSDictionary, com.webobjects.eocontrol.EOGlobalID, com.webobjects.eoaccess.EODatabaseChannel)
    * @see EODatabase#snapshotForGlobalID(EOGlobalID, long)
    */
   public NSDictionary databaseContextShouldUpdateCurrentSnapshot(EODatabaseContext dbCtxt, NSDictionary existingSnapshot, NSDictionary fetchedRow, EOGlobalID gid, EODatabaseChannel dbChannel) {
     NSDictionary resultSnapshot =  (NSDictionary)perform("databaseContextShouldUpdateCurrentSnapshot", dbCtxt, existingSnapshot, fetchedRow, gid, dbChannel, null);
     if (resultSnapshot != null) {
       return resultSnapshot;
     }
    
     /* There is no way for this delegate method to say "do what you normally do". Our two choices for a default return value are
       never update the snapshot or always update it.  What we want is neither, we want the unchanged EOF behavior.  So we
       re-implement what EODatabaseChannel would so in the absence of this delegate method: updating of the snapshot depends
       whether we are refreshing and on the snapshot's age and the fetchTimestamp of the EC doing the fetching.
      */   
    try {
       // Again with the object rape.  EODatabaseChannel.currentEditingContext() is private and the underlying instance variable
       // is protected.  We need the ec, so we do what we have to...
       EOEditingContext ec = (EOEditingContext) currentEditingContext.invoke(dbChannel, new Object[] {});
      
       // Get the snapshot if it has not expired.  cachedSnapshot will be null if it has expired
       // If not null, it should be the same as the existingSnapshot parameter
       NSDictionary cachedSnapshot = dbCtxt.database().snapshotForGlobalID(gid, ec.fetchTimestamp());
   
       // If we are refreshing or the snapshot in the cache has timed out, but the fetched row
       // matches the cached snapshot, reset the time stamp by recording the existing snapshot again.
       if (existingSnapshot.equals(fetchedRow) && (dbChannel.isRefreshingObjects() || cachedSnapshot == null)) {
         dbCtxt.database().recordSnapshotForGlobalID(existingSnapshot, gid);
       }
      
       // Handle refreshing fetches.  If the fetched data is the same, we return
       // existingSnapshot to avoid a bug in EODatabaseChannel where == is used
       // instead of equals() when this delegate method is called.  Without this,
       // EOObjectStore.ObjectsChangedInStoreNotification will be sent when  there are no real changes.
       // This should be fixed in 5.4.3 but is left here for 5.3 compatibility
       if (dbChannel.isRefreshingObjects()) {
         return  existingSnapshot.equals(fetchedRow) ? existingSnapshot : fetchedRow;
       }
   
       // Same as for refreshing, if the snapshot has expired but is unchanged in the database,
       // return the existing snapshot
       if (cachedSnapshot == null && existingSnapshot.equals(fetchedRow)) {
         return existingSnapshot;
       }
   
       // Return the existing snapshot unless it has expired
        return cachedSnapshot != null ? existingSnapshot : fetchedRow;
    }
    catch (Exception e) {
      throw NSForwardException._runtimeExceptionForThrowable(e);
      }
  }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextShouldUsePessimisticLock(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eoaccess.EODatabaseChannel)
     */
    public boolean databaseContextShouldUsePessimisticLock(EODatabaseContext dbCtxt, EOFetchSpecification fetchSpec, EODatabaseChannel dbChannel) {
        return booleanPerform("databaseContextShouldUsePessimisticLock", new Object[] {dbCtxt, fetchSpec, dbChannel}, false);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextWillFireArrayFaultForGlobalID(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOGlobalID, com.webobjects.eoaccess.EORelationship, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eocontrol.EOEditingContext)
     */
    public void databaseContextWillFireArrayFaultForGlobalID(EODatabaseContext dbCtxt, EOGlobalID gid, EORelationship rel, EOFetchSpecification fetchSpec, EOEditingContext ec) {
        perform("databaseContextWillFireArrayFaultForGlobalID", new Object[] {dbCtxt, gid, rel, fetchSpec, ec}, null);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextWillFireObjectFaultForGlobalID(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eocontrol.EOGlobalID, com.webobjects.eocontrol.EOFetchSpecification, com.webobjects.eocontrol.EOEditingContext)
     */
    public void databaseContextWillFireObjectFaultForGlobalID(EODatabaseContext dbCtxt, EOGlobalID gid, EOFetchSpecification fetchSpec, EOEditingContext ec) {
        perform("databaseContextWillFireObjectFaultForGlobalID", new Object[] {dbCtxt, gid, fetchSpec, ec}, null);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextWillOrderAdaptorOperations(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.foundation.NSArray)
     */
   public NSArray databaseContextWillOrderAdaptorOperations(EODatabaseContext dbCtxt, NSArray databaseOps) {
       NSArray result = (NSArray)perform("databaseContextWillOrderAdaptorOperations", new Object[] {dbCtxt, databaseOps}, null);

       /* OK, this is really quite brutal.  This delegate method has no way of returning an "I did not handle this so do the default thing"
        * response.  The default thing is private so it can't be called directly.  Rather than re-implement it, we use reflection to
        * gain access to the private default implementation private NSArray orderAdaptorOperations().
        */
       if (result == null)
       {
           try {
               result = (NSArray) orderAdaptorOperations.invoke(dbCtxt, new Object[] {});
           }
           catch (Exception e) {
               throw NSForwardException._runtimeExceptionForThrowable(e);
           }
       }
       return result;
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextWillPerformAdaptorOperations(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.foundation.NSArray, com.webobjects.eoaccess.EOAdaptorChannel)
     */
    public NSArray databaseContextWillPerformAdaptorOperations(EODatabaseContext dbCtxt, NSArray adaptorOps, EOAdaptorChannel adChannel) {
        return (NSArray)perform("databaseContextWillPerformAdaptorOperations", new Object[] {dbCtxt, adaptorOps, adChannel}, adaptorOps);
    }


    /**
     * @see com.webobjects.eoaccess.EODatabaseContext.Delegate#databaseContextWillRunLoginPanelToOpenDatabaseChannel(com.webobjects.eoaccess.EODatabaseContext, com.webobjects.eoaccess.EODatabaseChannel)
     */
    public boolean databaseContextWillRunLoginPanelToOpenDatabaseChannel(EODatabaseContext dbCtxt, EODatabaseChannel dbChannel) {
        return booleanPerform("databaseContextWillRunLoginPanelToOpenDatabaseChannel", new Object[] {dbCtxt, dbChannel}, true);
    }

}
TOP

Related Classes of er.extensions.eof.ERXDatabaseContextMulticastingDelegate

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.