Community
Participate
Working Groups
Matching Enum values is not facilitated with a JoinPoint pattern. Enum code requires Enum value JoinPoints. Currently the following simple aspect acts when a constant-specific method with a particular Enum value is executed. @Pointcut( "execution(List<T> getSameValue()) && target(testEnum) && if()") public static boolean testPointcut1( TestEnum testEnum ){ return testEnum == TestEnum.Value2; } @Before("testPointcut1(testEnum)") public void test1( TestEnum testEnum ) { System.out.println( "Generics aspect [" + testEnum.ordinal() + "]" ); } The Enum is public enum TestEnum { Value1{ public <T> List<T> getValue(){ return null; } public <T> List<T> getSameValue(){ return null; } }, Value2{ public <T> Set<T> getValue(){ return null; } public <T> List<T> getSameValue(){ return null; } }; abstract <T> Collection<T> getValue(); abstract <T> Collection<T> getSameValue(); public static void main(String[] args) { System.out.println( Value1.getSameValue() ); System.out.println( Value2.getSameValue() ); } } Even though this is a simple use case more complicated Enum code is possible.
just bringing it onto the radar, unlikely to make 1.6.3
unsetting the target field which is currently set for something already released
Just like Andy said on the mailing list, I am also not really sure what you want here. You did not describe it clearly. My guess is that somehow you wish to limit the target to a specific instance (i.e. to a specific enum value) statically without having to use the dynamic if() pointcut. This would be a completely new feature, not just for enums but for any kind of target. I doubt that we will ever see something like this in AspectJ syntax. The only part of AspectJ where something similar exists is annotation parameter matching where you can limit to parameters matching certain primitive type or enum constants. What is possible as of today is only what you used plus something like is(EnumType) or !is(EnumType), but that does not help you much in this case. I am not really sure what you want to achieve with the generics in your enum, so I was tempted to remove them when extending your sample code in order to show what is possible. But I kept them, so you do not think that removing the '<T>' stuff would cause any of the behaviour you see. ------------------------------------------------------------------------ package de.scrum_master.app; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; public enum TestEnum { Value1 { public <T> List<T> getValue() { return null; } public <T> List<T> getSameValue() { return (List<T>) Arrays.asList(1, 2, 3); } }, Value2 { public <T> Set<T> getValue() { return null; } public <T> List<T> getSameValue() { return (List<T>) Arrays.asList(4, 5, 6); } }; abstract <T> Collection<T> getValue(); abstract <T> Collection<T> getSameValue(); public static void main(String[] args) { System.out.println(Value1.getSameValue()); System.out.println(Value2.getSameValue()); System.out.println(new NoEnum().getSameValue()); new NoEnum().doSomething(Value1); new NoEnum().doSomething(Value2); } public static class NoEnum { public <T> List<T> getSameValue() { return (List<T>) Arrays.asList(7, 8, 9); } public void doSomething(TestEnum testEnum) { System.out.println(testEnum); } } } ------------------------------------------------------------------------ package de.scrum_master.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import de.scrum_master.app.TestEnum; @Aspect public class MyAspect { @Pointcut("execution(java.util.List getSameValue()) && target(testEnum) && if()") public static boolean testPointcut1(TestEnum testEnum) { return testEnum == TestEnum.Value2; } @Before("testPointcut1(testEnum)") public void test1(JoinPoint joinPoint, TestEnum testEnum) { System.out.println(joinPoint + " -> " + testEnum); } @Pointcut("execution(* *(*)) && args(testEnum) && if()") public static boolean testPointcut2(TestEnum testEnum) { return testEnum == TestEnum.Value2; } @Before("testPointcut2(testEnum)") public void test2(JoinPoint joinPoint, TestEnum testEnum) { System.out.println(joinPoint + " -> " + testEnum); } @Before("execution(* (!is(EnumType)).getSameValue())") public void test3(JoinPoint joinPoint) { System.out.println(joinPoint + " -> no enum"); } } ------------------------------------------------------------------------ Console log: [1, 2, 3] execution(List de.scrum_master.app.TestEnum.2.getSameValue()) -> Value2 [4, 5, 6] execution(List de.scrum_master.app.TestEnum.NoEnum.getSameValue()) -> no enum [7, 8, 9] Value1 execution(void de.scrum_master.app.TestEnum.NoEnum.doSomething(TestEnum)) -> Value2 Value2
Thanks. Your code works. I think my pointcut @Pointcut( "execution(List<T> getSameValue()) && target(testEnum) && if()") wasn't correct. I think it meant that I was trying to statically match using target(testEnum) and also dynamically match using if(). Is this the problem you point out ? I may be misremembering my goal. That was an old issue.
It was not correct insofar as the '<T>' did not really help and the 'List' class was not fully qualified by its package name. So are you saying that the only problem you had for 12 years is that you couldn't get the syntax straight and there is not really any new AspectJ feature you need? I am asking directly in order to understand better.
Besides, if you don't remember the purpose of this issue yourself, why did you bring it up again on the mailing list? I thought you had a specific problem. Anyway, I am glad that the problem seems to be solved. Would you agree that the issue be closed by a maintainer (Andy usually)?
Yes. You can close it. I have a specific problem now( didn't use AspectJ during these years ) and I remembered the old issue. I will reply to Andy's mail.
A question I have is this. The generics syntax isn't useful for this code when I use AspectJ. Is that what you mean ? Are there examples that use the generics syntax ?
package state; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class EnumAspect { @Pointcut("execution(java.util.List getValue()) && target(testEnum) && if()") public static boolean testPointcut1(TestEnum testEnum) { return testEnum == TestEnum.Value2; } @Before("testPointcut1(testEnum)") public void test1(JoinPoint joinPoint, TestEnum testEnum) { System.out.println(joinPoint + " -> " + testEnum); } @Pointcut("execution(* *(*)) && args(testEnum) && if()") public static boolean testPointcut2(TestEnum testEnum) { return testEnum == TestEnum.Value2; } @Before("testPointcut2(testEnum)") public void test2(JoinPoint joinPoint, TestEnum testEnum) { System.out.println(joinPoint + " -> " + testEnum); } @Before("execution(* (!is(EnumType)).getValue())") public void test3(JoinPoint joinPoint) { System.out.println(joinPoint + " -> no enum"); } } package state; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; public enum TestEnum { Value1 { public <T> List<T> getValue() { return null; } // public <T> List<T> getSameValue() { // return (List<T>) Arrays.asList(1, 2, 3); // } }, Value2 { public <T> Set<T> getValue() { return null; } // public <T> List<T> getSameValue() { // return (List<T>) Arrays.asList(4, 5, 6); // } }; abstract <T> Collection<T> getValue(); //abstract <T> Collection<T> getSameValue(); public static void main(String[] args) { System.out.println(Value1.getValue()); System.out.println(Value2.getValue()); } } Is this code missing something that your doesn't ? Asking because it doesn't work for me.
You changed the sample code, so the pointcut does not match anymore: Value1.getValue() does not match as planned, because the 'if()' pointcut limits to Value2. Value2.getValue() does not match, because you changed the method to return a Set, not a List. So if you the pointcut expression for adjust testPointcut1 to execution(java.util.Collection getValue()) && target(testEnum) && if() or, more explicitly, to execution(java.util.Collection+ getValue()) && target(testEnum) && if() your test1 advice should get triggered.
As for your other question, here is a chapter about generics in AspectJ which you might want to read. Maybe I should read it again, too. I do not use generics a lot in connection with AspectJ. https://www.eclipse.org/aspectj/doc/released/adk15notebook/generics-inAspectJ5.html
Like I said before, using generics does not really make sense in an enum, it would not have any effect as far as I can see. How about this? ------------------------------------------------------------------------ package state; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; public enum TestEnum { Value1 { public List<Integer> getValue() { return Arrays.asList(1, 2, 3); } public List<Integer> getSameValue() { return Arrays.asList(4, 5, 6); } }, Value2 { public Set<String> getValue() { return new HashSet<String>(Arrays.asList("foo", "bar", "zot")); } public Set<String> getSameValue() { return new HashSet<String>(Arrays.asList("one", "two", "three")); } }; abstract Collection<?> getValue(); abstract Collection<?> getSameValue(); public static void main(String[] args) { System.out.println(Value1.getValue()); System.out.println(Value1.getSameValue()); System.out.println(Value2.getValue()); System.out.println(Value2.getSameValue()); } } ------------------------------------------------------------------------ Please note that you can still make both constants return different Collection<?> types such as List<Integer> or Set<String>, why ever you would want to do that. (Maybe in order to make the program harder to read and maintain.) ------------------------------------------------------------------------ package state; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class EnumAspect { @Pointcut("execution(java.util.Collection getValue()) && target(testEnum) && if()") public static boolean testPointcut1(TestEnum testEnum) { return testEnum == TestEnum.Value2; } @Before("testPointcut1(testEnum)") public void test1(JoinPoint joinPoint, TestEnum testEnum) { System.out.println(joinPoint + " -> " + testEnum); } } ------------------------------------------------------------------------ Now the console log would be: ------------------------------------------------------------------------ [1, 2, 3] [4, 5, 6] execution(Set state.TestEnum.2.getValue()) -> Value2 [bar, foo, zot] [one, two, three]