Package com.impetus.client.rdbms.query

Source Code of com.impetus.client.rdbms.query.RDBMSEntityReader

/*******************************************************************************
* * Copyright 2012 Impetus Infotech.
*  *
*  * 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 com.impetus.client.rdbms.query;

import java.lang.reflect.Field;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EmbeddableType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.client.rdbms.HibernateClient;
import com.impetus.kundera.client.Client;
import com.impetus.kundera.client.ClientBase;
import com.impetus.kundera.client.EnhanceEntity;
import com.impetus.kundera.metadata.MetadataUtils;
import com.impetus.kundera.metadata.model.ApplicationMetadata;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.Relation;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.metadata.model.type.AbstractManagedType;
import com.impetus.kundera.persistence.AbstractEntityReader;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.persistence.EntityReader;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.query.KunderaQuery;
import com.impetus.kundera.query.KunderaQuery.FilterClause;
import com.impetus.kundera.query.QueryHandlerException;

/**
* The Class RDBMSEntityReader.
*
* @author vivek.mishra
*/
public class RDBMSEntityReader extends AbstractEntityReader implements EntityReader
{

    /** the log used by this class. */
    private static Logger log = LoggerFactory.getLogger(RDBMSEntityReader.class);

    /** The conditions. */
    private Queue conditions;

    /** The filter. */
    private String filter;

    /** The jpa query. */
    private String jpaQuery;

    /**
     * Instantiates a new rDBMS entity reader.
     *
     * @param luceneQuery
     *            the lucene query
     * @param query
     *            the query
     */
    public RDBMSEntityReader(String query, KunderaQuery kunderaQuery, final KunderaMetadata kunderaMetadata)
    {
        super(kunderaMetadata);
        this.jpaQuery = query;
        this.kunderaQuery = kunderaQuery;
    }

    /**
     * Instantiates a new rDBMS entity reader.
     */
    public RDBMSEntityReader(final KunderaMetadata kunderaMetadata)
    {
        super(kunderaMetadata);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.impetus.kundera.persistence.EntityReader#populateRelation(com.impetus
     * .kundera.metadata.model.EntityMetadata, java.util.List, boolean,
     * com.impetus.kundera.client.Client)
     */
    @Override
    public List<EnhanceEntity> populateRelation(EntityMetadata m, Client client, int maxResults)
    {
        // TODO: maxresults to be taken care after work on pagination.

        List<EnhanceEntity> ls = null;
        List<String> relationNames = m.getRelationNames();
        boolean isParent = m.isParent();
        if (!isParent)
        {
            // if it is not a parent.
            String sqlQuery = null;
            if (MetadataUtils.useSecondryIndex(((ClientBase) client).getClientMetadata()))
            {
                sqlQuery = getSqlQueryFromJPA(m, relationNames, null);
            }
            else
            {
                // prepare lucene query and find.
                Set<String> rSet = fetchDataFromLucene(m.getEntityClazz(), client);
                if (rSet != null && !rSet.isEmpty())
                {
                    filter = "WHERE";
                }
                sqlQuery = getSqlQueryFromJPA(m, relationNames, rSet);
            }
            // call client with relation name list and convert to sql query.

            ls = populateEnhanceEntities(m, relationNames, client, sqlQuery);
        }
        else
        {
            if (MetadataUtils.useSecondryIndex(((ClientBase) client).getClientMetadata()))
            {
                try
                {
                    List entities = ((HibernateClient) client).find(getSqlQueryFromJPA(m, relationNames, null),
                            new ArrayList<String>(), m);
                    ls = new ArrayList<EnhanceEntity>(entities.size());
                    ls = transform(m, ls, entities);
                }
                catch (Exception e)
                {
                    log.error("Error while executing handleAssociation for RDBMS, Caused by {}.", e);
                    throw new QueryHandlerException(e);
                }
            }
            else
            {
                ls = onAssociationUsingLucene(m, client, ls);
            }
        }

        return ls;
    }

    /**
     * Populate enhance entities.
     *
     * @param m
     *            the m
     * @param relationNames
     *            the relation names
     * @param client
     *            the client
     * @param sqlQuery
     *            the sql query
     * @return the list
     */
    private List<EnhanceEntity> populateEnhanceEntities(EntityMetadata m, List<String> relationNames, Client client,
            String sqlQuery)
    {
        List<EnhanceEntity> ls = null;
        List result = ((HibernateClient) client).find(sqlQuery, relationNames, m);

        if (!result.isEmpty())
        {
            ls = new ArrayList<EnhanceEntity>(result.size());
            for (Object o : result)
            {
                EnhanceEntity entity = null;
                if (!o.getClass().isAssignableFrom(EnhanceEntity.class))
                {
                    entity = new EnhanceEntity(o, getId(o, m), null);
                }
                else
                {
                    entity = (EnhanceEntity) o;
                }
                ls.add(entity);
            }
        }
        return ls;
    }

