org.openmrs.module.auditlog.api.db.DAOUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.auditlog.api.db.DAOUtils.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.auditlog.api.db;

import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.hibernate.EntityMode;
import org.hibernate.SessionFactory;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.CollectionType;
import org.hibernate.type.OneToOneType;
import org.hibernate.type.Type;
import org.openmrs.api.context.Context;

public class DAOUtils {

    /**
     * Finds all the types for associations to audit in as recursive way i.e if a Persistent type is
     * found, then we also find its collection element types and types for fields mapped as one to
     * one.
     * 
     * @param clazz the Class to match against
     * @return a set of found class names
     */
    public static Set<Class<?>> getAssociationTypesToAudit(Class<?> clazz) {
        return getAssociationTypesToAuditInternal(clazz, null);
    }

    /**
     * Finds all the types for associations to audit in as recursive way i.e if a Persistent type is
     * found, then we also find its collection element types and types for fields mapped as one to
     * one.
     * 
     * @param clazz the Class to match against
     * @param foundAssocTypes the found association types
     * @return a set of found class names
     */
    private static Set<Class<?>> getAssociationTypesToAuditInternal(Class<?> clazz, Set<Class<?>> foundAssocTypes) {
        if (foundAssocTypes == null) {
            foundAssocTypes = new HashSet<Class<?>>();
        }

        ClassMetadata cmd = getSessionFactory().getClassMetadata(clazz);
        if (cmd != null) {
            for (Type type : cmd.getPropertyTypes()) {
                //If this is a OneToOne or a collection type
                if (type.isCollectionType() || OneToOneType.class.isAssignableFrom(type.getClass())) {
                    CollectionType collType = (CollectionType) type;
                    boolean isManyToManyColl = false;
                    if (collType.isCollectionType()) {
                        collType = (CollectionType) type;
                        isManyToManyColl = ((SessionFactoryImplementor) getSessionFactory())
                                .getCollectionPersister(collType.getRole()).isManyToMany();
                    }
                    Class<?> assocType = type.getReturnedClass();
                    if (type.isCollectionType()) {
                        assocType = collType.getElementType((SessionFactoryImplementor) getSessionFactory())
                                .getReturnedClass();
                    }

                    //Ignore non persistent types
                    if (getSessionFactory().getClassMetadata(assocType) == null) {
                        continue;
                    }

                    if (!foundAssocTypes.contains(assocType)) {
                        //Don't implicitly audit types for many to many collections items
                        if (!type.isCollectionType() || (type.isCollectionType() && !isManyToManyColl)) {
                            foundAssocTypes.add(assocType);
                            //Recursively inspect each association type
                            foundAssocTypes.addAll(getAssociationTypesToAuditInternal(assocType, foundAssocTypes));
                        }
                    }
                }
            }
        }
        return foundAssocTypes;
    }

    /**
     * Gets a set of concrete subclasses for the specified class recursively, note that interfaces
     * and abstract classes are excluded
     * 
     * @param clazz the Super Class
     * @return a set of subclasses
     * @should return a list of subclasses for the specified type
     * @should exclude interfaces and abstract classes
     */
    public static Set<Class<?>> getPersistentConcreteSubclasses(Class<?> clazz) {
        return getPersistentConcreteSubclassesInternal(clazz, null, null);
    }

    /**
     * Gets a set of concrete subclasses for the specified class recursively, note that interfaces
     * and abstract classes are excluded
     * 
     * @param clazz the Super Class
     * @param foundSubclasses the list of subclasses found in previous recursive calls, should be
     *            null for the first call
     * @param mappedClasses the ClassMetadata Collection
     * @return a set of subclasses
     */
    @SuppressWarnings("unchecked")
    private static Set<Class<?>> getPersistentConcreteSubclassesInternal(Class<?> clazz,
            Set<Class<?>> foundSubclasses, Collection<ClassMetadata> mappedClasses) {
        if (foundSubclasses == null) {
            foundSubclasses = new HashSet<Class<?>>();
        }
        if (mappedClasses == null) {
            mappedClasses = getSessionFactory().getAllClassMetadata().values();
        }

        if (clazz != null) {
            for (ClassMetadata cmd : mappedClasses) {
                Class<?> possibleSubclass = cmd.getMappedClass(EntityMode.POJO);
                if (!clazz.equals(possibleSubclass) && clazz.isAssignableFrom(possibleSubclass)) {
                    if (!Modifier.isAbstract(possibleSubclass.getModifiers()) && !possibleSubclass.isInterface()) {
                        foundSubclasses.add(possibleSubclass);
                    }
                    foundSubclasses.addAll(getPersistentConcreteSubclassesInternal(possibleSubclass,
                            foundSubclasses, mappedClasses));
                }
            }
        }

        return foundSubclasses;
    }

    public static ClassMetadata getClassMetadata(Class<?> clazz) {
        return getSessionFactory().getClassMetadata(clazz);
    }

    public static SessionFactory getSessionFactory() {
        return Context.getRegisteredComponents(SessionFactory.class).get(0);
    }
}