MetaClass.java
- /*
- * Copyright 2009-2023 the original author or authors.
- *
- * Licensed 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
- *
- * https://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.ibatis.reflection;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.util.Collection;
- import org.apache.ibatis.reflection.invoker.GetFieldInvoker;
- import org.apache.ibatis.reflection.invoker.Invoker;
- import org.apache.ibatis.reflection.invoker.MethodInvoker;
- import org.apache.ibatis.reflection.property.PropertyTokenizer;
- /**
- * @author Clinton Begin
- */
- public class MetaClass {
- private final ReflectorFactory reflectorFactory;
- private final Reflector reflector;
- private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
- this.reflectorFactory = reflectorFactory;
- this.reflector = reflectorFactory.findForClass(type);
- }
- public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
- return new MetaClass(type, reflectorFactory);
- }
- public MetaClass metaClassForProperty(String name) {
- Class<?> propType = reflector.getGetterType(name);
- return MetaClass.forClass(propType, reflectorFactory);
- }
- public String findProperty(String name) {
- StringBuilder prop = buildProperty(name, new StringBuilder());
- return prop.length() > 0 ? prop.toString() : null;
- }
- public String findProperty(String name, boolean useCamelCaseMapping) {
- if (useCamelCaseMapping) {
- name = name.replace("_", "");
- }
- return findProperty(name);
- }
- public String[] getGetterNames() {
- return reflector.getGetablePropertyNames();
- }
- public String[] getSetterNames() {
- return reflector.getSetablePropertyNames();
- }
- public Class<?> getSetterType(String name) {
- PropertyTokenizer prop = new PropertyTokenizer(name);
- if (prop.hasNext()) {
- MetaClass metaProp = metaClassForProperty(prop.getName());
- return metaProp.getSetterType(prop.getChildren());
- }
- return reflector.getSetterType(prop.getName());
- }
- public Class<?> getGetterType(String name) {
- PropertyTokenizer prop = new PropertyTokenizer(name);
- if (prop.hasNext()) {
- MetaClass metaProp = metaClassForProperty(prop);
- return metaProp.getGetterType(prop.getChildren());
- }
- // issue #506. Resolve the type inside a Collection Object
- return getGetterType(prop);
- }
- private MetaClass metaClassForProperty(PropertyTokenizer prop) {
- Class<?> propType = getGetterType(prop);
- return MetaClass.forClass(propType, reflectorFactory);
- }
- private Class<?> getGetterType(PropertyTokenizer prop) {
- Class<?> type = reflector.getGetterType(prop.getName());
- if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
- Type returnType = getGenericGetterType(prop.getName());
- if (returnType instanceof ParameterizedType) {
- Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
- if (actualTypeArguments != null && actualTypeArguments.length == 1) {
- returnType = actualTypeArguments[0];
- if (returnType instanceof Class) {
- type = (Class<?>) returnType;
- } else if (returnType instanceof ParameterizedType) {
- type = (Class<?>) ((ParameterizedType) returnType).getRawType();
- }
- }
- }
- }
- return type;
- }
- private Type getGenericGetterType(String propertyName) {
- try {
- Invoker invoker = reflector.getGetInvoker(propertyName);
- if (invoker instanceof MethodInvoker) {
- Field declaredMethod = MethodInvoker.class.getDeclaredField("method");
- declaredMethod.setAccessible(true);
- Method method = (Method) declaredMethod.get(invoker);
- return TypeParameterResolver.resolveReturnType(method, reflector.getType());
- }
- if (invoker instanceof GetFieldInvoker) {
- Field declaredField = GetFieldInvoker.class.getDeclaredField("field");
- declaredField.setAccessible(true);
- Field field = (Field) declaredField.get(invoker);
- return TypeParameterResolver.resolveFieldType(field, reflector.getType());
- }
- } catch (NoSuchFieldException | IllegalAccessException e) {
- // Ignored
- }
- return null;
- }
- public boolean hasSetter(String name) {
- PropertyTokenizer prop = new PropertyTokenizer(name);
- if (!prop.hasNext()) {
- return reflector.hasSetter(prop.getName());
- }
- if (reflector.hasSetter(prop.getName())) {
- MetaClass metaProp = metaClassForProperty(prop.getName());
- return metaProp.hasSetter(prop.getChildren());
- }
- return false;
- }
- public boolean hasGetter(String name) {
- PropertyTokenizer prop = new PropertyTokenizer(name);
- if (!prop.hasNext()) {
- return reflector.hasGetter(prop.getName());
- }
- if (reflector.hasGetter(prop.getName())) {
- MetaClass metaProp = metaClassForProperty(prop);
- return metaProp.hasGetter(prop.getChildren());
- }
- return false;
- }
- public Invoker getGetInvoker(String name) {
- return reflector.getGetInvoker(name);
- }
- public Invoker getSetInvoker(String name) {
- return reflector.getSetInvoker(name);
- }
- private StringBuilder buildProperty(String name, StringBuilder builder) {
- PropertyTokenizer prop = new PropertyTokenizer(name);
- if (prop.hasNext()) {
- String propertyName = reflector.findPropertyName(prop.getName());
- if (propertyName != null) {
- builder.append(propertyName);
- builder.append(".");
- MetaClass metaProp = metaClassForProperty(propertyName);
- metaProp.buildProperty(prop.getChildren(), builder);
- }
- } else {
- String propertyName = reflector.findPropertyName(name);
- if (propertyName != null) {
- builder.append(propertyName);
- }
- }
- return builder;
- }
- public boolean hasDefaultConstructor() {
- return reflector.hasDefaultConstructor();
- }
- }