    /**
     * Gets the sql query from jpa.
     *
     * @param entityMetadata
     *            the entity metadata
     * @param relations
     *            the relations
     * @param primaryKeys
     *            the primary keys
     * @return the sql query from jpa
     */
    public String getSqlQueryFromJPA(EntityMetadata entityMetadata, List<String> relations, Set<String> primaryKeys)
    {
        ApplicationMetadata appMetadata = kunderaMetadata.getApplicationMetadata();
        Metamodel metaModel = appMetadata.getMetamodel(entityMetadata.getPersistenceUnit());

        if (jpaQuery != null)
        {
            String query = appMetadata.getQuery(jpaQuery);
            boolean isNative = kunderaQuery != null ? kunderaQuery.isNative() : false;

            if (isNative)
            {
                return query != null ? query : jpaQuery;
            }
        }

        // Suffixing the UNDERSCORE instead of prefix as Oracle 11g complains
        // about invalid characters error while executing the request.
        String aliasName = entityMetadata.getTableName() + "_";

        StringBuilder queryBuilder = new StringBuilder("Select ");

        EntityType entityType = metaModel.entity(entityMetadata.getEntityClazz());
        Set<Attribute> attributes = entityType.getAttributes();
        for (Attribute field : attributes)
        {
            if (!field.isAssociation() && !field.isCollection()
                    && !((Field) field.getJavaMember()).isAnnotationPresent(ManyToMany.class)
                    && !((Field) field.getJavaMember()).isAnnotationPresent(Transient.class)
                    && !((MetamodelImpl) metaModel).isEmbeddable(((AbstractAttribute) field).getBindableJavaType()))
            {
                queryBuilder.append(aliasName);
                queryBuilder.append(".");
                queryBuilder.append(((AbstractAttribute) field).getJPAColumnName());
                queryBuilder.append(", ");
            }
        }

        // Handle embedded columns, add them to list.
        Map<String, EmbeddableType> embeddedColumns = ((MetamodelImpl) metaModel).getEmbeddables(entityMetadata
                .getEntityClazz());
        for (EmbeddableType embeddedCol : embeddedColumns.values())
        {
            Set<Attribute> embeddedAttributes = embeddedCol.getAttributes();
            for (Attribute column : embeddedAttributes)
            {
                queryBuilder.append(aliasName);
                queryBuilder.append(".");
                queryBuilder.append(((AbstractAttribute) column).getJPAColumnName());
                queryBuilder.append(", ");
            }
        }

        if (relations != null)
        {
            for (String relation : relations)
            {
                Relation rel = entityMetadata.getRelation(entityMetadata.getFieldName(relation));
                String r = MetadataUtils.getMappedName(entityMetadata, rel, kunderaMetadata);
                if (!((AbstractAttribute) entityMetadata.getIdAttribute()).getJPAColumnName().equalsIgnoreCase(
                        r != null ? r : relation)
                        && rel != null
                        && !rel.getProperty().isAnnotationPresent(ManyToMany.class)
                        && !rel.getProperty().isAnnotationPresent(OneToMany.class)
                        && (rel.getProperty().isAnnotationPresent(OneToOne.class)
                                && StringUtils.isBlank(rel.getMappedBy()) || rel.getProperty().isAnnotationPresent(
                                ManyToOne.class)))
                {
                    queryBuilder.append(aliasName);
                    queryBuilder.append(".");
                    queryBuilder.append(r != null ? r : relation);
                    queryBuilder.append(", ");
                }
            }
        }

        // Remove last ","
        queryBuilder.deleteCharAt(queryBuilder.lastIndexOf(","));

        queryBuilder.append(" From ");
        if (entityMetadata.getSchema() != null && !entityMetadata.getSchema().isEmpty())
        {
            queryBuilder.append(entityMetadata.getSchema() + ".");
        }
        queryBuilder.append(entityMetadata.getTableName());
        queryBuilder.append(" ");
        queryBuilder.append(aliasName);
        // add conditions
        if (filter != null)
        {
            queryBuilder.append(" Where ");
        }

        // Append conditions
        onCondition(entityMetadata, (MetamodelImpl) metaModel, primaryKeys, aliasName, queryBuilder, entityType);

        return queryBuilder.toString();
    }

