import org.aspectj.testing.Tester;

// aspect inheritance and advice, introduction

public class Driver {
    public static void test() {
        C1 c1 = new C1();
        
        Tester.checkEqual(c1.foo(), "from A2", "sub-aspects");
        Tester.checkEqual(c1.bar(), 
                           "from A0 #2", 
                           "sub-aspects and position");

	// the around advice lexically in A1 runs twice, once for each concrete
	// sub-aspects.  putting advice on a concrete pointcut in an abstract
	// aspect will always have this odd behavior, and possibly should be illegal
        Tester.checkEqual(c1.getString(), 
                           ":A2:A1:A1:C1",
                           "multiple arounds");
    }

    public static void main(String[] args) { test(); }
}

class C1 {
    String getString() {
        return ":C1";
    }
}

abstract aspect A1 {
    String C1.foo() {
	return "from A1";
    }
    
    String C1.bar() {
	return "from A1";
    }

    String around(): 
            call(String C1.getString()) {
        return ":A1" + proceed();
    }
}

aspect A2 extends A1 {
    String C1.foo() {
	return "from A2";
    }

    String around(): 
            call(String C1.getString()) {
        return ":A2" + proceed();
    }
    
}

aspect A0 extends A1 {
    // multiple conflicting declarations in the same aspect are now an error
    //String C1.bar() {
    //	return "from A0 #1";
    //}
    
    String C1.bar() {
	return "from A0 #2";
    }
}