BeanWrapper.java

  1. /*
  2.  *    Copyright 2009-2024 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       https://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.reflection.wrapper;

  17. import java.util.List;

  18. import org.apache.ibatis.reflection.ExceptionUtil;
  19. import org.apache.ibatis.reflection.MetaClass;
  20. import org.apache.ibatis.reflection.MetaObject;
  21. import org.apache.ibatis.reflection.ReflectionException;
  22. import org.apache.ibatis.reflection.SystemMetaObject;
  23. import org.apache.ibatis.reflection.factory.ObjectFactory;
  24. import org.apache.ibatis.reflection.invoker.Invoker;
  25. import org.apache.ibatis.reflection.property.PropertyTokenizer;

  26. /**
  27.  * @author Clinton Begin
  28.  */
  29. public class BeanWrapper extends BaseWrapper {

  30.   private final Object object;
  31.   private final MetaClass metaClass;

  32.   public BeanWrapper(MetaObject metaObject, Object object) {
  33.     super(metaObject);
  34.     this.object = object;
  35.     this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
  36.   }

  37.   @Override
  38.   public Object get(PropertyTokenizer prop) {
  39.     if (prop.hasNext()) {
  40.       return getChildValue(prop);
  41.     } else if (prop.getIndex() != null) {
  42.       return getCollectionValue(prop, resolveCollection(prop, object));
  43.     } else {
  44.       return getBeanProperty(prop, object);
  45.     }
  46.   }

  47.   @Override
  48.   public void set(PropertyTokenizer prop, Object value) {
  49.     if (prop.hasNext()) {
  50.       setChildValue(prop, value);
  51.     } else if (prop.getIndex() != null) {
  52.       setCollectionValue(prop, resolveCollection(prop, object), value);
  53.     } else {
  54.       setBeanProperty(prop, object, value);
  55.     }
  56.   }

  57.   @Override
  58.   public String findProperty(String name, boolean useCamelCaseMapping) {
  59.     return metaClass.findProperty(name, useCamelCaseMapping);
  60.   }

  61.   @Override
  62.   public String[] getGetterNames() {
  63.     return metaClass.getGetterNames();
  64.   }

  65.   @Override
  66.   public String[] getSetterNames() {
  67.     return metaClass.getSetterNames();
  68.   }

  69.   @Override
  70.   public Class<?> getSetterType(String name) {
  71.     PropertyTokenizer prop = new PropertyTokenizer(name);
  72.     if (!prop.hasNext()) {
  73.       return metaClass.getSetterType(name);
  74.     }
  75.     MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
  76.     if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
  77.       return metaClass.getSetterType(name);
  78.     }
  79.     return metaValue.getSetterType(prop.getChildren());
  80.   }

  81.   @Override
  82.   public Class<?> getGetterType(String name) {
  83.     PropertyTokenizer prop = new PropertyTokenizer(name);
  84.     if (!prop.hasNext()) {
  85.       return metaClass.getGetterType(name);
  86.     }
  87.     MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
  88.     if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
  89.       return metaClass.getGetterType(name);
  90.     }
  91.     return metaValue.getGetterType(prop.getChildren());
  92.   }

  93.   @Override
  94.   public boolean hasSetter(String name) {
  95.     PropertyTokenizer prop = new PropertyTokenizer(name);
  96.     if (!prop.hasNext()) {
  97.       return metaClass.hasSetter(name);
  98.     }
  99.     if (metaClass.hasSetter(prop.getIndexedName())) {
  100.       MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
  101.       if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
  102.         return metaClass.hasSetter(name);
  103.       }
  104.       return metaValue.hasSetter(prop.getChildren());
  105.     }
  106.     return false;
  107.   }

  108.   @Override
  109.   public boolean hasGetter(String name) {
  110.     PropertyTokenizer prop = new PropertyTokenizer(name);
  111.     if (!prop.hasNext()) {
  112.       return metaClass.hasGetter(name);
  113.     }
  114.     if (metaClass.hasGetter(prop.getIndexedName())) {
  115.       MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
  116.       if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
  117.         return metaClass.hasGetter(name);
  118.       }
  119.       return metaValue.hasGetter(prop.getChildren());
  120.     }
  121.     return false;
  122.   }

  123.   @Override
  124.   public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
  125.     MetaObject metaValue;
  126.     Class<?> type = getSetterType(prop.getName());
  127.     try {
  128.       Object newObject = objectFactory.create(type);
  129.       metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(),
  130.           metaObject.getReflectorFactory());
  131.       set(prop, newObject);
  132.     } catch (Exception e) {
  133.       throw new ReflectionException("Cannot set value of property '" + name + "' because '" + name
  134.           + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
  135.     }
  136.     return metaValue;
  137.   }

  138.   private Object getBeanProperty(PropertyTokenizer prop, Object object) {
  139.     try {
  140.       Invoker method = metaClass.getGetInvoker(prop.getName());
  141.       try {
  142.         return method.invoke(object, NO_ARGUMENTS);
  143.       } catch (Throwable t) {
  144.         throw ExceptionUtil.unwrapThrowable(t);
  145.       }
  146.     } catch (RuntimeException e) {
  147.       throw e;
  148.     } catch (Throwable t) {
  149.       throw new ReflectionException(
  150.           "Could not get property '" + prop.getName() + "' from " + object.getClass() + ".  Cause: " + t.toString(), t);
  151.     }
  152.   }

  153.   private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
  154.     try {
  155.       Invoker method = metaClass.getSetInvoker(prop.getName());
  156.       Object[] params = { value };
  157.       try {
  158.         method.invoke(object, params);
  159.       } catch (Throwable t) {
  160.         throw ExceptionUtil.unwrapThrowable(t);
  161.       }
  162.     } catch (Throwable t) {
  163.       throw new ReflectionException("Could not set property '" + prop.getName() + "' of '" + object.getClass()
  164.           + "' with value '" + value + "' Cause: " + t.toString(), t);
  165.     }
  166.   }

  167.   @Override
  168.   public boolean isCollection() {
  169.     return false;
  170.   }

  171.   @Override
  172.   public void add(Object element) {
  173.     throw new UnsupportedOperationException();
  174.   }

  175.   @Override
  176.   public <E> void addAll(List<E> list) {
  177.     throw new UnsupportedOperationException();
  178.   }

  179. }