    /**
     *
     * @param entityMetadata
     * @param primaryKeys
     * @param aliasName
     * @param queryBuilder
     * @param entityType
     */
    private void onCondition(EntityMetadata entityMetadata, MetamodelImpl metamodel, Set<String> primaryKeys,
            String aliasName, StringBuilder queryBuilder, EntityType entityType)
    {
        if (primaryKeys == null)
        {
            for (Object o : conditions)
            {
                if (o instanceof FilterClause)
                {
                    FilterClause clause = ((FilterClause) o);
                    Object value = clause.getValue().get(0);
                    String propertyName = clause.getProperty();
                    String condition = clause.getCondition();

                    if (StringUtils.contains(propertyName, '.'))
                    {
                        int indexOf = propertyName.indexOf(".");
                        String jpaColumnName = propertyName.substring(0, indexOf);
                        String embeddedColumnName = propertyName.substring(indexOf + 1, propertyName.length());
                        String fieldName = entityMetadata.getFieldName(jpaColumnName);
                        Attribute attribute = entityType.getAttribute(fieldName);
                        EmbeddableType embeddedType = metamodel.embeddable(((AbstractAttribute) attribute)
                                .getBindableJavaType());
                        Attribute embeddedAttribute = embeddedType.getAttribute(embeddedColumnName);

                        addClause(entityMetadata, aliasName, queryBuilder, entityType, value, condition, fieldName,
                                embeddedAttribute);
                    }
                    else
                    {
                        String fieldName = entityMetadata.getFieldName(propertyName);
                        Attribute attribute = entityType.getAttribute(fieldName);
                        if (metamodel.isEmbeddable(((AbstractAttribute) attribute).getBindableJavaType()))
                        {
                            EmbeddableType embeddedType = metamodel.embeddable(((AbstractAttribute) attribute)
                                    .getBindableJavaType());
                            Set<Attribute> attributes = embeddedType.getAttributes();
                            for (Attribute embeddedAttribute : attributes)
                            {
                                Object embeddedAttributevalue = PropertyAccessorHelper.getObject(value,
                                        (Field) embeddedAttribute.getJavaMember());
                                addClause(entityMetadata, aliasName, queryBuilder, entityType, embeddedAttributevalue,
                                        condition, propertyName, embeddedAttribute);
                                queryBuilder.append(" and ");
                            }

                            queryBuilder.delete(queryBuilder.lastIndexOf("and"), queryBuilder.lastIndexOf("and") + 3);
                        }
                        else if (((AbstractAttribute) entityMetadata.getIdAttribute()).getJPAColumnName().equals(
                                propertyName))
                        {
                            addClause(entityMetadata, aliasName, queryBuilder, entityType, value, condition,
                                    propertyName, entityMetadata.getIdAttribute());
                        }
                        else
                        {
                            addClause(entityMetadata, aliasName, queryBuilder, entityType, value, condition,
                                    propertyName, attribute);
                        }
                    }
                }
                else
                {
                    queryBuilder.append(" ");
                    queryBuilder.append(o);
                    queryBuilder.append(" ");
                }
            }
        }
        else
        {
            queryBuilder.append(aliasName);
            queryBuilder.append(".");
            queryBuilder.append(((AbstractAttribute) entityMetadata.getIdAttribute()).getJPAColumnName());
            queryBuilder.append(" ");
            queryBuilder.append("IN(");
            int count = 0;
            Attribute col = entityMetadata.getIdAttribute();
            boolean isString = isStringProperty(entityType, col);
            for (String key : primaryKeys)
            {
                appendStringPrefix(queryBuilder, isString);
                queryBuilder.append(key);
                appendStringPrefix(queryBuilder, isString);
                if (++count != primaryKeys.size())
                {
                    queryBuilder.append(",");
                }
                else
                {
                    queryBuilder.append(")");
                }
            }
        }
    }

    /**
     *
     * @param entityMetadata
     * @param aliasName
     * @param queryBuilder
     * @param entityType
     * @param value
     * @param condition
     * @param propertyName
     * @param attribute
     */
    private void addClause(EntityMetadata entityMetadata, String aliasName, StringBuilder queryBuilder,
            EntityType entityType, Object value, String condition, String propertyName, Attribute attribute)
    {
        boolean isString = isStringProperty(entityType, attribute);

        // queryBuilder.append(aliasName);
        // queryBuilder.append(".");
        queryBuilder.append(StringUtils.replace(((AbstractAttribute) attribute).getJPAColumnName(), aliasName,
                aliasName));

        queryBuilder.append(" ");
        queryBuilder.append(condition);

        if (condition.equalsIgnoreCase("like"))
        {
            queryBuilder.append("%");
        }
        queryBuilder.append(" ");
        if (condition.equalsIgnoreCase("IN"))
        {
            buildINClause(queryBuilder, value, isString);
        }
        else
        {
            appendStringPrefix(queryBuilder, isString);
            queryBuilder.append(value);
            appendStringPrefix(queryBuilder, isString);
        }
    }

