SoulSpirit created WICKET-4930:
----------------------------------

             Summary: Generified Component and Component.inputConverter()
                 Key: WICKET-4930
                 URL: https://issues.apache.org/jira/browse/WICKET-4930
             Project: Wicket
          Issue Type: Wish
          Components: wicket
    Affects Versions: 6.4.0, 7.0
            Reporter: SoulSpirit
         Attachments: 0001-From-Component-to-Component-T.patch

Many years are passed since I first used Wicket and there are 2 things I've 
never really understood:
1. Why Component hasn't been generified (i.e. type parametrized)?
2. Why Component.getConverter() takes a Class<C> parameter?

For the first question, I have the suspect the answser brings to backward 
compatibilities issues (even if Wicket project hasn't always been so much 
backward compatible between releases). The recent introduction of 
IGenericComponent is a hint.

The answer to the second question came clear after a recent release (I don't 
remember which) that broke some of my components (I'll explain later why). I've 
always used Converters to convert the model object to a String, but I've 
learned that they are also used to convert "other" values related to the 
Component.
For example, an AbstractChoice may have a model of type X, and at the same time 
showing values (the choices) of a different type Y. I never ever had this need, 
but I understand it's a possibility, and that it should be possible to set a 
Converter for either type X and Y.
The problem is that the only tool Component.getConverter() has to choose 
between the available Converters is the Class<C> of the value we want to 
convert, and this isn't always enought.

The recent Wicket release I was speaking about changed the way validation 
messages are generated, converting every message's variable (${input} and 
${label} too) with the Component's Converter.
If, for example, a custom Component is bound to a IModel<String> that need 
custom conversion, the same Converter is used to transform that ${label} that 
compose the validation message. And there's no way to avoid it without 
re-engineering the custom Component.

I think is more natural to refer to a "component converter" as something that 
"converts the model to a string".
The tipical Component.getConverter() implementation looks like this:

public <C> IConverter<C> getConverter(final Class<C> type)
  if (MyType.class.isAssignableFrom(type)){
    return (IConverter<C>)converter;
  }else{
    return super.getConverter(type);
}

but I'd like to have something like this, that just converts from/to the type 
of the component's model:

public IConverter<MyType> getInputConverter(){
  return converter;
}

Obviously, this syntax requires Component to be defined with a type parameter.

The patch I've attached introduces the method 
Component#getInputConverter(Class<T>).
I haven't removed the Class parameter present in the original #getConverter() 
method to avoid reflection use, but I have introduced 
FormComponent#getInputConverter() (without parameters) as a shortcut to it.

Along with these two methods, I changed the declaration of Component to 
Component<T>, and I updated all the framework to support that type parameter, 
thus removing IGenericComponent, GenericPanel and GenericWebPage.

The patch breaks something in the compatibility field, but I've updated all the 
tests to work correctly, and I've made most of them making use of the new type 
parameter. I'm open to discuss it in detail if someone is interested.
Little confusion remains in the project about type parameters related to 
List<T>, List<? extends T>, ? extends List<? extends T>, Collection<T>, ... , 
but that sort of confusion was already present and I haven't invested much time 
trying to fix it.

This patch isn't fully polished as I haven't checked if all the classes make 
use of the new type parameter and I haven't tried it with any of my real 
projects, because I understand it will not be so easily integrated into the 
main branch. It represents just an idea to demonstrate that such a refactoring 
is possible, and it is fairly effortless (it took me about 10 hours of work).

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to