For now I provided a org.xwiki.component.util.DefaultParameterizedType
which is implemented like the one in the oracle JVM and which is what
I seen other libraries that need custom ParameterizedType doing. Works
pretty well so far with both orache JVM and OpenJDK. At worst if
someone report an issue with another JVM I have a backup plan which is
to change any ParameterizedType provided to EmbeddableComponentManager
in our DefaultParameterizedType but I would prefer to avoid that if
not absolutely necessary.

Also note that the issue is only when you lookup a component, you
can't have this kind of issue with injection. We don't have that much
ParameterizedType, only reference resolver/serializer plus the
Provider so it's not a very commons task either.

On Sun, Mar 11, 2012 at 9:05 PM, Andreas Jonsson <[email protected]> wrote:
> Hi,
>
> We must consider how we define the equality of RoleHints.  Different
> implementations of the interface ParameterizedType do not need to
> implement equals and hashValue consistently.  For instance, this lookup
> doesn't work at the moment:

Actually they do need to implement equals the same way since that's
part of the specs but there is no spec for  hashCode yes.

>
> Utils.getComponent(new ParameterizedType() {
>                @Override
>                public Type [] getActualTypeArguments() {
>                    Type [] args = {
>                        String.class
>                    };
>                    return args;
>                }
>
>                @Override
>                public Type getOwnerType() {
>                    return null;
>                }
>
>                @Override
>                public Type getRawType() {
>                    return DocumentReferenceResolver.class;
>                }
>            });
>

You don't need to do that, DocumentReferenceResolver provide to
statics Type to make easier to lookup it.

Utils.getComponent(DocumentReferenceResolver.TYPE_STRING)

