kr.debop4j.data.hibernate.tools.EntityTool.java Source code

Java tutorial

Introduction

Here is the source code for kr.debop4j.data.hibernate.tools.EntityTool.java

Source

/*
 * Copyright 2011-2013 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
 *
 *     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 kr.debop4j.data.hibernate.tools;

import com.google.common.collect.Sets;
import kr.debop4j.core.Function1;
import kr.debop4j.core.IDataObject;
import kr.debop4j.core.json.GsonSerializer;
import kr.debop4j.core.json.IJsonSerializer;
import kr.debop4j.core.parallelism.Parallels;
import kr.debop4j.core.tools.MapperTool;
import kr.debop4j.core.tools.StringTool;
import kr.debop4j.data.hibernate.HibernateParameter;
import kr.debop4j.data.hibernate.repository.IHibernateDao;
import kr.debop4j.data.hibernate.repository.impl.HibernateDao;
import kr.debop4j.data.model.*;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.LocaleType;
import org.hibernate.type.ObjectType;
import org.hibernate.type.StringType;

import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import static kr.debop4j.core.Guard.shouldNotBeNull;
import static kr.debop4j.core.Guard.shouldNotBeWhiteSpace;

/**
 * Hibernate     Utility Class .
 *
 * @author ? ( sunghyouk.bae@gmail.com )
 * @since 12. 9. 24
 */
@Slf4j
@SuppressWarnings("unchecked")
public class EntityTool {

    private EntityTool() {
    }

    /** The constant PROPERTY_ANCESTORS. */
    public static final String PROPERTY_ANCESTORS = "ancestors";
    /** The constant PROPERTY_DESCENDENTS. */
    public static final String PROPERTY_DESCENDENTS = "descendents";

    @Getter(lazy = true)
    private static final IJsonSerializer gsonSerializer = new GsonSerializer();

    /**
     * Entity to string.
     *
     * @param entity the entity
     * @return the string
     */
    public static String entityToString(IDataObject entity) {
        return (entity != null) ? StringTool.objectToString(entity) : StringTool.NULL_STR;
    }

    /**
     * As gson text.
     *
     * @param entity the entity
     * @return the string
     * @throws Exception the exception
     */
    public static String asGsonText(IDataObject entity) throws Exception {
        return getGsonSerializer().serializeToText(entity);
    }

    // region << Hierarchy >>

    /**
     * Assert not circular hierarchy.
     *
     * @param child  the child
     * @param parent the parent
     */
    public static <T extends IHierarchyEntity<T>> void assertNotCircularHierarchy(T child, T parent) {
        if (child == parent)
            throw new IllegalArgumentException("Child and Parent are same.");

        if (child.getDescendents().contains(parent))
            throw new IllegalArgumentException("child  parent ? ??  .");

        if (Sets.intersection(parent.getAncestors(), child.getDescendents()).size() > 0)
            throw new IllegalArgumentException(
                    "parent? ? child? ?? ? ?  ?.");
    }

    /**
     * Sets hierarchy.
     *
     * @param child     the child
     * @param oldParent the old parent
     * @param newParent the new parent
     */
    public static <T extends IHierarchyEntity<T>> void setHierarchy(T child, T oldParent, T newParent) {
        shouldNotBeNull(child, "child");

        log.trace(
                " ?  ,   ... child=[{}], oldParent=[{}], newParent=[{}]",
                child, oldParent, newParent);

        if (oldParent != null)
            removeHierarchy(child, oldParent);

        if (newParent != null)
            setHierarchy(child, newParent);
    }

    /**
     * Sets hierarchy.
     *
     * @param child  the child
     * @param parent the parent
     */
    public static <T extends IHierarchyEntity<T>> void setHierarchy(T child, T parent) {
        if (parent == null || child == null)
            return;

        log.trace("?  ? ?? . child=[{}], parent=[{}]", child, parent);

        parent.getDescendents().add(child);
        parent.getDescendents().addAll(child.getDescendents());

        for (T ancestor : parent.getAncestors()) {
            ancestor.getDescendents().add(child);
            ancestor.getDescendents().addAll(child.getDescendents());
        }

        child.getAncestors().add(parent);
        child.getAncestors().addAll(parent.getAncestors());
    }

    /**
     * Remove hierarchy.
     *
     * @param child  the child
     * @param parent the parent
     */
    public static <T extends IHierarchyEntity<T>> void removeHierarchy(T child, T parent) {
        if (parent == null)
            return;

        shouldNotBeNull(child, "child");

        log.trace("?  ? ?? . child=[{}], parent=[{}]", child, parent);

        child.getAncestors().remove(parent);
        child.getAncestors().removeAll(parent.getAncestors());

        for (T ancestor : parent.getAncestors()) {
            ancestor.getDescendents().remove(child);
            ancestor.getDescendents().removeAll(child.getDescendents());
        }
        for (T descendent : child.getDescendents()) {
            descendent.getAncestors().remove(parent);
            descendent.getAncestors().removeAll(parent.getAncestors());
        }
    }

