org.nextframework.persistence.PersistenceUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.nextframework.persistence.PersistenceUtils.java

Source

package org.nextframework.persistence;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.SessionFactory;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.collection.AbstractCollectionPersister;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.Type;
import org.nextframework.service.ServiceException;
import org.nextframework.service.ServiceFactory;

public class PersistenceUtils {

    private static final char PROPERTY_SEPARATOR = '.';

    static HibernateSessionProvider getSessionProvider() {
        return getSessionProvider(PersistenceConfiguration.DEFAULT_CONFIG);
    }

    static HibernateSessionProvider getSessionProvider(String persistenceContext) {
        PersistenceConfiguration config = PersistenceConfiguration.getConfig(persistenceContext);
        if (config == null) {
            throw new NullPointerException(
                    "Cannot find PersistenceConfiguration for context " + persistenceContext);
        }
        HibernateSessionProvider configSessionProvider = config.getSessionProvider();
        return configSessionProvider != null ? configSessionProvider : createSessionProviderUsingServiceFactory();
    }

    //TODO CONFIGURE TRANSACTION, SEARCH FOR FACTORY
    static HibernateSessionProvider createSessionProviderUsingServiceFactory() {
        try {
            return ServiceFactory.getService(HibernateSessionProvider.class);
        } catch (NoClassDefFoundError e) {
            throw new QueryBuilderException(
                    "No HibernateSessionProvider available. Try using PersistenceConfiguration.getConfig().setSessionProvider(...) OR "
                            + "include nextframework-core jar and configure a ServiceFactory.",
                    e);
        } catch (RuntimeException e) {
            try {
                if (e instanceof ServiceException) { //as this exception is not a required dependency it could not exist in the first catch clause
                    throw new QueryBuilderException(
                            "No HibernateSessionProvider available. Try using PersistenceConfiguration.getConfig().setSessionProvider(...) OR "
                                    + "register the HibernateSessionProvider as a service.",
                            e);
                }
            } catch (NoClassDefFoundError e2) {
            }
            throw e;
        }
    }

    public static String removeAccents(String string) {
        String source = "";
        String target = "AEIOUAEIOUAEIOUAEIOUAOCaeiouaeiouaeiouaeiouaoc";
        return translate(string, source, target);
    }

    /*
     * Copied from CharSetUtils (commons lang) under Apache License http://www.apache.org/licenses/LICENSE-2.0
     */
    static String translate(String str, String searchChars, String replaceChars) {
        if (str == null || str.length() == 0) {
            return str;
        }
        StringBuffer buffer = new StringBuffer(str.length());
        char[] chrs = str.toCharArray();
        char[] withChrs = replaceChars.toCharArray();
        int sz = chrs.length;
        int withMax = replaceChars.length() - 1;
        for (int i = 0; i < sz; i++) {
            int idx = searchChars.indexOf(chrs[i]);
            if (idx != -1) {
                if (idx > withMax) {
                    idx = withMax;
                }
                buffer.append(withChrs[idx]);
            } else {
                buffer.append(chrs[i]);
            }
        }
        return buffer.toString();
    }

    public static String getIdPropertyName(Class<?> fromClass, SessionFactory sessionFactory) {
        return getClassMetadata(fromClass, sessionFactory).getIdentifierPropertyName();
    }

    @SuppressWarnings("deprecation")
    public static Serializable getId(Object entity, SessionFactory sessionFactory) {
        return getClassMetadata(entity.getClass(), sessionFactory).getIdentifier(entity);
    }

    private static ClassMetadata getClassMetadata(Class<? extends Object> class1, SessionFactory sessionFactory) {
        if (class1.getSimpleName().contains("$$")) {
            //this is a generated class.. get the user class
            class1 = class1.getSuperclass();
        }
        return sessionFactory.getClassMetadata(class1);
    }

