Package org.apache.solr.client.solrj.beans

Source Code of org.apache.solr.client.solrj.beans.DocumentObjectBinder

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.client.solrj.beans;

import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* A class to map objects to and from solr documents.
*
* @version $Id: DocumentObjectBinder.java 693132 2008-09-08 15:22:18Z koji $
* @since solr 1.3
*/
public class DocumentObjectBinder {
  private final Map<Class, List<DocField>> infocache = new ConcurrentHashMap<Class, List<DocField>>();

  public DocumentObjectBinder() {
  }

  public <T> List<T> getBeans(Class<T> clazz, SolrDocumentList solrDocList) {
    List<DocField> fields = getDocFields( clazz );
    List<T> result = new ArrayList<T>(solrDocList.size());

    for(int j=0;j<solrDocList.size();j++) {
      SolrDocument sdoc = solrDocList.get(j);

      T obj = null;
      try {
        obj = clazz.newInstance();
        result.add(obj);
      } catch (Exception e) {
        throw new RuntimeException("Could not instantiate object of " + clazz,e);
      }
      for (int i = 0; i < fields.size(); i++) {
        DocField docField = fields.get(i);
        docField.inject(obj, sdoc);
      }
    }
    return result;
  }
 
  public SolrInputDocument toSolrInputDocument( Object obj )
  {
    List<DocField> fields = getDocFields( obj.getClass() );
    if( fields.isEmpty() ) {
      throw new RuntimeException( "class: "+obj.getClass()+" does not define any fields." );
    }
   
    SolrInputDocument doc = new SolrInputDocument();
    for( DocField field : fields ) {
      doc.setField( field.name, field.get( obj ), 1.0f );
    }
    return doc;
  }
 
  private List<DocField> getDocFields( Class clazz )
  {
    List<DocField> fields = infocache.get(clazz);
    if (fields == null) {
      synchronized(infocache) {
        infocache.put(clazz, fields = collectInfo(clazz));
      }
    }
    return fields;
  }

  private List<DocField> collectInfo(Class clazz) {
    List<DocField> fields = new ArrayList<DocField>();
    Class superClazz = clazz;
    ArrayList<AccessibleObject> members = new ArrayList<AccessibleObject>();
    while (superClazz != null && superClazz != Object.class) {
      members.addAll(Arrays.asList(superClazz.getDeclaredFields()));
      members.addAll(Arrays.asList(superClazz.getDeclaredMethods()));
      superClazz = superClazz.getSuperclass();
    }
    for (AccessibleObject member : members) {
      if (member.isAnnotationPresent(Field.class)) {
        member.setAccessible(true);
        fields.add(new DocField(member));
      }
    }
    return fields;
  }

  private static class DocField {
    private String name;
    private java.lang.reflect.Field field;
    private Method setter;
    private Method getter;
    private Class type;
    private boolean isArray = false, isList=false;

    public DocField(AccessibleObject member) {
      if (member instanceof java.lang.reflect.Field) {
        field = (java.lang.reflect.Field) member;
      } else {
        setter = (Method) member;
      }
      Field annotation = member.getAnnotation(Field.class);
      storeName(annotation);
      storeType();
     
      // Look for a matching getter
      if( setter != null ) {
        String gname = setter.getName();
        if( gname.startsWith("set") ) {
          gname = "get" + gname.substring(3);
          try {
            getter = setter.getDeclaringClass().getMethod( gname, (Class[])null );
          }
          catch( Exception ex ) {
            // no getter -- don't worry about it...
            if( type == Boolean.class ) {
              gname = "is" + setter.getName().substring( 3 );
              try {
                getter = setter.getDeclaringClass().getMethod( gname, (Class[])null );
              }
              catch( Exception ex2 ) {
                // no getter -- don't worry about it...
              }
            }
          }
        }
      }
    }

    private void storeName(Field annotation) {
      if (annotation.value().equals(Field.DEFAULT)) {
        if (field != null) {
          name = field.getName();
        } else {
          String setterName = setter.getName();
          if (setterName.startsWith("set") && setterName.length() > 3) {
            name = setterName.substring(3, 4).toLowerCase() + setterName.substring(4);
          } else {
            name = setter.getName();
          }
        }
      } else {
        name = annotation.value();
      }
    }

    private void storeType() {
      if (field != null) {
        type = field.getType();
      } else {
        Class[] params = setter.getParameterTypes();
        if (params.length != 1)
          throw new RuntimeException("Invalid setter method. Must have one and only one parameter");
        type = params[0];
      }
      if(type == Collection.class || type == List.class || type == ArrayList.class) {
        type = Object.class;
        isList = true;
        /*ParameterizedType parameterizedType = null;
        if(field !=null){
          if( field.getGenericType() instanceof ParameterizedType){
            parameterizedType = (ParameterizedType) field.getGenericType();
            Type[] types = parameterizedType.getActualTypeArguments();
            if (types != null && types.length > 0) type = (Class) types[0];
          }
        }*/
      } else if (type.isArray()) {
        isArray = true;
        type = type.getComponentType();
      }
    }

    public <T> void inject(T obj, SolrDocument sdoc) {
      Object val = sdoc.getFieldValue(name);
      if(val == null) return;
      if (isArray) {
        if (val instanceof List) {
          List collection = (List) val;
          set(obj, collection.toArray((Object[]) Array.newInstance(type,collection.size())));
        } else {
          Object[] arr = (Object[]) Array.newInstance(type, 1);
          arr[0] = val;
          set(obj, arr);
        }
      } else if (isList) {
        if (val instanceof List) {
          set(obj, val);
        } else {
          ArrayList l = new ArrayList();
          l.add(val);
          set(obj, l);
        }
      } else {
        if (val instanceof List) {
          List l = (List) val;
          if(l.size()>0)
            set(obj, l.get(0));
        }
        else {
          set(obj,val) ;
        }
      }
    }
   
    private void set(Object obj, Object v) {
      try {
        if (field != null) {
          field.set(obj, v);
        } else if (setter != null) {
          setter.invoke(obj, v);
        }
      }
      catch (Exception e) {
        throw new RuntimeException("Exception while setting value : "+v+" on " + (field != null ? field : setter), e);
      }
    }
   
    public Object get( final Object obj )
    {
      if (field != null) {
        try {
          return field.get(obj);
        }
        catch (Exception e) {       
          throw new RuntimeException("Exception while getting value: " + field, e);
        }
      }
      else if (getter == null) {
        throw new RuntimeException( "Missing getter for field: "+name+" -- You can only call the 'get' for fields that have a field of 'get' method" );
      }
     
      try {
        return getter.invoke( obj, (Object[])null );
      }
      catch (Exception e) {       
        throw new RuntimeException("Exception while getting value: " + getter, e);
      }
    }
  }
}
TOP

Related Classes of org.apache.solr.client.solrj.beans.DocumentObjectBinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.