com.qcadoo.model.internal.HibernateServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.qcadoo.model.internal.HibernateServiceImpl.java

Source

/**
 * ***************************************************************************
 * Copyright (c) 2010 Qcadoo Limited
 * Project: Qcadoo Framework
 * Version: 1.4
 *
 * This file is part of Qcadoo.
 *
 * Qcadoo is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation; either version 3 of the License,
 * or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * ***************************************************************************
 */
package com.qcadoo.model.internal;

import com.google.common.base.Preconditions;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.DataDefinitionService;
import com.qcadoo.model.api.types.FieldType;
import com.qcadoo.model.internal.api.HibernateService;
import com.qcadoo.model.internal.api.InternalDataDefinition;
import com.qcadoo.model.internal.types.BelongsToEntityType;
import com.qcadoo.model.internal.types.DateTimeType;
import com.qcadoo.model.internal.types.DecimalType;
import com.qcadoo.model.internal.types.StringType;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.criteria.CriteriaJoinWalker;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Locale;

@Service
public class HibernateServiceImpl implements HibernateService {

    private static final Logger LOG = LoggerFactory.getLogger(HibernateServiceImpl.class);

    @Autowired
    private DataDefinitionService dataDefinitionService;

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public int getTotalNumberOfEntities(final Criteria criteria) {
        final CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
        final SessionImplementor session = (SessionImplementor) getCurrentSession();
        SessionFactoryImplementor factory = session.getFactory();
        CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteriaImpl,
                criteriaImpl.getEntityOrClassName(), CriteriaQueryTranslator.ROOT_SQL_ALIAS);
        String[] implementors = factory.getImplementors(criteriaImpl.getEntityOrClassName());

        CriteriaJoinWalker walker = new CriteriaJoinWalker(
                (OuterJoinLoadable) factory.getEntityPersister(implementors[0]), translator, factory, criteriaImpl,
                criteriaImpl.getEntityOrClassName(), session.getLoadQueryInfluencers());

        final String sql = "select count(*) as cnt from (" + walker.getSQLString() + ") sq";

        getCurrentSession().flush(); // is this safe?

        return ((Number) getCurrentSession().createSQLQuery(sql)
                .setParameters(translator.getQueryParameters().getPositionalParameterValues(),
                        translator.getQueryParameters().getPositionalParameterTypes())
                .uniqueResult()).intValue();
    }

    @Override
    public InternalDataDefinition resolveDataDefinition(final Criteria criteria) {
        final CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
        final SessionImplementor session = (SessionImplementor) getCurrentSession();
        SessionFactoryImplementor factory = session.getFactory();
        CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteriaImpl,
                criteriaImpl.getEntityOrClassName(), CriteriaQueryTranslator.ROOT_SQL_ALIAS);

        String[] aliases = criteriaImpl.getProjection().getAliases();
        Type[] types = criteriaImpl.getProjection().getTypes(criteriaImpl, translator);

        return resolveDataDefinition(types, aliases);
    }

    @Override
    public InternalDataDefinition resolveDataDefinition(final Query query) {
        return resolveDataDefinition(query.getReturnTypes(), query.getReturnAliases());
    }

    private InternalDataDefinition resolveDataDefinition(final Type[] types, final String[] aliases) {
        if (types.length == 1 && types[0] instanceof EntityType) {
            return resolveDataDefinitionFromEntityType((EntityType) types[0]);
        } else {
            DynamicDataDefinitionImpl dataDefinition = new DynamicDataDefinitionImpl();

            for (int i = 0; i < types.length; i++) {
                dataDefinition.addField(aliases[i] == null ? Integer.toString(i) : aliases[i],
                        convertHibernateType(types[i]));
            }

            return dataDefinition;
        }
    }

    private InternalDataDefinition resolveDataDefinitionFromEntityType(final EntityType entityType) {
        return resolveDataDefinitionFromClassType(entityType.getName());
    }

    private InternalDataDefinition resolveDataDefinitionFromClassType(final String classType) {
        String[] tmp = classType.replaceFirst("com.qcadoo.model.beans.", "").split("\\.");
        String model = tmp[1].replaceFirst(tmp[0].substring(0, 1).toUpperCase(Locale.ENGLISH) + tmp[0].substring(1),
                "");
        Preconditions.checkState(StringUtils.isNotBlank(model), "Can't parse model name from class' binary name.");
        model = model.substring(0, 1).toLowerCase(Locale.ENGLISH) + model.substring(1);
        return (InternalDataDefinition) dataDefinitionService.get(tmp[0], model);
    }

    private FieldType convertHibernateType(final Type type) {
        if (type instanceof BigDecimalType || type instanceof DoubleType || type instanceof FloatType) {
            return new DecimalType();
        }
        if (type instanceof FloatType || type instanceof BigIntegerType || type instanceof IntegerType
                || type instanceof ShortType || type instanceof LongType) {
            return new com.qcadoo.model.internal.types.IntegerType();
        }
        if (type instanceof BooleanType) {
            return new com.qcadoo.model.internal.types.BooleanType();
        }
        if (type instanceof DateType) {
            return new com.qcadoo.model.internal.types.DateType();
        }
        if (type instanceof TimestampType || type instanceof TimeType) {
            return new DateTimeType();
        }
        if (type instanceof org.hibernate.type.StringType || type instanceof CharacterType) {
            return new StringType();
        }
        if (type instanceof TextType) {
            return new com.qcadoo.model.internal.types.TextType();
        }
        if (type instanceof EntityType) {
            DataDefinition dataDefinition = resolveDataDefinitionFromEntityType((EntityType) type);

            if (dataDefinition == null) {
                LOG.warn("Cannot find dataDefinition for class " + ((EntityType) type).getName());
            } else {
                return new BelongsToEntityType(dataDefinition.getPluginIdentifier(), dataDefinition.getName(),
                        dataDefinitionService, false, true);
            }
        }

        LOG.warn("Cannot map hibernate's type " + type.getClass().getCanonicalName() + ", using string type");

        return new StringType();
    }

    protected void setDataDefinitionService(final DataDefinitionService dataDefinitionService) {
        this.dataDefinitionService = dataDefinitionService;
    }

    protected void setSessionFactory(final SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public List<?> list(final Query query) {
        return query.list();
    }

    @Override
    public List<?> list(final Criteria criteria) {
        return criteria.list();
    }

}