    /**
     * Get ancestors criteria.
     *
     * @param entity      the entity
     * @param session     the session
     * @param entityClass the entity class
     * @return the detached criteria
     */
    public static <T extends IHierarchyEntity<T> & IEntity<TId>, TId extends Serializable> DetachedCriteria getAncestorsCriteria(
            T entity, Session session, Class<T> entityClass) {
        return DetachedCriteria.forClass(entityClass).createAlias(PROPERTY_DESCENDENTS, "des")
                .add(Restrictions.eq("des.id", entity.getId()));
    }

    /**
     * Get descendents criteria.
     *
     * @param entity      the entity
     * @param session     the session
     * @param entityClass the entity class
     * @return the detached criteria
     */
    public static <T extends IHierarchyEntity<T> & IEntity<TId>, TId extends Serializable> DetachedCriteria getDescendentsCriteria(
            T entity, Session session, Class<T> entityClass) {
        return DetachedCriteria.forClass(entityClass).createAlias(PROPERTY_ANCESTORS, "ans")
                .add(Restrictions.eq("ans.id", entity.getId()));
    }

    /**
     * Get ancestors id criteria.
     *
     * @param entity      the entity
     * @param session     the session
     * @param entityClass the entity class
     * @return the detached criteria
     */
    public static <T extends IHierarchyEntity<T> & IEntity<TId>, TId extends Serializable> DetachedCriteria getAncestorsIdCriteria(
            T entity, Session session, Class<T> entityClass) {
        return getAncestorsCriteria(entity, session, entityClass)
                .setProjection(Projections.distinct(Projections.id()));
    }

    /**
     * Get descendents id criteria.
     *
     * @param entity      the entity
     * @param session     the session
     * @param entityClass the entity class
     * @return the detached criteria
     */
    public static <T extends IHierarchyEntity<T> & IEntity<TId>, TId extends Serializable> DetachedCriteria getDescendentsIdCriteria(
            T entity, Session session, Class<T> entityClass) {
        return getDescendentsCriteria(entity, session, entityClass)
                .setProjection(Projections.distinct(Projections.id()));
    }

    // endregion

    // region << ILocaleEntity >>

    /**  ?     HQL . */
    public static final String GET_LIST_BY_LOCALE_KEY = "select distinct loen from %s loen where :key in indices (loen.localeMap)";

    /**  ? ??    HQL . */
    public static final String GET_LIST_BY_LOCALE_PROPERTY = "select distinct loen from %s loen join loen.localeMap locale where locale.%s = :%s";

    /**
     * Copy locale.
     *
     * @param source      the source
     * @param destination the destination
     */
    public static <T extends ILocaleEntity<TLocaleValue>, TLocaleValue extends ILocaleValue> void CopyLocale(
            T source, T destination) {
        for (Locale locale : source.getLocales())
            destination.addLocaleValue(locale, source.getLocaleValue(locale));
    }

    /**
     * Contains locale.
     *
     * @param entityClass the entity class
     * @param locale      the locale
     * @return the list
     */
    public static <T extends ILocaleEntity<TLocaleValue>, TLocaleValue extends ILocaleValue> List<T> containsLocale(
            Class<T> entityClass, Locale locale) {

        String hql = String.format(GET_LIST_BY_LOCALE_KEY, entityClass.getName());
        if (log.isDebugEnabled())
            log.debug("IEntity [{}] ? Locale[{}]    hql=[{}]", entityClass.getName(),
                    locale, hql);

        IHibernateDao dao = new HibernateDao();
        return dao.find(entityClass, hql, new HibernateParameter("key", locale, LocaleType.INSTANCE));

    }

    /**
     * Contains locale.
     *
     * @param entityClass  the entity class
     * @param propertyName the property name
     * @param value        the value
     * @param type         the type
     * @return the list
     */
    public static <T extends ILocaleEntity<TLocaleValue>, TLocaleValue extends ILocaleValue> List<T> containsLocale(
            final Class<T> entityClass, final String propertyName, final Object value,
            final org.hibernate.type.Type type) {

        final String hql = String.format(GET_LIST_BY_LOCALE_PROPERTY, entityClass.getName(), propertyName,
                propertyName);
        if (log.isDebugEnabled())
            log.debug(
                    "IEntity [{}] ? Locale ?[{}]? ? [{}] ?  . hql=[{}]",
                    entityClass.getName(), propertyName, value, hql);

        IHibernateDao dao = new HibernateDao();
        return dao.find(entityClass, hql, new HibernateParameter(propertyName, value, ObjectType.INSTANCE));
    }

    // endregion

    // region << IMetaEntity >>

    private static final String GET_LIST_BY_META_KEY = "select distinct me from %s me where :key in indices(me.metaMap)";
    public static final String GET_LIST_BY_META_VALUE = "select distinct me from %s me join me.metaMap meta where meta.value = :value";

