diff --git a/org.jgrapes.core/src/org/jgrapes/core/annotation/Handler.java b/org.jgrapes.core/src/org/jgrapes/core/annotation/Handler.java index 09d67587948..0990f080054 100644 --- a/org.jgrapes.core/src/org/jgrapes/core/annotation/Handler.java +++ b/org.jgrapes.core/src/org/jgrapes/core/annotation/Handler.java @@ -80,8 +80,8 @@ * Finally, independent of any specified channels, the matching algorithm * invokes {@link Eligible#isEligibleFor(Object) isEligibleFor} * for each of the event's channels with the component's default criterion - * as argument. This results in a match if - * the component itself is used as one of the event's channels + * as argument unless {@link #excludeSelf()} is set. This results in a match + * if the component itself is used as one of the event's channels * (see the description of {@link Eligible}). * * If a match is found for a given event's properties and a handler's @@ -265,6 +265,26 @@ final class NoChannel extends ClassChannel { */ boolean dynamic() default false; + /** + * Excludes the handler from channel matching against its component's + * default criterion. The typical use case for this annotation is + * a converter component that receives events from some source channel + * and then fires the same kind of events with modified data using + * itself as the (source) channel. In this case, the events + * generated by the component must not be processed by the component + * although they are fired using the component as channel. So while it + * is useful to be able to target a specific component (using it as + * channel) in general, it isn't in this special case and can therefore + * be turned off with this annotation. + * + * Of course, it would also be possible to work around the ambiguity + * by firing the conversion results on an extra channel. But it is + * quite intuitive to use the component itself as (source) channel. + * + * @return true, if set + */ + boolean excludeSelf() default false; + /** * This class provides the {@link Evaluator} for the * {@link Handler} annotation provided by the core package. It @@ -495,7 +515,7 @@ public Scope(ComponentType component, Method method, } // Finally, a component always handles events // directed at it directly. - if (component instanceof Channel) { + if (component instanceof Channel && !annotation.excludeSelf()) { channelCriteria.add( ((Channel) component).defaultCriterion()); }