All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dongliu.dbutils.mapping.BeanMapping Maven / Gradle / Ivy

There is a newer version: 6.0.2
Show newest version
package net.dongliu.dbutils.mapping;

import net.dongliu.dbutils.exception.ReflectionException;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Bean mapping info
 *
 * @author Liu Dong
 */
public class BeanMapping {
    private final Map propertyMap;

    private BeanMapping(Map propertyMap) {
        this.propertyMap = propertyMap;
    }

    /**
     * Get column names this bean can mapping
     */
    public Collection columnNames() {
        return propertyMap.keySet();
    }

    /**
     * Get property by name, case insensitive
     */
    public Property getProperty(String name) {
        return propertyMap.get(name);
    }

    /**
     * Return all bean properties
     */
    public Collection Properties() {
        return propertyMap.values();
    }


    private static final WeakHashMap, BeanMapping> cache = new WeakHashMap<>();
    private static final ReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * Returns a PropertyDescriptor[] for the given Class.
     *
     * @param cls The Class to retrieve PropertyDescriptors for.
     * @return A PropertyDescriptor[] describing the Class.
     */
    public static BeanMapping getBeanMapping(Class cls) {
        lock.readLock().lock();
        try {
            BeanMapping beanMapping = cache.get(cls);
            if (beanMapping != null) {
                return beanMapping;
            }
        } finally {
            lock.readLock().unlock();
        }

        lock.writeLock().lock();
        try {
            BeanMapping beanMapping = cache.get(cls);
            if (beanMapping != null) {
                return beanMapping;
            }
            beanMapping = _getBeanMapping(cls);
            cache.put(cls, beanMapping);
            return beanMapping;
        } finally {
            lock.writeLock().unlock();
        }

    }

    private static BeanMapping _getBeanMapping(Class cls) {
        // process bean properties
        Map propertyMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        PropertyDescriptor[] descriptors;
        try {
            descriptors = Introspector.getBeanInfo(cls).getPropertyDescriptors();
        } catch (IntrospectionException e) {
            throw new ReflectionException(e);
        }
        for (PropertyDescriptor descriptor : descriptors) {
            Method writeMethod = descriptor.getWriteMethod();
            Method readMethod = descriptor.getReadMethod();
            // A Illegal property to mapping to sql result set, should have both getter and setter
            // getClass was filtered by this
            if (writeMethod == null || readMethod == null) {
                continue;
            }

            Column column = getColumnAnnotation(cls, descriptor);
            String name;
            if (column != null) {
                name = column.value();
            } else {
                name = descriptor.getName();
            }
            propertyMap.put(name, new GetterSetterProperty(descriptor));
        }

        // process bean public fields
        for (Field field : cls.getFields()) {
            if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
                continue;
            }
            String name = field.getName();
            Column column = field.getDeclaredAnnotation(Column.class);
            if (column != null) {
                name = column.value();
            }
            if (propertyMap.containsKey(name)) {
                continue;
            }
            propertyMap.put(name, new FieldProperty(field));

        }

        return new BeanMapping(propertyMap);
    }

    private static Column getColumnAnnotation(Class cls, PropertyDescriptor descriptor) {
        // try to get backing field
        Column column = null;
        Field backingField = getBackingField(cls, descriptor);
        if (backingField != null) {
            column = backingField.getAnnotation(Column.class);
        }
        if (column == null) {
            column = descriptor.getReadMethod().getAnnotation(Column.class);
        }
        if (column == null) {
            column = descriptor.getWriteMethod().getAnnotation(Column.class);
        }
        return column;
    }

    private static Field getBackingField(Class cls, PropertyDescriptor descriptor) {
        String name = descriptor.getName();
        Field backingField;
        try {
            backingField = cls.getDeclaredField(name);
        } catch (NoSuchFieldException e) {
            Class type = descriptor.getPropertyType();
            if (type.equals(boolean.class) || type.equals(Boolean.class)) {
                try {
                    backingField = cls.getDeclaredField("is" + Character.toUpperCase(name.charAt(0)) + name.substring(1));
                } catch (NoSuchFieldException e1) {
                    backingField = null;
                }
            } else {
                backingField = null;
            }
        }
        return backingField;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy