All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.impetus.client.cassandra.query.CassandraEntityReader Maven / Gradle / Ivy

There is a newer version: 3.13
Show newest version
/*******************************************************************************
 * * 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.cassandra.query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.cassandra.thrift.IndexClause;
import org.apache.cassandra.thrift.IndexExpression;
import org.apache.cassandra.thrift.IndexOperator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.client.cassandra.CassandraClientBase;
import com.impetus.kundera.Constants;
import com.impetus.kundera.client.Client;
import com.impetus.kundera.client.ClientBase;
import com.impetus.kundera.client.EnhanceEntity;
import com.impetus.kundera.db.SearchResult;
import com.impetus.kundera.metadata.MetadataUtils;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.persistence.AbstractEntityReader;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.persistence.EntityReader;
import com.impetus.kundera.query.KunderaQuery;
import com.impetus.kundera.query.QueryHandlerException;

/**
 * The Class CassandraEntityReader.
 * 
 * @author vivek.mishra
 */
public class CassandraEntityReader extends AbstractEntityReader implements EntityReader
{
    private static final String MIN_ = "min";

    private static final String MAX_ = "max";

    /** The conditions. */
    private Map> conditions = new HashMap>();

    /** The log. */
    private static Logger log = LoggerFactory.getLogger(CassandraEntityReader.class);

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

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

    @Override
    public EnhanceEntity findById(Object primaryKey, EntityMetadata m, Client client)
    {
        return super.findById(primaryKey, m, client);
    }

    /**
     * Method responsible for reading back entity and relations using secondary
     * indexes(if it holds any relation), else retrieve row keys using lucene.
     * 
     * @param m
     *            entity meta data
     * @param relationNames
     *            relation names
     * @param isParent
     *            if entity is not holding any relation.
     * @param client
     *            client instance
     * @return list of wrapped enhance entities.
     */

    @Override
    public List populateRelation(EntityMetadata m, Client client, int maxResults)
    {
        if (log.isInfoEnabled())
        {
            log.info("On populate relation via JPQL");
        }
        List ls = null;
        List relationNames = m.getRelationNames();
        boolean isParent = m.isParent();

        boolean isRowKeyQuery = conditions != null ? conditions.keySet().iterator().next() : false;

        // If Query is not for find by range.
        if (!isRowKeyQuery)
        {
            // If holding associations.
            if (!isParent)
            {
                // In case need to use secondary indexes.
                if (MetadataUtils.useSecondryIndex(((ClientBase) client).getClientMetadata()))
                {
                    ls = ((CassandraClientBase) client).find(m, relationNames, this.conditions.get(isRowKeyQuery),
                            maxResults, null);
                }
                else
                {
                    // prepare lucene query and find.
                    Set rSet = fetchDataFromLucene(m.getEntityClazz(), client);

                    try
                    {
                        ls = (List) ((CassandraClientBase) client).find(m.getEntityClazz(),
                                relationNames, true, m, rSet.toArray(new Object[] {}));
                    }
                    catch (Exception e)
                    {
                        log.error("Error while executing handleAssociation for cassandra, Caused by: ", e);
                        throw new QueryHandlerException(e);
                    }
                }
            }
            else
            {
                if (MetadataUtils.useSecondryIndex(((ClientBase) client).getClientMetadata()))
                {
                    // in case need to search on secondry columns and it is not
                    // set
                    // to true!
                    ls = ((CassandraClientBase) client).find(this.conditions.get(isRowKeyQuery), m, true,
                            m.getRelationNames(), maxResults, null);
                }
                else
                {
                    ls = onAssociationUsingLucene(m, client, ls);
                }
            }
        }
        else
        {
            ls = handleFindByRange(m, client, ls, conditions, isRowKeyQuery, null, maxResults);
        }
        return ls;
    }

