Yes your analysis is correct.
I would clarify that 3 or 2c don’t have to apply on already supported return types, it is
more likely custom types like JodaTime types.
I do think 3 is the most valuable but that 2c is a relatively close second.
Now the @Spatial and @TikaBridge annotations do have attributes which will influence how
the underlying bridge is created.
I don’t think you are proposing to move the spatial and Tika bridge creation up on
AnnotationMetadataProvider. That would AFAIU duplicate the bridge creation logic between
the AMP and some ProgrammaticMetadataProvider.
Also I have a hard time navigating and understanding AnnotationMetadataProvider, so I’m
not sure we should make it more complex.
So somehow, the AMP should convert @Spatial, @NumericField, @TikaBridge, and @DateBridge
into some non annotation based representation and pass that information to the
bridgeFactory. Your approach would be to call explicitly buildXxxBridge() - like
buildDateBridge() - methods form AMP. These would be hosted on the BridgeFactory. Is that
correct? And the same explicit call logic would be done on a programmatic API equivalent.
Now how would you pass and to these kind of explicit calls in the 2c case when the
annotation is unknown a priori?
On 02 Apr 2014, at 13:23, Hardy Ferentschik <hardy(a)hibernate.org> wrote:
On 1 Jan 2014, at 22:07, Hardy Ferentschik <hardy(a)hibernate.org> wrote:
>
> On 1 Jan 2014, at 16:36, Emmanuel Bernard <emmanuel(a)hibernate.org> wrote:
>
>> ## Handling duplicates
>>
>> I had in mind the following logic.
>>
>> Prevent custom bridge providers to offer bridges in the same situation.
I am still trying to wrap my head around “same situation”. It might help to list the
different cases we have. Also the POC
for BridgeProvider has this method:
FieldBridge returnFieldBridgeIfMatching(Class<?> returnType, AnnotatedElement
bridgedElement, String memberName, ServiceManager serviceManager);
1) Explicit field bridge declaration
@Indexed
class Foo {
@Field(bridge=(a)FieldBridge(impl=MyCustomBridge.class)
String foo;
@Field
@FieldBridge(impl=MyOtherCustomBridge.class)
String snafu;
// ...
}
These is the simple case. BridgeProvider is not even involved, since the bridge is
explicitly specified
2) Bridge is indirectly specified via its context
2a) @TikaBridge
@Indexed
class Foo {
@Lob
@Basic(fetch = FetchType.LAZY)
@Field
@TikaBridge
Blob content;
//...
}
2b) @Spatial
@Indexed
class Bar {
@Spatial
public Coordinates getLocation() {
return new Coordinates() {
@Override
public Double getLatitude() {
return latitude;
}
@Override
public Double getLongitude() {
return longitude;
}
};
}
}
2c) Some custom annotation
@Indexed
class Foo {
@Field
String foo;
@Field
@Snafu
String snafu;
// …
}
A couple of considerations here. I guess 2a and 2b are the driving force behind passing
the AnnotatedElement into the BridgeProvider contract. The current implementations would
check whether
an annotation like @TikaBridge or @Spatal exist and behave accordingly. Part of the
problem is that in the case of programmatic configuration we now have to create a pseudo
annotated element
to make this contract work (see related discussion). This works fine with the current
commons-annotations approach, but the aim is really to let the programmatic configuration
populate the internal
metamodel directly instead of creating pseudo annotations.
The question for me atm, is why we go via the BridgeProvider at all for 2a and 2b? The
bridge might not be explicitly specified via a @Bridge annotation, but it is still a clear
case due to
@TikaBridge and @Spatial. Why can not the AnnotationMetadataProvider take care of this
and during the processing of the annotations of a property act accordingly. A programmatic
metadata provider
would also just act depending on whether spatial() was specified or not.
The problem maybe starts already at BridgeFactory#guessType which gets also passed
(numeric) field annotations as well as the processed member. guessType does then two
things, it processes the
annotations and if potentially queries the BridgeProviders. I think parts of the
responsibility should be moved into AnnotationMetadataProvider. BridgeFactory#guessType
should really only be called in
the case where the bridge is not explicitly or implicitly specified.
Which leaves 2c. The question is whether we think it is a valid use case to have a
BridgeProvider which returns a different bridge depending on some non Search related
annotation (@Snafu). If so,
we indeed need to pass the AnnotatedElement into the BridgeProvider.
3) No explicit or implicit bridge config
@Indexed
class Foo {
@Field
String snafu;
// …
}
I guess this is main use case for the BridgeProvider, right? In this case the bridge
really depends on the type of the indexed property (in the worst case also on some
additional custom annotation if
we support 2c).
Thoughts?
—Hardy