package org.mockejb.interceptor.test;

import java.lang.reflect.Method;

import java.util.List;

import junit.framework.TestCase;

import org.mockejb.interceptor.*;

/**
 * Tests standard pointcuts supplied with MockEJB as well as 
 * basic AspectSystem functions.
 * 
 * @author Alexander Ananiev
 */
public class PointcutTest extends TestCase {
    
    
    private TestIface testProxy;
    private InvocationContext targetInvoker;
    
    private AspectSystem aspectSystem;
    
    
    public void setUp() throws Exception {
        aspectSystem = AspectSystemFactory.getAspectSystem();
        aspectSystem.clear();
    }
    
    public void tearDown() throws Exception {
        aspectSystem.getAspectList().clear();
    }
        
    // TODO: refactor to multiple methods
    public void testClassPointcut() throws Exception {
        
        TestInterceptor interceptor = new TestInterceptor();
        Object target = new TestImpl();
        
        // test w/o subclasses
        aspectSystem.clear();
        aspectSystem.add( new ClassPointcut( TestIface.class ), 
                interceptor );
        
        Method m = TestIface.class.getMethod("test", null );
        
        List interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()>0 );

        
        
        // test with subclasses
        aspectSystem.clear();
        aspectSystem.add( new ClassPointcut( TestIface.class, true ), 
                interceptor );
        m = TestImpl.class.getMethod("test", null );
        
        interceptorList = aspectSystem.findInterceptors( m,m );
        assertTrue( interceptorList.size()>0 );

        // make it fail
        m = this.getClass().getMethod("setUp", null );
        interceptorList = aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()==0 );

        // test equals method
        aspectSystem.clear();
        aspectSystem.add( new ClassPointcut( TestIface.class ), 
                interceptor );
        
        aspectSystem.add( new ClassPointcut( TestIface.class ), 
                interceptor );
        
        assertTrue( aspectSystem.getAspectList().size()==1 );
        
        
    }
    
    public void testClassPatternPointcut() throws Exception {
        
        TestInterceptor interceptor = new TestInterceptor();
        Object target = new TestImpl();
        
        aspectSystem.clear();
        aspectSystem.add( new ClassPatternPointcut( ".*test" ), 
                interceptor );
        
        Method m = TestIface.class.getMethod("test", null );
        
        List interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()>0 );

        // test equals method

        aspectSystem.clear();
        aspectSystem.add( new ClassPatternPointcut( "Test" ), 
                interceptor );
        
        aspectSystem.add( new ClassPatternPointcut(  "Test" ), 
                interceptor );
        
        assertTrue( aspectSystem.getAspectList().size()==1 );
        
        
    }
    
    public void testMethodPatternPointcut() throws Exception {
        
        TestInterceptor interceptor = new TestInterceptor();
        Object target = new TestImpl();
        
        aspectSystem.clear();
        aspectSystem.add( new MethodPatternPointcut( "TestIface.test()" ), 
                interceptor );
        
        Method m = TestIface.class.getMethod("test", null );
        
        List interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()>0 );

        // test equals method

        aspectSystem.clear();
        aspectSystem.add( new MethodPatternPointcut( "Test" ), 
                interceptor );
        
        aspectSystem.add( new MethodPatternPointcut(  "Test" ), 
                interceptor );
        
        assertTrue( aspectSystem.getAspectList().size()==1 );
        
        
    }
    
    public void testPointcutPair() throws Exception {
        
        TestInterceptor interceptor = new TestInterceptor();
        Object target = new TestImpl();
        
        // make it fail
        aspectSystem.clear();
        aspectSystem.add( PointcutPair.and( new MethodPatternPointcut( "test()"),
                new ClassPointcut( this.getClass()) ), 
                interceptor );
        
        Method m = TestIface.class.getMethod("test", null );
        
        List interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()==0 );

        // make it succeed
        aspectSystem.clear();
        aspectSystem.add( PointcutPair.and( new MethodPatternPointcut( "test()"),
                new ClassPointcut( TestIface.class ) ), 
                interceptor );
        
        m = TestIface.class.getMethod("test", null );
        
        interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()==1 );
        
        // test or
        aspectSystem.clear();
        aspectSystem.add( PointcutPair.or( new MethodPatternPointcut( "test()"),
                new ClassPointcut( this.getClass() ) ), 
                interceptor );
        
        m = TestIface.class.getMethod("test", null );
        
        interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()==1 );

        // test complex condition
        aspectSystem.clear();
        aspectSystem.add( PointcutPair.or( new MethodPatternPointcut( "fail()"),
                PointcutPair.and( new ClassPointcut( TestIface.class  ), 
                new MethodPatternPointcut( "test()") ) ), 
                interceptor );
        
        m = TestIface.class.getMethod("test", null );
        
        interceptorList = 
            aspectSystem.findInterceptors( m,m );
        
        assertTrue( interceptorList.size()==1 );
        
        
        
        // TODO: test equals method

        
        
    }
    
}