    /**
     *
     * @param queryBuilder
     * @param value
     * @param isString
     */
    private void buildINClause(StringBuilder queryBuilder, Object value, boolean isString)
    {
        if (List.class.isAssignableFrom(value.getClass()) || Set.class.isAssignableFrom(value.getClass()))
        {
            queryBuilder.append(" (");
            Collection collection = ((Collection) value);
            for (Object obj : collection)
            {
                if (isString)
                {
                    appendStringPrefix(queryBuilder, isString);
                }
                queryBuilder.append(obj.toString());
                if (isString)
                {
                    appendStringPrefix(queryBuilder, isString);
                }
                queryBuilder.append(",");
            }
            if (!collection.isEmpty())
            {
                queryBuilder.deleteCharAt(queryBuilder.lastIndexOf(","));
            }
            queryBuilder.append(")");
        }
        else
        {
            queryBuilder.append(value.toString());
        }
    }

    /**
     * Append string prefix.
     *
     * @param queryBuilder
     *            the query builder
     * @param isString
     *            the is string
     */
    private void appendStringPrefix(StringBuilder queryBuilder, boolean isString)
    {
        if (isString)
        {
            queryBuilder.append("'");
        }
    }

    /**
     * Sets the conditions.
     *
     * @param q
     *            the new conditions
     */
    public void setConditions(Queue q)
    {
        this.conditions = q;
    }

    /**
     * Sets the filter.
     *
     * @param filter
     *            the new filter
     */
    public void setFilter(String filter)
    {
        this.filter = filter;
    }

    /**
     * Populate relations.
     *
     * @param relations
     *            the relations
     * @param o
     *            the o
     * @return the map
     */
    private Map<String, Object> populateRelations(List<String> relations, Object[] o)
    {
        Map<String, Object> relationVal = new HashMap<String, Object>(relations.size());
        int counter = 1;
        for (String r : relations)
        {
            relationVal.put(r, o[counter++]);
        }
        return relationVal;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.impetus.kundera.persistence.EntityReader#findById(java.lang.Object,
     * com.impetus.kundera.metadata.model.EntityMetadata, java.util.List,
     * com.impetus.kundera.client.Client)
     */
    @Override
    public EnhanceEntity findById(Object primaryKey, EntityMetadata m, Client client)
    {
        List<String> relationNames = m.getRelationNames();
        if (relationNames != null && !relationNames.isEmpty())
        {
            Set<String> keys = new HashSet<String>(1);
            keys.add(primaryKey.toString());
            String query = getSqlQueryFromJPA(m, relationNames, keys);
            List<EnhanceEntity> results = populateEnhanceEntities(m, relationNames, client, query);
            return results != null && !results.isEmpty() ? results.get(0) : null;
        }
        else
        {
            Object o;
            try
            {
                o = client.find(m.getEntityClazz(), primaryKey);
            }
            catch (Exception e)
            {
                throw new PersistenceException(e);
            }
            return o != null ? new EnhanceEntity(o, getId(o, m), null) : null;
        }

        // return super.findById(primaryKey, m, client);
    }

    /**
     * Checks if is string property.
     *
     * @param m
     *            the m
     * @param fieldName
     *            the field name
     * @return true, if is string property
     */
    private boolean isStringProperty(EntityType entityType, Attribute attribute)
    {
        String discriminatorColumn = ((AbstractManagedType) entityType).getDiscriminatorColumn();

        if (attribute.getName().equals(discriminatorColumn))
        {
            return true;
        }

        return attribute != null ? ((AbstractAttribute) attribute).getBindableJavaType().isAssignableFrom(String.class)
                || ((AbstractAttribute) attribute).getBindableJavaType().isAssignableFrom(Character.class)
                || ((AbstractAttribute) attribute).getBindableJavaType().isAssignableFrom(char.class)
                || ((AbstractAttribute) attribute).getBindableJavaType().isAssignableFrom(Date.class)
                || ((AbstractAttribute) attribute).getBindableJavaType().isAssignableFrom(java.util.Date.class) : false;
    }
}
TOP

Related Classes of com.impetus.client.rdbms.query.RDBMSEntityReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.