> At the same time, there is the backwards compliancy issue. This might be
> ok for RoleHint equality:
>
>    /**
>     * Defines the equality of types.
>     *
>     * @param t1 operand for comparison.
>     * @param t2 operand for comparison.
>     * @return {\code true} if the roles should be considered equal.
>     */
>    private boolean typeEquals(Type t1, Type t2) {
>
>        if (t1 instanceof ParameterizedType && t2 instanceof
> ParameterizedType) {
>            ParameterizedType pt1 = (ParameterizedType) t1;
>            ParameterizedType pt2 = (ParameterizedType) t2;
>
>            Type [] args1 = pt1.getActualTypeArguments();
>            Type [] args2 = pt2.getActualTypeArguments();
>
>            if (args1.length != args2.length) {
>                return false;
>            }
>
>            for (int i = 0; i < args1.length; i++) {
>                if (!typeEquals(args1[i], args2[i])) {
>                    return false;
>                }
>            }
>        } else if ((t1 instanceof Class && !(t2 instanceof Class))
>                || (t2 instanceof Class && !(t1 instanceof Class))) {
>            /*
>             * For compliancy with legacy code.
>             *
>             * Looking up components using raw classes only
>             * matches components registered as raw classes, and a
>             * component registered as raw class can only be
>             * looked up using a raw class.
>             */
>            return false;
>        }
>
>        Class c1 = ReflectionUtils.getTypeClass(t1);
>        Class c2 = ReflectionUtils.getTypeClass(t2);
>
>        return c1.equals(c2);
>    }
>
>    @Override
>    @SuppressWarnings("unchecked")
>    public boolean equals(Object obj)
>    {
>        if (this == obj) {
>            return true;
>        }
>
>        if ((obj == null) || (obj.getClass() != this.getClass())) {
>            return false;
>        }
>
>        RoleHint<T> rolehint = (RoleHint<T>) obj;
>
>        return typeEquals(getRoleType(), rolehint.getRoleType())
>            && (getHint() == rolehint.getHint() || (getHint() != null &&
> getHint().equals(rolehint.getHint())));
>    }
>
>    @Override
>    public int hashCode()
>    {
>        int hash = 8;
>
>        hash = 31 * hash + (null == getRoleType() ? 0 :
> ReflectionUtils.getTypeClass(getRoleType()).hashCode());
>        hash = 31 * hash + (null == getHint() ? 0 : getHint().hashCode());
>
>        return hash;
>    }
>
> /Andreas
>
>
> 2012-03-06 14:51, Thomas Mortagne skrev:
>> It's committed.
>>
>> Would be nice to have comments on the new APIs (suggest better naming,
>> etc...). It's a very important API and we really need to have
>> something we are sure of before 4.0 final.
>>
>> On Mon, Mar 5, 2012 at 6:53 PM, Thomas Mortagne
>> <[email protected]> wrote:
>>> Hi guys,
>>>
>>> I'm almost done but there is one little detail left: for easier
>>> retro-compatibility I would like to introduce a new @Role annotation
>>> and deprecate the @ComponentRole annotation. The idea is that Role
>>> will "officially" take into account generic parameters while
>>> ComponentRole does not. That way no existing component role behavior
>>> will be broken or require crappy retro-compatibility like registering
>>> automatically both generic and non generic roles (what I started to do
>>> at first).
>>>
>>> On Thu, Mar 1, 2012 at 6:20 PM, Thomas Mortagne
>>> <[email protected]> wrote:
>>>> Hi devs,
>>>>
>>>> I recently modified component manager internals and changed the role
>>>> used as key in the map from Class to Type so that it properly make a
>>>> difference between Provider<Toto> and Provider<Titi> without the need
>>>> to generate a special hint.
>>>>
>>>> For the one not aware of what Type is lets say it's what Class is
>>>> extending. Among other things Type is also extended by
>>>> ParameterizedType which is interesting here because it basically
>>>> contain a Class with it's generic parameters (it also indicate if the
>>>> type in included in another one but we don't care in our case ;)).
>>>>
>>>> To summarize:
>>>> * Provider is a Class
>>>> * Provider<String> is ParameterizedType
>>>> and both are Type
>>>>
>>>> That said I would like to  change the whole ComponentManager and
>>>> related descriptors APIs to use Type as role instead of Class.
>>>>
>>>> = What it bring
>>>>
>>>> What it means is that it makes possible to cleanly represent a
>>>> Provider in which the generic type is meaningful right in the
>>>> ComponentDescriptor (right now the generic type is extract from the
>>>> implementation class when the provider is registered which is pretty
>>>> crappy) and simplify a lot the current implementation.
>>>>
>>>> But it also mean we could use this new "feature" for other components.
>>>> For example right now we have things like:
>>>>
>>>> @Component
>>>> public class DefaultStringDocumentReferenceResolver implements
>>>> DocumentReferenceResolver<String>
>>>>
>>>> and
>>>>
>>>> @Component
>>>> @Named("default/reference")
>>>> public class DefaultReferenceDocumentReferenceResolver implements
>>>> DocumentReferenceResolver<EntityReference>
>>>>
>>>> and injected by
>>>>
>>>> @Inject
>>>> DocumentReferenceResolver<String> resolver;
>>>>
>>>> and
>>>>
>>>> @Inject
>>>> @Named("default/reference")
>>>> DocumentReferenceResolver<EntityReference> resolver;
>>>>
>>>> Having Type used as role means that we could have:
>>>>
>>>> @Inject
>>>> DocumentReferenceResolver<String> resolver;
>>>>
>>>> and
>>>>
>>>> @Inject
>>>> DocumentReferenceResolver<EntityReference> resolver;
>>>>
>>>> = What it breaks
>>>>
>>>> So what's the catch ?
>>>>
>>>> Basically it would break any code that currently programmatically
>>>> register or unregister Provider since It would remove the current hack
>>>> to discover the Provider parameter (assuming that the
>>>> ComponentDescriptor now provide the complete role). But that's OK IMO
>>>> given that Provider support is very recent and I doubt it's a common
>>>> use case.
>>>>
>>>> We would obviously keep and deprecate all the existing APIs based on
>>>> Class which are pretty easy to implement since Class extends Type.
>>>> Even if removing them would not cause any issue when you build it's
>>>> not binary compatible since it's not the same method signature.
>>>>
>>>> So WDYT ?
>>>>
>>>> Here is my +1 and since we are starting a new major version it sounds
>>>> a good occasion so introduce such change.
>>>>
>>>> --
>>>> Thomas Mortagne
>>>
>>>
>>>
>>> --
>>> Thomas Mortagne
>>
>>
>>
>
> _______________________________________________
> devs mailing list
> [email protected]
> http://lists.xwiki.org/mailman/listinfo/devs



-- 
Thomas Mortagne
_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs

Reply via email to