    /**
     * Contains meta key.
     *
     * @param entityClass the entity class
     * @param key         the key
     * @return the list
     */
    public static <T extends IMetaEntity> List<T> containsMetaKey(Class<T> entityClass, String key) {
        shouldNotBeWhiteSpace(key, "key");

        String hql = String.format(GET_LIST_BY_META_KEY, entityClass.getName());

        if (log.isDebugEnabled())
            log.debug(" [{}]? ??  [{}]     hql=[{}]",
                    entityClass.getName(), key, hql);

        IHibernateDao dao = new HibernateDao();
        return dao.find(entityClass, hql, new HibernateParameter("key", key, StringType.INSTANCE));
    }

    /**
     * Contains meta value.
     *
     * @param entityClass the entity class
     * @param value       the value
     * @return the list
     */
    public static <T extends IMetaEntity> List<T> containsMetaValue(final Class<T> entityClass,
            final String value) {
        shouldNotBeWhiteSpace(value, "value");

        String hql = String.format(GET_LIST_BY_META_VALUE, entityClass.getName());
        if (log.isDebugEnabled())
            log.debug("?? value[{}]    hql=[{}]", value, hql);

        IHibernateDao dao = new HibernateDao();
        return dao.find(entityClass, hql, new HibernateParameter("value", value, StringType.INSTANCE));
    }

    // endregion

    // region << IEntity Mapper >>

    /**
     * ? ? ? ? ? ? .
     *
     * @param source the source
     * @param target the target
     * @return target entity
     */
    public static <S, T> T mapEntity(S source, T target) {
        MapperTool.map(source, target);
        return target;
    }

    /**
     * Map entity.
     *
     * @param source      the source
     * @param targetClass the target class
     * @return target entity
     */
    public static <S, T> T mapEntity(S source, Class<T> targetClass) {
        shouldNotBeNull(source, "source");
        return MapperTool.map(source, targetClass);
    }

    /**
     * ?  ?  ? . {@link kr.debop4j.core.tools.MapperTool} ? .
     *
     * @param sources the sources
     * @param targets the targets
     * @return the list
     */
    public static <S, T> List<T> mapEntities(List<S> sources, List<T> targets) {
        shouldNotBeNull(sources, "sources");
        shouldNotBeNull(targets, "targets");

        int size = Math.min(sources.size(), targets.size());

        for (int i = 0; i < size; i++) {
            MapperTool.map(sources.get(i), targets.get(i));
        }
        return targets;
    }

    /**
     *  ? ? ? .  ? DTO ?  .
     *
     * @param sources     the sources
     * @param targetClass the target class
     * @return the list
     */
    public static <S, T> List<T> mapEntitiesAsParallel(final List<S> sources, final Class<T> targetClass) {
        if (sources == null || sources.size() == 0)
            return new ArrayList<>();

        return Parallels.runEach(sources, new Function1<S, T>() {
            @Override
            public T execute(@Nullable S input) {
                return MapperTool.map(input, targetClass);
            }
        });
    }

    // endregion

    // region << TreeNode >>

    /**
     * Update tree node position.
     *
     * @param entity the entity
     */
    public static <T extends ITreeEntity<T>> void updateTreeNodePosition(T entity) {
        shouldNotBeNull(entity, "entity");

        log.trace("update tree node position... entity=[{}]", entity);

        TreeNodePosition nodePosition = entity.getNodePosition();

        if (entity.getParent() != null) {
            nodePosition.setLevel(entity.getParent().getNodePosition().getLevel() + 1);
            if (!entity.getParent().getChildren().contains(entity))
                nodePosition.setOrder(entity.getParent().getChildren().size());
        } else {
            nodePosition.setLevel(0);
            nodePosition.setOrder(0);
        }
    }

    /**
     *   ? ??  .
     *
     * @param entity the entity
     * @return the child count
     */
    public static <T extends ITreeEntity<T>> Long getChildCount(T entity) {

        log.trace("tree entity? ?? ?  . entity=[{}]", entity);

        DetachedCriteria dc = HibernateTool.createDetachedCriteria(entity.getClass());
        dc.add(Restrictions.eq("parent", entity));

        IHibernateDao dao = new HibernateDao();
        return dao.count(entity.getClass(), dc);
    }

    /**
     * Has children.
     *
     * @param entity the entity
     * @return the boolean
     */
    public static <T extends ITreeEntity<T>> Boolean hasChildren(T entity) {

        log.trace("tree entity  ???  . entity=[{}]", entity);

        DetachedCriteria dc = HibernateTool.createDetachedCriteria(entity.getClass());
        dc.add(Restrictions.eq("parent", entity));

        IHibernateDao dao = new HibernateDao();
        return dao.exists(entity.getClass(), dc);
    }

    // endregion
}