    /**
     * Handle find by range.
     * 
     * @param m
     *            the m
     * @param client
     *            the client
     * @param result
     *            the result
     * @param ixClause
     *            the ix clause
     * @param isRowKeyQuery
     *            the is row key query
     * @param columns
     * @return the list
     */
    public List handleFindByRange(EntityMetadata m, Client client, List result,
            Map> ixClause, boolean isRowKeyQuery, List columns, int maxResults)
    {
        List expressions = ixClause.get(isRowKeyQuery).get(0).getExpressions();

        if (expressions == null)
        {
            return null;
        }

        Map rowKeys = getRowKeyValue(expressions,
                ((AbstractAttribute) m.getIdAttribute()).getJPAColumnName());

        byte[] minValue = rowKeys.get(MIN_);
        byte[] maxVal = rowKeys.get(MAX_);

        try
        {
            result = ((CassandraClientBase) client).findByRange(minValue, maxVal, m, m.getRelationNames() != null
                    && !m.getRelationNames().isEmpty(), m.getRelationNames(), columns, expressions, maxResults);
        }
        catch (Exception e)
        {
            log.error("Error while executing find by range, Caused by: ", e);
            throw new QueryHandlerException(e);
        }
        return result;
    }

    public List readFromIndexTable(EntityMetadata m, Client client,
            Map> indexClauseMap)
    {
        List searchResults = new ArrayList();
        List primaryKeys = new ArrayList();

        String columnFamilyName = m.getTableName() + Constants.INDEX_TABLE_SUFFIX;
        searchResults = ((CassandraClientBase) client).searchInInvertedIndex(columnFamilyName, m, indexClauseMap);

        Map embeddedColumns = new HashMap();
        for (SearchResult searchResult : searchResults)
        {
            if (searchResult.getEmbeddedColumnValues() != null)
            {
                for (String embeddedColVal : searchResult.getEmbeddedColumnValues())
                {
                    if (embeddedColVal != null)
                    {
                        StringBuilder strBuilder = new StringBuilder(embeddedColVal);
                        strBuilder.append("|");
                        strBuilder.append(searchResult.getPrimaryKey().toString());
                        embeddedColumns.put(strBuilder.toString(), searchResult.getPrimaryKey().toString());
                    }
                }
            }
        }
        List enhanceEntityList = new ArrayList();
        if (embeddedColumns != null && !embeddedColumns.isEmpty())
        {
            enhanceEntityList = client.find(m.getEntityClazz(), embeddedColumns);
        }
        else
        {
            for (SearchResult searchResult : searchResults)
            {
                primaryKeys.add(searchResult.getPrimaryKey());
            }
            enhanceEntityList = (List) ((CassandraClientBase) client).find(m.getEntityClazz(),
                    m.getRelationNames(), true, m, primaryKeys.toArray(new String[] {}));
        }

        return enhanceEntityList;
    }

    /**
     * Method to set indexcluase conditions.
     * 
     * @param conditions
     *            index conditions.
     */
    public void setConditions(Map> conditions)
    {
        this.conditions = conditions;
    }

    /**
     * Returns list of row keys. First element will be min value and second will
     * be major value.
     * 
     * @param expressions
     * @param primaryKeyName
     * @return
     */
    Map getRowKeyValue(List expressions, String primaryKeyName)
    {
        Map rowKeys = new HashMap();

        List rowExpressions = new ArrayList();

        if (expressions != null)
        {
            for (IndexExpression e : expressions)
            {
                if (primaryKeyName.equals(new String(e.getColumn_name())))
                {
                    IndexOperator operator = e.op;
                    if (operator.equals(IndexOperator.LTE) || operator.equals(IndexOperator.LT))
                    {
                        rowKeys.put(MAX_, e.getValue());
                        rowExpressions.add(e);
                    }
                    else if (operator.equals(IndexOperator.GTE) || operator.equals(IndexOperator.GT))
                    {
                        rowKeys.put(MIN_, e.getValue());
                        rowExpressions.add(e);
                    }
                    else if (operator.equals(IndexOperator.EQ))
                    {
                        rowKeys.put(MAX_, e.getValue());
                        rowKeys.put(MIN_, e.getValue());
                        rowExpressions.add(e);
                    }
                }
            }
            expressions.removeAll(rowExpressions);
        }
        return rowKeys;
    }
}