It has taken me longer than expected, but I just felt exhausted after I finished the implementation of @PredicateLink
-type annotations, and I had to slow down a little. I also struggled with fixing DrJava bug [ 1578865 ], and that consumed about two afternoons, without a successful end thus far.
Now I have almost finished the implementation of @Combine
, and I can (almost) do cool things like these:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | @Combine @interface OrNames { OnlyThreadWithName[] value(); } @Combine(Combine.Mode.AND) @interface NameAndGroup { OnlyThreadWithName name() default @OnlyThreadWithName("foo"); OnlyThreadWithGroupName group() default @OnlyThreadWithGroupName("main"); } @Combine(Combine.Mode.OR) @interface CombineCombine { OrNames names() default @OrNames({ @OnlyThreadWithName("foo"), @OnlyThreadWithName("bar")}); NameAndGroup nameAndGroup() default @NameAndGroup(); } @Combine(Combine.Mode.NOT) public @interface NotEventThread { OnlyEventThread value() default @OnlyEventThread; } |
What doesn’t work right yet is the handling of arrays of annotations, as in the @OrNames
annotation above. Right now, I produce one class file for each @Combine
-type annotation, and that class file includes exactly one method with all the parameters for all the member annotations.
The predicate method for @NameAndGroup
, for example, is boolean check(Object thisO, String a, boolean b, String c, boolean d)
, since all predicates have the value of this
or null
as first parameter, and the predicates of the two member annotations @OnlyThreadWithName
and OnlyThreadWithGroupName
both require a String
and a boolean
in addition to the Object thisO
.
Unfortunately, this approach of creating one method that has all the parameters required for its member annotations doesn’t work for arrays of annotations, of course, since the array can have a different number of elements every time the @Combine
-type annotation is used. I still like the general approach of flattening out the parameter list; it makes it very easy to pass the arguments to the member predicate methods. Now I have to figure out how I handle arrays of annotations.
There are two options that I see right now:
- Treat the array of annotations as one parameter, and then write some kind of
for
loop in the auto-generated predicate method to call the predicate method of every array element. The problem with this approach is that I don’t know how to treat an annotation as a value and access its parts at runtime. Would the annotation have to haveRUNTIME
retention? Annotations look like interfaces. Do I make make method calls to retrieve the data? - I create a new predicate method each time the number of elements differs. This is probably easier to do, but creates code bloat.
I may try to take a nap before I have to go to the office now, but considering that it’s 10 AM already, it’s pretty much pointless. I also have to figure out why the grading script didn’t work for Felipe on Friday.
Update: I guess there’s also the option of always using RUNTIME
retention and doing the entire lookup using reflection. Maybe I should do that as a comparison, but I have the feeling that this will be incredibly heavy-weight.