    public static Object getProperty(Object object, String property) {
        PropertyDescriptor propertyDescriptor = getPropertyDescriptor(object, property);
        try {
            return propertyDescriptor.getReadMethod().invoke(object);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e.getTargetException());
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error setting reading " + property + " of " + object, e);
        }
    }

    public static void setProperty(Object object, String property, Object value) {
        int indexOfSubPath = property.indexOf(PROPERTY_SEPARATOR);
        if (indexOfSubPath > 0) {//we have a subproperty here
            String base = property.substring(0, indexOfSubPath);
            String token = property.substring(indexOfSubPath + 1);
            PropertyDescriptor basePropertyDescriptor = getPropertyDescriptor(object, base);
            Method readMethod = basePropertyDescriptor.getReadMethod();
            if (readMethod == null) {
                throw new IllegalArgumentException(
                        "Property " + base + " of path " + property + " of object " + object + " is not readable");
            }
            Object baseValue;
            try {
                baseValue = readMethod.invoke(object);
            } catch (Exception e) {
                throw new IllegalArgumentException(
                        "Error reading " + base + " of path " + property + " of object " + object, e);
            }
            if (baseValue == null) {
                Class<?> baseType = readMethod.getReturnType();
                try {
                    baseValue = baseType.newInstance();
                } catch (Exception e) {
                    throw new IllegalArgumentException("Error instanciating " + baseType + " for " + base
                            + " of path " + property + " of object " + object, e);
                }
                setProperty(object, base, baseValue);
            }
            //configure deeper object
            object = baseValue;
            property = token;
        }
        PropertyDescriptor propertyDescriptor = getPropertyDescriptor(object, property);
        try {
            if (value instanceof Collection) {
                Class<?> propertyType = propertyDescriptor.getWriteMethod().getParameterTypes()[0];
                if (!propertyType.isAssignableFrom(value.getClass())) {
                    if (propertyType.isAssignableFrom(Set.class)) {
                        value = new LinkedHashSet<Object>((Collection<?>) value);
                    } else if (propertyType.isAssignableFrom(List.class)) {
                        value = new ArrayList<Object>((Collection<?>) value);
                    }
                }
            }
            propertyDescriptor.getWriteMethod().invoke(object, value);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e.getTargetException());
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error setting property " + property + " of " + object, e);
        }
    }

    public static PropertyDescriptor getPropertyDescriptor(Object object, String property) {
        if (object == null) {
            throw new IllegalArgumentException("Object cannot be null");
        }
        Class<? extends Object> clazz = object.getClass();
        return getPropertyDescriptor(clazz, property);
    }

    public static PropertyDescriptor getPropertyDescriptor(Class<? extends Object> clazz, String property) {
        PropertyDescriptor propertyDescriptor = null;
        if (clazz == null) {
            throw new IllegalArgumentException("Class cannot be null");
        }
        try {
            for (PropertyDescriptor pd : Introspector.getBeanInfo(clazz).getPropertyDescriptors()) {
                if (pd.getName().equals(property)) {
                    propertyDescriptor = pd;
                    break;
                }
            }
        } catch (IntrospectionException e) {
            throw new IllegalArgumentException("Cannot get property " + property + " of " + clazz, e);
        }
        if (propertyDescriptor == null) {
            throw new IllegalArgumentException("Invalid property " + property + " of " + clazz);
        }
        return propertyDescriptor;
    }

    static Class<?> getPropertyType(Object object, String property) {
        return getPropertyDescriptor(object.getClass(), property).getReadMethod().getReturnType();
    }

    public static class InverseCollectionProperties {
        public Class<?> type;
        public String property;
    }

    public static Class<?> getPropertyAssociationType(SessionFactory sessionFactory, Class<?> clazz,
            String property) {
        Class<?> result = null;
        ClassMetadata classMetadata = getClassMetadata(clazz, sessionFactory);
        if (classMetadata == null) {
            throw new PersistenceException("Class " + clazz.getName() + " is not mapped. ");
        }
        org.hibernate.type.Type propertyType = classMetadata.getPropertyType(property);
        if (propertyType instanceof AssociationType) {
            AssociationType associationType = (AssociationType) propertyType;
            String associatedEntityName = associationType
                    .getAssociatedEntityName((SessionFactoryImplementor) sessionFactory);
            AbstractEntityPersister abstractEntityPersister = (AbstractEntityPersister) sessionFactory
                    .getClassMetadata(associatedEntityName);
            result = abstractEntityPersister.getEntityType().getReturnedClass();
        } else {
            throw new PersistenceException("Property \"" + property + "\" of " + clazz
                    + " is not an association type (i.e. ManyToOne, OneToMany, AnyType, etc)");
        }
        return result;
    }

    public static InverseCollectionProperties getInverseCollectionProperty(SessionFactory sessionFactory,
            Class<? extends Object> clazz, String collectionProperty) {
        SessionFactoryImplementor sessionFactoryImplementor;
        String[] keyColumnNames;
        Class<?> returnedClass;
        try {
            sessionFactoryImplementor = (SessionFactoryImplementor) sessionFactory;
            ClassMetadata classMetadata = getClassMetadata(clazz, sessionFactory);
            if (classMetadata == null) {
                throw new PersistenceException("Class " + clazz.getName() + " is not mapped. ");
            }
            CollectionType ct = (CollectionType) classMetadata.getPropertyType(collectionProperty);
            AbstractCollectionPersister collectionMetadata = (AbstractCollectionPersister) sessionFactoryImplementor
                    .getCollectionMetadata(ct.getRole());
            keyColumnNames = ((AbstractCollectionPersister) collectionMetadata).getKeyColumnNames();
            returnedClass = ct.getElementType(sessionFactoryImplementor).getReturnedClass();
        } catch (ClassCastException e) {
            throw new PersistenceException(
                    "Property \"" + collectionProperty + "\" of " + clazz + " is not a mapped as a collection.");
        }

        AbstractEntityPersister collectionItemMetadata = (AbstractEntityPersister) sessionFactoryImplementor
                .getClassMetadata(returnedClass);
        Type[] propertyTypes = collectionItemMetadata.getPropertyTypes();
        String[] propertyNames = collectionItemMetadata.getPropertyNames();
        for (int i = 0; i < propertyTypes.length; i++) {
            Type type = propertyTypes[i];
            String propertyName = propertyNames[i];
            String[] propertyColumnNames = collectionItemMetadata.getPropertyColumnNames(propertyName);
            InverseCollectionProperties inverseCollectionProperties = getInverseCollectionProperties(
                    sessionFactoryImplementor, clazz, returnedClass, keyColumnNames, propertyColumnNames, type,
                    propertyName);
            if (inverseCollectionProperties != null) {
                return inverseCollectionProperties;
            }
        }
        //check id
        Type identifierType = collectionItemMetadata.getIdentifierType();
        String identifierName = collectionItemMetadata.getIdentifierPropertyName();
        String[] identifierColumnNames = collectionItemMetadata.getIdentifierColumnNames();
        InverseCollectionProperties inverseCollectionProperties = getInverseCollectionProperties(
                sessionFactoryImplementor, clazz, returnedClass, keyColumnNames, identifierColumnNames,
                identifierType, identifierName);
        if (inverseCollectionProperties != null) {
            return inverseCollectionProperties;
        }
        throw new PersistenceException(
                "Collection " + collectionProperty + " of " + clazz + " does not have an inverse path!");
    }

    @SuppressWarnings("unchecked")
    private static InverseCollectionProperties getInverseCollectionProperties(
            SessionFactoryImplementor sessionFactoryImplementor, Class<? extends Object> clazz,
            Class<?> returnedClass, String[] keyColumnNames, String[] propertyColumnNames, Type propertyType,
            String propertyName) {
        if (propertyType instanceof ManyToOneType) {
            ManyToOneType mtot = (ManyToOneType) propertyType;
            if (mtot.getReturnedClass().isAssignableFrom(clazz)) {
                //if propertyColumnNames == keyColumnNames
                if (Arrays.deepEquals(propertyColumnNames, keyColumnNames)) {
                    InverseCollectionProperties inverseCollectionProperties = new InverseCollectionProperties();
                    inverseCollectionProperties.property = propertyName;
                    inverseCollectionProperties.type = returnedClass;
                    return inverseCollectionProperties;
                }
            }
        }
        if (propertyType instanceof ComponentType) {
            ComponentType ct = (ComponentType) propertyType;
            String[] propertyNames = ct.getPropertyNames();
            Type[] propertyTypes = ct.getSubtypes();
            int beginIndex = 0;
            for (int i = 0; i < propertyTypes.length; i++) {
                Type subType = propertyTypes[i];
                String subPropertyName = propertyNames[i];
                int columnSpan = subType.getColumnSpan(sessionFactoryImplementor);
                String[] propertyColumnNamesMapping = new String[columnSpan];
                System.arraycopy(propertyColumnNames, beginIndex, propertyColumnNamesMapping, 0, columnSpan);
                InverseCollectionProperties inverseCollectionProperties = getInverseCollectionProperties(
                        sessionFactoryImplementor, clazz, returnedClass, keyColumnNames, propertyColumnNamesMapping,
                        subType, subPropertyName);
                if (inverseCollectionProperties != null) {
                    inverseCollectionProperties.property = propertyName + "."
                            + inverseCollectionProperties.property;
                    return inverseCollectionProperties;
                }
                beginIndex += columnSpan;
            }
        }
        return null;
    }

    /**
     * Removes from the src all elements present in toRemove collection
     * @param list
     * @param itens
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static List removeFromCollectionUsingId(SessionFactory sessionFactory, Collection src,
            Collection toRemove) {
        List<Object> result = new ArrayList<Object>();
        for (Object object : src) {
            if (!contains(sessionFactory, toRemove, object)) {
                result.add(object);
            }
        }
        return result;
    }

    @SuppressWarnings("rawtypes")
    private static boolean contains(SessionFactory sessionFactory, Collection collection, Object object) {
        Serializable id2 = getId(object, sessionFactory);
        for (Object item : collection) {
            Serializable id1 = getId(item, sessionFactory);
            if (id1.equals(id2)) {
                return true;
            }
        }
        return false;
    }

}