aspect Test{

//  This should match.    
    
    after(): execution(* Clazz.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): execution(* L0Aspect.*(..)) {}

    after(): execution(* L1Aspect.*(..)) {}

    after(): execution(* L2Aspect.*(..)) {}

    after(): execution(* L3Aspect.*(..)) {}
    
}

meta aspect Test1{

//  This should match.
    
    after(): adviceexecution(){}
        
    after(): execution(* Clazz.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): execution(* L0Aspect.*(..)) {}

    after(): execution(* L1Aspect.*(..)) {}

    after(): execution(* L2Aspect.*(..)) {}

    after(): execution(* L3Aspect.*(..)) {}
    
//  This should match not match because wrong meta level is given.    

    after(): meta execution(* Clazz.*(..)) {}

//  This should match.    
    
    after(): meta execution(* L0Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta execution(* L1Aspect.*(..)) {}

    after(): meta execution(* L2Aspect.*(..)) {}

    after(): meta execution(* L3Aspect.*(..)) {}

}

meta(2) aspect Test2{

//  This should match.
    
    after(): adviceexecution(){}
    
    after(): meta adviceexecution(){}
    
//  This should match.

    after(): execution(* Clazz.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): execution(* L0Aspect.*(..)) {}

    after(): execution(* L1Aspect.*(..)) {}

    after(): execution(* L2Aspect.*(..)) {}

    after(): execution(* L3Aspect.*(..)) {}
    
//  This should match not match because wrong meta level is given.    

    after(): meta execution(* Clazz.*(..)) {}

//  This should match.
    
    after(): meta execution(* L0Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta execution(* L1Aspect.*(..)) {}

    after(): meta execution(* L2Aspect.*(..)) {}

    after(): meta execution(* L3Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta(2) execution(* Clazz.*(..)) {}

    after(): meta(2) execution(* L0Aspect.*(..)) {}

//  This should match.    
    
    after(): meta(2) execution(* L1Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta(2) execution(* L2Aspect.*(..)) {}

    after(): meta(2) execution(* L3Aspect.*(..)) {}

}


meta(3) aspect Test3{

//  This should match.
    
    after(): adviceexecution(){}
    
    after(): meta adviceexecution(){}

    after(): meta(2) adviceexecution(){}

//  This should match.

    after(): execution(* Clazz.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): execution(* L0Aspect.*(..)) {}

    after(): execution(* L1Aspect.*(..)) {}

    after(): execution(* L2Aspect.*(..)) {}

    after(): execution(* L3Aspect.*(..)) {}
    
//  This should match not match because wrong meta level is given.    

    after(): meta execution(* Clazz.*(..)) {}

//  This should match.

    after(): meta execution(* L0Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta execution(* L1Aspect.*(..)) {}

    after(): meta execution(* L2Aspect.*(..)) {}

    after(): meta execution(* L3Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta(2) execution(* Clazz.*(..)) {}

    after(): meta(2) execution(* L0Aspect.*(..)) {}

//  This should match.    
    
    after(): meta(2) execution(* L1Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta(2) execution(* L2Aspect.*(..)) {}

    after(): meta(2) execution(* L3Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta(3) execution(* Clazz.*(..)) {}

    after(): meta(3) execution(* L0Aspect.*(..)) {}

    after(): meta(3) execution(* L1Aspect.*(..)) {}

//  This should match.    
    
    after(): meta(3) execution(* L2Aspect.*(..)) {}

//  This should match not match because wrong meta level is given.    

    after(): meta(3) execution(* L3Aspect.*(..)) {}
    
}

meta(3) aspect TestX {

//  This should not match cause adviceexecution shadows and
//  execution shadows do not overlap.
    
    after(): adviceexecution() && meta execution(* L0Aspect.*(..)) {}

}

meta(2) aspect Test123{

//  This should not match due to wrong meta level.    
    
    after(): meta adviceexecution() && meta(2) within(Test) {}

//  This should match.    
    
    after(): meta adviceexecution() && meta(2) within(Test1) {}

//  This should not match due to wrong meta level.    

    after(): meta adviceexecution() && meta(2) within(Test2) {}

}

//The follow aspects/class are just used to match against.

meta(3) aspect L3Aspect{
    void foo(){};
}   

meta(2) aspect L2Aspect{
    void foo(){};
}   

meta aspect L1Aspect{
    void foo(){};
}   

aspect L0Aspect{
    void foo(){};
}   

class Clazz {
    void foo(){};
}
