[ 
https://issues.apache.org/jira/browse/SOLR-6645?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14181136#comment-14181136
 ] 

Fabio Piro edited comment on SOLR-6645 at 10/23/14 8:45 AM:
------------------------------------------------------------

Sure [~erickerickson]! Here we go, PATCH added.


was (Author: dewos):
Sure [~erickerickson]! Here we go, PATH added.

> Refactored DocumentObjectBinder and added AnnotationListeners
> -------------------------------------------------------------
>
>                 Key: SOLR-6645
>                 URL: https://issues.apache.org/jira/browse/SOLR-6645
>             Project: Solr
>          Issue Type: New Feature
>          Components: clients - java
>            Reporter: Fabio Piro
>              Labels: annotations, binder, listener, solrj
>         Attachments: SOLR-6645.patch
>
>
> Hello good people.
> It is understandable that the priority of SolrJ is to provide a stable API 
> for java and not a rich-feature client, I'm well aware of that. On the other 
> hand more features nowadays mean most of the time Spring Solr Data. Although 
> I appreciate the enrichment work of that lib, sometimes depending on its 
> monolithic dependencies and magic is not a valid option.
> So, I was thinking that the official DocumentObjectBinder could benefit from 
> some love, and I had implemented a listener pattern for the annotations. 
> You can register your annotations and they relate listeners in the binder, 
> and it will invoke the corresponding method in the listener on getBean and on 
> toSolrInputDocument, therefore granting the chance to do something during the 
> ongoing process.
> Changes are:
> * [MOD] */beans/DocumentObjectBinder*:  The new logic and a new constructor 
> for registering the annotations
> * [ADD] */impl/AccessorAnnotationListener*: Abstract utility class with the 
> former get(), set(), isArray, isList, isContainedInMap etc...
> * [ADD] */impl/FieldAnnotationListener*: all the rest of DocField for dealing 
> with @Field
> * [ADD] */AnnotationListener*: the base listener class
> * [MOD] */SolrServer*: added setBinder (this is the only tricky change, I 
> hope it's not a problem).
> It's all well documented and the code is very easy to read. Tests are all 
> green, it should be 100% BC and the performance impact is void (the logic 
> flow is exactly the same as now, and I only changed the bare essentials and 
> nothing more, anyway).
> Some Examples (they are not part of the pull-request):
> The long awaited @FieldObject in 4 lines of code:
> https://issues.apache.org/jira/browse/SOLR-1945
> {code:java}
> public class FieldObjectAnnotationListener extends 
> AccessorAnnotationListener<FieldObject> {
>     public FieldObjectAnnotationListener(AnnotatedElement element, 
> FieldObject annotation) {
>         super(element, annotation);
>     }
>     @Override
>     public void onGetBean(Object obj, SolrDocument doc, DocumentObjectBinder 
> binder) {
>         Object nested = binder.getBean(target.clazz, doc);
>         setTo(obj, nested);
>     }
>     @Override
>     public void onToSolrInputDocument(Object obj, SolrInputDocument doc, 
> DocumentObjectBinder binder) {
>         SolrInputDocument nested = binder.toSolrInputDocument(getFrom(obj));
>         for (Map.Entry<String, SolrInputField> entry : nested.entrySet()) {
>             doc.addField(entry.getKey(), entry.getValue());
>         }
>     }
> }
> {code}
> Or something entirely new like an annotation for ChildDocuments:
> {code:java}
> public class ChildDocumentsAnnotationListener extends 
> AccessorAnnotationListener<ChildDocuments> {
>     public ChildDocumentsAnnotationListener(AnnotatedElement element, 
> ChildDocuments annotation) {
>         super(element, annotation);
>         if (!target.isInList || target.clazz.isPrimitive()) {
>             throw new BindingException("@NestedDocuments is applicable only 
> on List<Object>.");
>         }
>     }
>     @Override
>     public void onGetBean(Object obj, SolrDocument doc, DocumentObjectBinder 
> binder) {
>         List<Object> nested = new ArrayList<>();
>         for (SolrDocument child : doc.getChildDocuments()) {
>             nested.add(binder.getBean(target.clazz, child));// this should be 
> recursive, but it's only an example
>         }
>         setTo(obj, nested);
>     }
>     @Override
>     public void onToSolrInputDocument(Object obj, SolrInputDocument doc, 
> DocumentObjectBinder binder) {
>         SolrInputDocument nested = binder.toSolrInputDocument(getFrom(obj));
>         doc.addChildDocuments(nested.getChildDocuments());
>     }
> }
> {code}
> In addition, all the logic is encapsulated in the listener, so you can make a 
> custom FieldAnnotationListener too, and override the default one
> {code:java}
> public class CustomFieldAnnotationListener extends FieldAnnotationListener {
>     private boolean isTransentPresent;
>     public CustomFieldAnnotationListener(AnnotatedElement element, Field 
> annotation) {
>         super(element, annotation);
>         this.isTransentPresent = element.isAnnotationPresent(Transient.class);
>     }
>     @Override
>     public void onGetBean(Object obj, SolrDocument doc, DocumentObjectBinder 
> binder) {
>         if(!isTransentPresent){
>             super.onGetBean(obj, doc, binder);
>         }
>     }
>     @Override
>     public void onToSolrInputDocument(Object obj, SolrInputDocument doc, 
> DocumentObjectBinder binder) {
>         if(!isTransentPresent){
>             super.onToSolrInputDocument(obj, doc, binder);
>         }
>     }
> }
> {code}
> I think this is a good solution for a win-win scenario:
> - The code is almost unchanged (only shifted, wisely changed) so there is no 
> new code to test and to support for the devs.
> - People who only need the plain @Field will be untouched and unaware of the 
> change.
> - People who need some extra functionalities can now easily extend the @Field 
> logic, or make new annotations.
> - With some luck, a Community-Driven repository with the most useful features 
> can emerge.
> - [Bonus] The binder is now entirely documented and not so scarier like 
> before (we are almost at Halloween, but still... :) )
>  The code is production-ready and it's here: 
> https://github.com/dewos/lucene-solr/tree/trunk/solr/solrj/src/java/org/apache/solr/client/solrj
>  If you are interested in merging it to the core, we can discuss the last 
> touch (mainly what to leave protected and what to set private).



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@lucene.apache.org
For additional commands, e-mail: dev-h...@lucene.apache.org

Reply via email to