I've done the same thing in my project, taking it a step further: I've
hidden the annotation implementation in an InvocationHandler and written a
simple factory that takes the annotation class and enum value and creates a
dynamic proxy for the annotation desired:

public final class AnnotationFactory {

    public static <A extends Annotation,
                   E extends Enum<E>> A create(final Class<A> annoClass,
                                               final E theEnum) {
        // Details omitted for brevity
    }
}

An AnnotationInvocationHandler class (not shown) implements the details of
the annotation specification.  You wouldn't then be forced to re-implement
the annotation implementation for each new annotation class you create,
just create them programatically using the factory.

Your code could then look like this:

private void bindFoo(Class<? extends Foo> fooClass,
                     WhatKindOfStuff whatKindOfStuff) {
   bind(Foo.class)
     .annotatedWith(AnnotationFactory.create(DoesFooStuff.class,
                                             whatKindOfStuff))
     .to(fooClass);
}

This makes DoesFooStuffImpl class unnecessary.

-Russ

On Fri, Sep 7, 2012 at 9:59 AM, Fred Faber <[email protected]> wrote:

> Noticed the typos now.  I started by naming "DoesFooStuff" naming as "
> FooClient", so please disregard those references.
>
> On Fri, Sep 7, 2012 at 9:57 AM, Fred Faber <[email protected]> wrote:
>
>> A pattern to mitigate the boilerplate is to use a parameterized
>> annotation:
>>
>>   @Retention(RetentionPolicy.RUNTIME)
>>   @BindingAnnotation
>>   public @interface DoesFooStuff {
>>     DoesFooStuff value();
>>
>>     enum WhatKindOfStuff {
>>
>>       STUFF_THAT_A_WANTS,
>>
>>       STUFF_THAT_B_WANTS,
>>
>>       ...
>>
>>       STUFF_THAT_Z_WANTS
>>
>>     }
>>
>>   }
>>
>> You would then use this to annotate your Foos:
>>
>>
>> class AFoo {
>>
>>   @Inject AFoo(@DoesStuffForFoo(Foo.WhatKindOfStuff.STUFF_THAT_A_WANTS) IFoo 
>> foo) {
>>
>>     ...
>>
>>   }
>>
>> }
>>
>>
>>
>> In your module you'd define an implementation of the interface (which is 
>> tricky...you need to be careful to follow the spec on the Annotation 
>> javadoc):
>>
>>
>>   @SuppressWarnings("ClassExplicitlyAnnotation")
>>   private static class DoesFooStuffImpl implements DoesStuffForFoo {
>>
>>     private final WhatKindOfStuff value;
>>
>>     private DoesFooStuffImpl(WhatKindOfStuff value) {
>>
>>       this.value = value;
>>     }
>>
>>     @Override WhatKindOfStuff String value() {
>>       return value;
>>     }
>>
>>     @Override public Class<? extends Annotation> annotationType() {
>>       return DoesStuffForFoo.class;
>>     }
>>
>>     @Override public String toString() {
>>       return "@" + DoesStuffForFoo.class.getName() + "(value=" + value + ")";
>>
>>     }
>>
>>     @Override public boolean equals(Object o) {
>>       return o instanceof DoesStuffForFooImpl
>>
>>           && ((DoesStuffForFoo) o).value().equals(value());
>>     }
>>
>>     @Override public int hashCode() {
>>       return (127 * "value".hashCode()) ^ value.hashCode();
>>     }
>>
>>   }
>>
>>
>> You could then define a helper method as syntatic sugar over the binding:
>>
>>
>> private void bindFoo(Class<? extends Foo> fooClass, WhatKindOfStuff 
>> whatKindOfStuff {
>>
>>    bind(Foo.class)
>>      .annotatedWith(new DoesFooStuffImpl(whatKindOfStuff))
>>      .to(fooClass);
>> }
>>
>> And then your bindings become:
>>
>> @Override protected void configure() {
>>   bindFoo(FooThatAFooWants.class, WhatKindOfStuff.STUFF_THAT_A_WANTS);
>>   bindFoo(FooThatBFooWants.class, WhatKindOfStuff.STUFF_THAT_B_WANTS);
>>   ...
>>   bindFoo(FooThatZFooWants.class, WhatKindOfStuff.STUFF_THAT_Z_WANTS);
>>  }
>>
>>
>> Fred
>>
>> On Fri, Sep 7, 2012 at 3:02 AM, robertdup <[email protected]> wrote:
>>
>>> Yes it's right.. but this way don't satisfy me totally cause I have some
>>> XFoo classes.
>>> I will have to create many annotation (@A,@B, ..., @Z), and I must bind
>>> all of them or I will get a guice exception.
>>>
>>> bind(IFoo.class).annotatedWith.(A.class).to(DefaultFoo.class);
>>> bind(IFoo.class).annotatedWith.(B.class).to(DefaultFoo.class);
>>> [...]
>>> bind(IFoo.class).annotatedWith.(Y.class).to(DefaultFoo.class);
>>> bind(IFoo.class).annotatedWith.(Z.class).to(DefaultFoo.class);
>>>
>>> In my case, I just have to override a couple of binding and let the
>>> other on the default implementation (DefaultFoo.class)
>>> bind(IFoo.class).annotatedWith.(E.class).to(MyEFoo.class);
>>> bind(IFoo.class).annotatedWith.(K.class).to(MyKFoo.class);
>>>
>>> Otherwise, PrivateModule looks too "heavy" to implement in my case..
>>>
>>>
>>>    - Well, Is there an other way that could be less verbose ?
>>>
>>>
>>> Best regards;
>>>
>>>
>>> On Friday, September 7, 2012 3:59:12 AM UTC+2, Fred Faber wrote:
>>>
>>>> Strictly speaking, the robot legs problem describes a scenario where
>>>> the types of your object chain are identical.  In your case, you wouldn't
>>>> have AFoo and BFoo, but just Foo.  It's a luxury of sorts to have AFoo and
>>>> BFoo because you _can_ use a binding annotation on the constructor of each.
>>>>  That is the solution I would prefer for its clarity in how AFoo and BFoo
>>>> are being configured:
>>>>
>>>> class AFoo {
>>>>   @Inject AFoo(@DoesStuffRelatedToA IFoo ifoo) { ... }
>>>> }
>>>>
>>>> class BFoo {
>>>>   @Inject BFoo(@DoesStuffRelatedToB IFoo ifoo) { ... }
>>>>  }
>>>>
>>>> Here, grepping through the code directly for DoesStuffRelatedToA would
>>>> lead me to the binding for IFoo in context of AFoo, and that's a little bit
>>>> of a win for code maintenance.
>>>>
>>>> Fred
>>>>
>>>> On Thu, Sep 6, 2012 at 12:51 PM, robertdup <[email protected]> wrote:
>>>>
>>>>>  Thanks for your reply.
>>>>>
>>>>> Do you know if it's a common uses to have more than 20 privates
>>>>> modules ?
>>>>>
>>>>>
>>>>>
>>>>> On Thursday, September 6, 2012 4:00:35 PM UTC+2, Thomas Broyer wrote:
>>>>>>
>>>>>> This is known as the "robot legs" problem, see
>>>>>> http://code.google.com/p/**g**oogle-guice/wiki/**FrequentlyAsk**
>>>>>> edQuestions#How_**do_I_build_**two_similar_but_**slightly_**
>>>>>> different_trees_of_**objec<http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec>
>>>>>>
>>>>>> On Thursday, September 6, 2012 9:14:24 AM UTC+2, robertdup wrote:
>>>>>>>
>>>>>>> Hello there,
>>>>>>>
>>>>>>> I trying to implement default binding on my module without any
>>>>>>> success...
>>>>>>>
>>>>>>> Here is what I would like to do (*my dream*) :
>>>>>>>
>>>>>>> class AFoo
>>>>>>>> {
>>>>>>>>     @Inject AFoo( IFoo foo ){}
>>>>>>>> }
>>>>>>>>
>>>>>>>> class BFoo
>>>>>>>> {
>>>>>>>>    @Inject BFoo( IFoo foo ){}
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>> bind(IFoo.class).to(**DefaultFoo**.class);
>>>>>>>> bind(IFoo.class).to(OtherFoo.**c**lass)*.on(BFoo.class)*;
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I know that I could solve this problem using annotation like this :
>>>>>>>
>>>>>>> class AFoo
>>>>>>>> {
>>>>>>>>     @Inject AFoo( @A IFoo foo ){}
>>>>>>>> }
>>>>>>>>
>>>>>>>> class BFoo
>>>>>>>> {
>>>>>>>>    @Inject BFoo( @B IFoo foo ){}
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>> bind(IFoo.class).**annotatedWith**(A.class).to(**DefaultFoo.class)*
>>>>>>>> *;
>>>>>>>> bind(IFoo.class).**annotatedWith**(B.class).to(**OtherFoo.class);
>>>>>>>>
>>>>>>>
>>>>>>> But this way is too boring and dirty.. (because I have to add
>>>>>>> annotation/binding definition for each one)
>>>>>>>
>>>>>>>
>>>>>>>    - *Are there some others ways to solve Default binding "problem"
>>>>>>>    ?*
>>>>>>>
>>>>>>> Thanks in advance; Best regards
>>>>>>>
>>>>>>  --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "google-guice" group.
>>>>> To view this discussion on the web visit https://groups.google.com/d/*
>>>>> *msg/google-guice/-/**bqRh1CKDwsEJ<https://groups.google.com/d/msg/google-guice/-/bqRh1CKDwsEJ>
>>>>> .
>>>>>
>>>>> To post to this group, send email to [email protected].
>>>>> To unsubscribe from this group, send email to google-guice...@**
>>>>> googlegroups.com.
>>>>>
>>>>> For more options, visit this group at http://groups.google.com/**
>>>>> group/google-guice?hl=en<http://groups.google.com/group/google-guice?hl=en>
>>>>> .
>>>>>
>>>>
>>>>
>>
>  --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>



-- 
Gambling Problem? Call 1-800-Gambler

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to