package org.mockejb;

import java.io.Serializable;

import javax.ejb.*;
import org.apache.commons.logging.*;

import org.mockejb.interceptor.*;

/**
 * Handles calls to findByPrimaryKey for CMP beans.
 * Checks if the requested PK is in the EntityDatabase,
 * if it is, gets the entity from the EntityDatabase and returns it to the client.
 * Otherwise, proceeds to the next interceptor in the chain. 
 *  
 * @author Alexander Ananiev
 */
public class CMPFindByPrimaryKeyHandler  implements Aspect, Serializable {

    // logger for this class
    private static Log logger = LogFactory.getLog( CMPFindByPrimaryKeyHandler.class.getName() );

    protected EntityDatabase entityDatabase;
    
    public CMPFindByPrimaryKeyHandler( final EntityDatabase entityDatabase ){
        this.entityDatabase = entityDatabase;
    }
    
    public Pointcut getPointcut(){
       
        return PointcutPair.and(  new MethodPatternPointcut( "findByPrimaryKey" ), 
                PointcutPair.or( new ClassPointcut( EJBHome.class, true), 
                        new ClassPointcut( EJBLocalHome.class, true) ) );
    }
   
    public void intercept( InvocationContext invocationContext ) throws Exception {
        
        // get the descriptor
        BasicEjbDescriptor descriptor= (BasicEjbDescriptor) invocationContext.getPropertyValue("descriptor");
        
        // handle only CMP entity beans
        if ( descriptor instanceof EntityBeanDescriptor &&
                ((EntityBeanDescriptor) descriptor).isCMP()) {
            
            //EntityBeanDescriptor descriptor = (EntityBeanDescriptor) ejbDescriptor;
            
            logger.debug("Intercepted "+invocationContext.getProxyMethod());
            
            Object [] paramVals = invocationContext.getParamVals(); 
            Object pk = paramVals[0];
            
            Object entity = entityDatabase.find( descriptor.getHomeClass(), pk);
            // if entity is in DB - return
            if (entity!=null) {
                invocationContext.setReturnObject( entity );
            }
            else {
                logger.info( "Entity "+descriptor.getIfaceClass().getName()+
                        " for PK "+pk+" is not found in the entity database. Proceeding to the next interceptor...");
                // proceed to the next interceptor, may be some other interceptor implements "findByPrimaryKey"
                invocationContext.proceed();
            }
        }   
        else {  // not a CMP entity bean
            invocationContext.proceed();    
        }
    }
    
    
    /**
     * This class does not have state, so all instances of this class
     * are considered equal
     */
    public boolean equals( Object obj ){
        
        if ( obj instanceof CMPFindByPrimaryKeyHandler &&
                entityDatabase.equals( ((CMPFindByPrimaryKeyHandler)obj).entityDatabase ) ) 
            return true;
        else
            return false;
        
    }

    public int hashCode() { 
        return this.getClass().hashCode()+entityDatabase.hashCode();  
    }    
   

}