ubc.pavlab.aspiredb.server.util.CrudUtilsImpl.java Source code

Java tutorial

Introduction

Here is the source code for ubc.pavlab.aspiredb.server.util.CrudUtilsImpl.java

Source

/*
 * The aspiredb project
 * 
 * Copyright (c) 2012 University of British Columbia
 * 
 * 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
 * 
 * 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 ubc.pavlab.aspiredb.server.util;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.engine.CascadeStyle;
import org.hibernate.engine.CascadingAction;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Convenience methods needed to perform CRUD operations on entities.
 * 
 * @author pavlidis
 * @version $Id: CrudUtilsImpl.java,v 1.2 2013/06/11 22:30:47 anton Exp $
 */
@Component
public class CrudUtilsImpl implements InitializingBean, CrudUtils {

    static Log log = LogFactory.getLog(CrudUtilsImpl.class.getName());

    private static Set<String> crudMethods;

    static {
        crudMethods = new HashSet<String>();
        crudMethods.add("update");
        crudMethods.add("create");
        crudMethods.add("remove");
        crudMethods.add("save");
        crudMethods.add("find");
        crudMethods.add("findOrCreate");
        crudMethods.add("delete");
        crudMethods.add("load");
        crudMethods.add("loadAll");
        crudMethods.add("persist");
        crudMethods.add("persistOrUpdate");
    }

    /**
     * @param entity
     * @return
     */
    public static boolean isTransient(Object entity) {
        if (entity == null) {
            return true;
        }
        try {
            return org.apache.commons.beanutils.BeanUtils.getSimpleProperty(entity, "id") == null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Test whether a method creates objects
     * 
     * @param m
     * @return
     */
    public static boolean methodIsCreate(Method m) {
        return methodIsCreate(m.getName());
    }

    public static boolean methodIsCreate(String m) {
        return m.equals("create") || m.equals("save") || m.equals("findOrCreate") || m.equals("persist");
    }

    /**
     * Test whether a method is a CRUD method.
     * 
     * @param m
     * @return
     */
    public static boolean methodIsCrud(Method m) {
        if (log.isTraceEnabled()) {
            log.trace("Testing " + m.getName());
        }
        return crudMethods.contains(m.getName());
    }

    /**
     * Test whether a method deletes objects
     * 
     * @param m
     * @return
     */
    public static boolean methodIsDelete(Method m) {
        return methodIsDelete(m.getName());
    }

    public static boolean methodIsDelete(String s) {
        return s.equals("remove") || s.equals("delete");
    }

    /**
     * Test whether a method loads objects. Patterns accepted include "read", "find", "load*" (latter for load or
     * loadAll)
     * 
     * @param m
     * @return
     */
    public static boolean methodIsLoad(Method m) {
        return methodIsLoad(m.getName());
    }

    public static boolean methodIsLoad(String m) {
        return m.equals("read") || m.startsWith("find") || m.startsWith("load");
    }

    /**
     * Test whether a method updates objects
     * 
     * @param m
     * @return
     */
    public static boolean methodIsUpdate(Method m) {
        return methodIsUpdate(m.getName());
    }

    public static boolean methodIsUpdate(String s) {
        return s.equals("update") || s.equals("persistOrUpdate");
    }

    private Map<String, CollectionMetadata> collectionMetaData;

    private Map<String, ClassMetadata> metaData;

    @Autowired
    private SessionFactory sessionFactory;

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    @Override
    public void afterPropertiesSet() {
        metaData = sessionFactory.getAllClassMetadata();
        collectionMetaData = sessionFactory.getAllCollectionMetadata();
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.persistence.CrudUtils#getCollectionPersister(java.lang.String)
     */
    @Override
    public CollectionPersister getCollectionPersister(String role) {
        return (CollectionPersister) collectionMetaData.get(role);
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.persistence.CrudUtils#getEntityPersister(java.lang.Object)
     */
    @Override
    public EntityPersister getEntityPersister(Object object) {
        String className = object.getClass().getName();
        // hack to remove "$$EnhancerByCGLib... or _$$_javaassist_
        className = className.replaceAll("(_)?\\$\\$.+$", "");

        return ((EntityPersister) metaData.get(className));
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.persistence.CrudUtils#getSessionFactory()
     */
    @Override
    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.persistence.CrudUtils#needCascade(java.lang.String, org.hibernate.engine.CascadeStyle)
     */
    @Override
    public boolean needCascade(String m, CascadeStyle cs) {

        if (methodIsDelete(m)) {
            return cs.doCascade(CascadingAction.DELETE);
        }

        return needCascade(cs);
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.persistence.CrudUtils#setSessionFactory(org.hibernate.SessionFactory)
     */
    @Override
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.persistence.CrudUtils#willCascade(org.hibernate.engine.CascadeStyle)
     */
    @Override
    public boolean willCascade(CascadeStyle cs) {
        return cs == CascadeStyle.ALL || cs == CascadeStyle.ALL_DELETE_ORPHAN || cs == CascadeStyle.UPDATE;
    }

    /**
     * @param service The service where we look for the method
     * @param entity The type of entity to be created
     * @return
     */
    Method getCreateMethod(Object service, Object entity) {
        return getMethodForNames(service, entity, new String[] { "create", "save" });
    }

    /**
     * @param service The service where we look for the method
     * @param entity The type of entity to be deleted
     * @return
     */
    Method getDeleteMethod(Object service, Object entity) {
        return getMethodForNames(service, entity, new String[] { "delete", "remove" });
    }

    /**
     * @param service The service where we look for the method
     * @param entity The type of entity to be found
     * @return
     */
    Method getFindMethod(Object service, Object entity) {
        return getMethodForNames(service, entity, new String[] { "find" });
    }

    /**
     * @param service The service where we look for the method
     * @param entity The type of entity to be found or created
     * @return
     */
    Method getFindOrCreateMethod(Object service, Object entity) {
        return getMethodForNames(service, entity, new String[] { "findOrCreate" });
    }

    /**
     * @param target The object that might have the method (e.g., a service)
     * @param argument The single argument the method is expected to take. (e.g., an entity)
     * @param possibleNames An array of names of the methods (e.g., "create", "save").
     * @return
     */
    Method getMethodForNames(Object target, Object argument, String[] possibleNames) {
        String argInterfaceName = StringUtils.chomp(argument.getClass().getName(), "Impl");

        Class<?>[] argArray = null;
        try {
            Class<?> entityInterface = Class.forName(argInterfaceName);
            argArray = new Class[] { entityInterface };
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        for (String methodName : possibleNames) {
            try {
                return target.getClass().getMethod(methodName, argArray);
            } catch (Exception e1) {
                // okay keep trying
            }
        }
        log.warn(
                target.getClass().getSimpleName() + " does not have method with " + argInterfaceName + " argument");
        return null;
    }

    /**
     * @param service The service where we look for the method
     * @param entity The type of entity to be updated
     * @return
     */
    Method getUpdateMethod(Object service, Object entity) {
        return getMethodForNames(service, entity, new String[] { "update" });
    }

    /**
     * Determine if cascading an association is required.
     * 
     * @param cs
     * @return
     */
    private boolean needCascade(CascadeStyle cs) {
        return cs.doCascade(CascadingAction.PERSIST) || cs.doCascade(CascadingAction.SAVE_UPDATE)
                || cs.doCascade(CascadingAction.SAVE_UPDATE_COPY);
    }
}