I really need someone who actually understands the AnnotationBinder and
commons-annotations stuff to look at this and help me find the plan for
applying attribute converters.
From what I can tell, PropertyHolder is the proper place to perform the
resolution of which converter to use because that allows for the
variance in how they resolution is handled in the
class/composite/collection cases. But PropertyHolder by itself does
not have all the info it needs, specifically access to the XProperty
objects. And my simple attempt to have PropertyBinder tell
PropertyHolder about the XProperty "works", but pretty sure it breaks
down in the composite path cases due to the ordering of the calls
(really need the inner most converts applied first).
As of now, 4.3 Beta4 is hung up on getting this sorted out.
On Wed 04 Sep 2013 11:43:19 PM CDT, Steve Ebersole wrote:
Stepping through the code showed me that PropertyHolder#addProperty
will not be useful here. Its called after the corresponding
SimpleValueBinder#setType call. Really not understanding how these are
intended to work.
I have some of the normalization working, hooked into PropertyHolder
constructors. But if this is the correct approach, I am not following
how to do a few things.
For example, in ClassPropertyHolder I have this:
https://gist.github.com/sebersole/6446095 Essentially it traverses
the super classes of the entity (depth first) and adds conversions it
finds. That part is fine. The trouble is outlined at the end of that
method in the comment. The situation is this:
@MappedSuperclass
public static class Super {
...
@Convert(converter = SillyStringConverter.class)
public String it;
}
@Entity(name = "Sub")
@Convert( attributeName = "it", disableConversion = true )
public static class Sub extends Super {
}
In building the "normalized" map of conversions for Sub, I really need
to be able to look at its attributes. But I am unsure how to do that
given just the XClass. There is the XClass#getDeclaredProperties, but
to use that I need to know about field/property access. I don't think
we know about field/property access at that point in ClassPropertyHolder.
Also, I am not sure that iterating properties yet again is a great idea.
One alternative I had considered was to hook this in with
PropertyBinder, where it calls SimpleValueBinder. That needs to
happen anyway; the plan was to delegate the call to determine the
Convert to use PropertyHolder and to pass that Convert into
SimpleValueBinder. That code would need to pass in the XProperty
anyway. So currently PropertyBinder does:
simpleValueBinder.setType( property, returnedClass, containerClassName );
My plan was to instead have it do:
simpleValueBinder.setType( property, returnedClass,
containerClassName, holder.resolveAttributeConverter( property ) );
I *think* that when resolveAttributeConverter() would be called, we'd
have enough info to fully resolve the converter to use properly.
There are similar concerns in ComponentPropertyHolder, but maybe a
discussion of the above will shed light on those concerns too.
On Wed 04 Sep 2013 02:44:40 PM CDT, Steve Ebersole wrote:
>
> I am still a bit confused on how to apply the normalization to make
> sure it happens in the proper order.
>
> Let's look at:
>
> @Entity
> class Person {
> ...
> @Embedded
> @Convert( attributeName="city", converter=Converter2.class )
> public Address homeAddress;
> }
>
> @Embeddable
> class Address {
> ...
> @Convert( converter=Converter1.class )
> public String city;
> }
>
>
> So here, the Converter2 class ought to be the one applied to
> "homeAddress.city" path.
>
> Now granted there are a few different ways to skin this cat, but the
> plan I had was to normalize these all on the root of the path. So
> here, both of these conversions would get stored on
> ClassPropertyHolder<Person> under the "homeAddress.city" path. When
I
> go to build the SimpleValue for Person.homeAddress.city, I'd ask the
> CompositePropertyHolder for Person.homeAddress to resolve the explicit
> (non-autoApply) conversion for its city attribute (the simple value).
> The trouble I have though is applying the conversions in the proper
> order. For example, here, I'd want to apply the conversions defined
> directly on the Embeddable first (the Embeddable conversions should
> always act as the baseline), then the conversions at its Embedded
> point (via XML or annotations).
>
> One idea was to hook into org.hibernate.cfg.PropertyHolder#addProperty
> in terms of normalizing the paths. I am just not sure of the timing
> between these PropertyHolder#addProperty (and how populated the passed
> Property objects are at that point) and the calls to
> SimpleValueBinder/PropertyBinder.
>
> Interestingly, I still am not sure we have enough here to report an
> error in cases like:
>
> @Entity
> @Convert( attributeName="homeAddress.city", converter=Converter3.class )
> class Person {
> ...
> @Embedded
> @Convert( attributeName="city", converter=Converter2.class )
> public Address homeAddress;
> }
>
> Unless we somehow kept "proximity info" or "location info" about
the
> conversion in PropertyHolder.
>
>
> On Wed 04 Sep 2013 01:27:21 AM CDT, Emmanuel Bernard wrote:
>>
>>
>> On Tue 2013-09-03 17:22, Steve Ebersole wrote:
>>>
>>>
>>> 2.a) It seems like there are times when
>>> org.hibernate.cfg.AbstractPropertyHolder#parent would be useful for
>>> what I need to do. But there appears to be times when this is null.
>>> For entity mappings (ClassPropertyHolder) thats fine. But for the
>>> others, that would be problematic. Going back to the
>>> Person#homeAddress example, I'd really need the
>>> ComponentPropertyHolder for Person#homeAddress to register the
>>> converts with ClassPropertyHolder<Person> under the
"homeAddress"
>>> base key ("homeAddress.city" for example). Is there a time here
>>> where AbstractPropertyHolder#parent would be null for
>>> ComponentPropertyHolder/CollectionPropertyHolder?
>>
>>
>>
>> I looked around the code base and the only case I could find is for
>> ClassPropertyHolder whose parent is indeed null.
>>
>>>
>>>
>>> 2.b) Is this AbstractPropertyHolder#parent the best way you see to
>>> handle path-based converts? Or do you see a better option?
>>>
>>
>>
>>
>> Yes I still think it's the best aproach and frankly I don't quite see
>> alternatives.