@@ -1171,13 +1171,13 @@ | |||
* Matches at an addChild join point for the parent type P and child type C | |||
*/ | |||
public pointcut addingChild(Parent p, Child c) : | |||
execution(* Parent.addChild(Child)) && this(p) && args(c); | |||
execution(* ParentHasChildren.addChild(ChildHasParent)) && this(p) && args(c); | |||
/** | |||
* Matches at a removeChild join point for the parent type P and child type C | |||
*/ | |||
public pointcut removingChild(Parent p, Child c) : | |||
execution(* Parent.removeChild(Child)) && this(p) && args(c); | |||
execution(* ParentHasChildren.removeChild(ChildHasParent)) && this(p) && args(c); | |||
} | |||
@@ -95,7 +95,7 @@ import org.aspectj.lang.annotation.*; | |||
} | |||
aspect GenericAspectX extends ParentChildRelationship<Top,Bottom> { | |||
aspect GenericAspectY extends ParentChildRelationship<Top,Bottom> { | |||
// Advice to trigger weave infos | |||
before(Top p): /*ParentChildRelationship.*/addingChildSimple(p) {} |
@@ -0,0 +1,173 @@ | |||
import java.util.*; | |||
import java.lang.reflect.*; | |||
import org.aspectj.lang.annotation.*; | |||
/** | |||
* a generic aspect, we've used descriptive role names for the type variables | |||
* (Parent and Child) but you could use anything of course | |||
*/ | |||
/*public */ abstract aspect ParentChildRelationship<Parent,Child> { | |||
/** generic interface implemented by parents */ | |||
interface ParentHasChildren<C extends ChildHasParent>{ | |||
List<C> getChildren(); | |||
void addChild(C child); | |||
void removeChild(C child); | |||
} | |||
/** generic interface implemented by children */ | |||
interface ChildHasParent<P extends ParentHasChildren>{ | |||
P getParent(); | |||
void setParent(P parent); | |||
} | |||
/** ensure the parent type implements ParentHasChildren<child type> */ | |||
declare parents: Parent implements ParentHasChildren<Child>; | |||
/** ensure the child type implements ChildHasParent<parent type> */ | |||
declare parents: Child implements ChildHasParent<Parent>; | |||
// Inter-type declarations made on the *generic* interface types to provide | |||
// default implementations. | |||
/** list of children maintained by parent */ | |||
public List<C> ParentHasChildren<C>.children = new ArrayList<C>(); | |||
/** reference to parent maintained by child */ | |||
public P ChildHasParent<P>.parent; | |||
/** Default implementation of getChildren for the generic type ParentHasChildren */ | |||
public List<C> ParentHasChildren<C>.getChildren() { | |||
return Collections.unmodifiableList(children); | |||
} | |||
/** Default implementation of getParent for the generic type ChildHasParent */ | |||
public P ChildHasParent<P>.getParent() { | |||
return parent; | |||
} | |||
/** | |||
* Default implementation of addChild, ensures that parent of child is | |||
* also updated. | |||
*/ | |||
public void ParentHasChildren<C>.addChild(C child) { | |||
if (child.parent != null) { | |||
child.parent.removeChild(child); | |||
} | |||
children.add(child); | |||
child.parent = this; | |||
} | |||
/** | |||
* Default implementation of removeChild, ensures that parent of | |||
* child is also updated. | |||
*/ | |||
public void ParentHasChildren<C>.removeChild(C child) { | |||
if (children.remove(child)) { | |||
child.parent = null; | |||
} | |||
} | |||
/** | |||
* Default implementation of setParent for the generic type ChildHasParent. | |||
* Ensures that this child is added to the children of the parent too. | |||
*/ | |||
public void ChildHasParent<P>.setParent(P parent) { | |||
parent.addChild(this); | |||
} | |||
/** | |||
* Matches at an addChild join point for the parent type P and child type C | |||
*/ | |||
public pointcut addingChild(Parent p, Child c) : | |||
execution(* ParentHasChildren.addChild(ChildHasParent)) && this(p) && args(c); | |||
/** | |||
* Matches at a removeChild join point for the parent type P and child type C | |||
*/ | |||
public pointcut removingChild(Parent p, Child c) : | |||
execution(* ParentHasChildren.removeChild(ChildHasParent)) && this(p) && args(c); | |||
} | |||
aspect GenericAspectZ extends ParentChildRelationship<Top,Bottom> { | |||
before(Top p,Bottom c): addingChild(p,c) {} | |||
before(Top p,Bottom c): removingChild(p,c) {} | |||
public static void main(String []argv) { | |||
// Check the state of top | |||
Top t = new Top(); | |||
check(t instanceof ParentHasChildren,"Top should implement ParentHasChildren"); | |||
Type[] intfs = Top.class.getGenericInterfaces(); | |||
check(intfs[0] instanceof ParameterizedType, | |||
"Expected Top to have parameterized interface but found "+intfs[0]); | |||
ParameterizedType pt = (ParameterizedType) intfs[0]; | |||
Type[] tArgs = pt.getActualTypeArguments(); | |||
check(tArgs[0]==Bottom.class, | |||
"Expecting Bottom parameter but found " + tArgs[0]); | |||
// Check the state of top | |||
Bottom b = new Bottom(); | |||
check(b instanceof ChildHasParent,"Bottom should implement ChildHasParent"); | |||
intfs = Bottom.class.getGenericInterfaces(); | |||
check(intfs[0] instanceof ParameterizedType, | |||
"Expected Bottom to have parameterized interface but found "+intfs[0]); | |||
pt = (ParameterizedType) intfs[0]; | |||
tArgs = pt.getActualTypeArguments(); | |||
check(tArgs[0]==Top.class, | |||
"Expecting Top parameter but found " + tArgs[0]); | |||
// Field fiddling | |||
b.parent = t; | |||
List<Bottom> kids = new ArrayList<Bottom>(); | |||
kids.add(b); | |||
t.children = kids; | |||
// start using the methods | |||
List<Bottom> kids2 = t.getChildren(); | |||
check(kids2.size()==1, | |||
"Expected one child of the Top but found "+kids2.size()); | |||
check(kids2.get(0).equals(b), | |||
"Expected one child of the Top which was what we put in there!"+kids2.get(0)); | |||
// and the parent methods | |||
Top retrievedParent = b.getParent(); | |||
check(retrievedParent==t, | |||
"parent check 1 failed "+ | |||
"retrieved="+retrievedParent+" expected="+t); | |||
Top top2 = new Top(); | |||
b.setParent(top2); | |||
Top retrievedParent2 = b.getParent(); | |||
check(retrievedParent2==top2, | |||
"parent check 2 failed "+ | |||
"retrieved="+retrievedParent2+" expected="+top2); | |||
Top top3 = new Top(); | |||
Bottom bot2 = new Bottom(); | |||
top3.addChild(bot2); | |||
Bottom aBottom = top3.getChildren().get(0); | |||
check(aBottom==bot2,"Incorrect child? expected="+bot2+" found="+aBottom); | |||
top3.removeChild(bot2); | |||
int size=top3.getChildren().size(); | |||
check(size==0,"Should be no children but there were "+size); | |||
} | |||
public static void check(boolean b,String msg) { | |||
if (!b) throw new RuntimeException(msg); | |||
} | |||
} | |||
class Top {} | |||
class Bottom {} | |||
@@ -395,7 +395,8 @@ public class GenericsTests extends XMLBasedAjcTestCase { | |||
public void testSophisticatedAspectsV() {runTest("uberaspects - V");} // casts are gone | |||
public void testSophisticatedAspectsW() {runTest("uberaspects - W");} | |||
public void testSophisticatedAspectsX() {runTest("uberaspects - X");} // from the AJDK | |||
// public void testSophisticatedAspectsY() {runTest("uberaspects - Y");} // pointcut matching | |||
public void testSophisticatedAspectsY() {runTest("uberaspects - Y");} // pointcut matching | |||
public void testSophisticatedAspectsZ() {runTest("uberaspects - Z");} | |||
// FIXME asc these two tests have peculiar error messages - generic aspect related | |||
// public void testItdUsingTypeParameter() {runTest("itd using type parameter");} |
@@ -4226,9 +4226,49 @@ | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/genericaspects/" title="uberaspects - Y"> | |||
<compile files="GenericAspectY.aj" options="-1.5 -showWeaveInfo"> | |||
<message kind="weave" text="Join point 'method-execution(void ParentChildRelationship$ParentHasChildren.addChild(C))' in Type 'ParentChildRelationship' (GenericAspectY.aj:53) advised by before advice from 'GenericAspectY' (GenericAspectY.aj:101) [with runtime test]"/> | |||
<message kind="weave" text="Extending interface set for type 'Top' (GenericAspectY.aj) to include 'ParentChildRelationship$ParentHasChildren<Bottom>' (GenericAspectY.aj)"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectY.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectY.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.children')"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.getChildren()')"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'void ParentChildRelationship$ParentHasChildren.addChild(C)')"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'void ParentChildRelationship$ParentHasChildren.removeChild(C)')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectY.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectY.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.children')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.getChildren()')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'void ParentChildRelationship$ParentHasChildren.addChild(C)')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'void ParentChildRelationship$ParentHasChildren.removeChild(C)')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ChildHasParent' (GenericAspectY.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectY.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.parent')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ChildHasParent' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.getParent()')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ChildHasParent' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'void ParentChildRelationship$ChildHasParent.setParent(P)')"/> | |||
<message kind="weave" text="Extending interface set for type 'Bottom' (GenericAspectY.aj) to include 'ParentChildRelationship$ChildHasParent<Top>' (GenericAspectY.aj)"/> | |||
<message kind="weave" text="Type 'Bottom' (GenericAspectY.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectY.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.parent')"/> | |||
<message kind="weave" text="Type 'Bottom' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.getParent()')"/> | |||
<message kind="weave" text="Type 'Bottom' (GenericAspectY.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectY.aj:'void ParentChildRelationship$ChildHasParent.setParent(P)')"/> | |||
</compile> | |||
<run class="GenericAspectY"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/generics/genericaspects/" title="uberaspects - Z"> | |||
<compile files="GenericAspectZ.aj" options="-1.5 -showWeaveInfo"> | |||
<message kind="weave" text="Join point 'method-execution(void ParentChildRelationship$ParentHasChildren.addChild(C))' in Type 'ParentChildRelationship' (GenericAspectZ.aj:53) advised by before advice from 'GenericAspectZ' (GenericAspectZ.aj:95) [with runtime test]"/> | |||
<message kind="weave" text="Join point 'method-execution(void ParentChildRelationship$ParentHasChildren.removeChild(C))' in Type 'ParentChildRelationship' (GenericAspectZ.aj:65) advised by before advice from 'GenericAspectZ' (GenericAspectZ.aj:96) [with runtime test]"/> | |||
<message kind="weave" text="Extending interface set for type 'Top' (GenericAspectZ.aj) to include 'ParentChildRelationship$ParentHasChildren<Bottom>' (GenericAspectZ.aj)"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectZ.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectZ.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.children')"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.getChildren()')"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'void ParentChildRelationship$ParentHasChildren.addChild(C)')"/> | |||
<message kind="weave" text="Type 'Top' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'void ParentChildRelationship$ParentHasChildren.removeChild(C)')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectZ.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectZ.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.children')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'java.util.List<C> ParentChildRelationship$ParentHasChildren.getChildren()')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'void ParentChildRelationship$ParentHasChildren.addChild(C)')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ParentHasChildren' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'void ParentChildRelationship$ParentHasChildren.removeChild(C)')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ChildHasParent' (GenericAspectZ.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectZ.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.parent')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ChildHasParent' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.getParent()')"/> | |||
<message kind="weave" text="Type 'ParentChildRelationship$ChildHasParent' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'void ParentChildRelationship$ChildHasParent.setParent(P)')"/> | |||
<message kind="weave" text="Extending interface set for type 'Bottom' (GenericAspectZ.aj) to include 'ParentChildRelationship$ChildHasParent<Top>' (GenericAspectZ.aj)"/> | |||
<message kind="weave" text="Type 'Bottom' (GenericAspectZ.aj) has intertyped field from 'ParentChildRelationship' (GenericAspectZ.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.parent')"/> | |||
<message kind="weave" text="Type 'Bottom' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'ParentChildRelationship$ParentHasChildren ParentChildRelationship$ChildHasParent.getParent()')"/> | |||
<message kind="weave" text="Type 'Bottom' (GenericAspectZ.aj) has intertyped method from 'ParentChildRelationship' (GenericAspectZ.aj:'void ParentChildRelationship$ChildHasParent.setParent(P)')"/> | |||
</compile> | |||
<run class="GenericAspectZ"/> | |||
</ajc-test> | |||