Package info.archinnov.achilles.query.slice

Source Code of info.archinnov.achilles.query.slice.SliceQueryProperties

/*
* Copyright (C) 2012-2014 DuyHai DOAN
*
*  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 info.archinnov.achilles.query.slice;

import static com.datastax.driver.core.querybuilder.QueryBuilder.asc;
import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
import static com.datastax.driver.core.querybuilder.QueryBuilder.desc;
import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
import static com.datastax.driver.core.querybuilder.QueryBuilder.gt;
import static com.datastax.driver.core.querybuilder.QueryBuilder.gte;
import static com.datastax.driver.core.querybuilder.QueryBuilder.in;
import static com.datastax.driver.core.querybuilder.QueryBuilder.lt;
import static com.datastax.driver.core.querybuilder.QueryBuilder.lte;
import static com.google.common.collect.FluentIterable.from;
import static info.archinnov.achilles.schemabuilder.Create.Options.ClusteringOrder;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import com.datastax.driver.core.querybuilder.Select.Where;
import info.archinnov.achilles.schemabuilder.Create.Options.ClusteringOrder.Sorting;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.RegularStatement;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.BindMarker;
import com.datastax.driver.core.querybuilder.Delete;
import com.datastax.driver.core.querybuilder.Select;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import info.archinnov.achilles.internal.metadata.holder.EntityMeta;
import info.archinnov.achilles.internal.validation.Validator;
import info.archinnov.achilles.type.ConsistencyLevel;

public class SliceQueryProperties<T> {

    private static final Logger log = LoggerFactory.getLogger(SliceQueryProperties.class);

    public static final int DEFAULT_LIMIT = 100;

    private static final Function<String, Object> FROM_NAME_TO_BIND_MARKER = new Function<String, Object>() {
        @Override
        public BindMarker apply(String name) {
            return bindMarker(name);
        }
    };

    private final EntityMeta entityMeta;
    private final Class<T> entityClass;
    private final SliceType sliceType;

    private Optional<Integer> limitO = Optional.fromNullable(DEFAULT_LIMIT);
    protected Optional<Integer> fetchSizeO = Optional.absent();
    private BoundingMode boundingMode = BoundingMode.INCLUSIVE_BOUNDS;
    private Optional<OrderingMode> orderingModeO = Optional.absent();

    private Optional<ConsistencyLevel> consistencyLevelO = Optional.absent();

    private List<Object> partitionKeys = new LinkedList<>();
    private List<String> partitionKeysName = new LinkedList<>();
    private List<Object> partitionKeysIn = new LinkedList<>();
    private String lastPartitionKeyName;
    private List<Object> fromClusteringKeys = new LinkedList<>();
    private List<String> fromClusteringKeysName = new LinkedList<>();
    private List<Object> toClusteringKeys = new LinkedList<>();
    private List<String> toClusteringKeysName = new LinkedList<>();
    private List<Object> withClusteringKeys = new LinkedList<>();
    private List<String> withClusteringKeysName = new LinkedList<>();
    private List<Object> clusteringsKeysIn = new LinkedList<>();
    private String lastClusteringKeyName;

    private ClusteringOrder clusteringOrder;

    private FutureCallback<Object>[] asyncListeners;

    private SliceQueryProperties(EntityMeta entityMeta, Class<T> entityClass, SliceType sliceType) {
        this.entityMeta = entityMeta;
        this.entityClass = entityClass;
        this.sliceType = sliceType;
        this.clusteringOrder = entityMeta.forSliceQuery().getClusteringOrderForSliceQuery();
    }

    public static <T> SliceQueryProperties<T> builder(EntityMeta entityMeta, Class<T> entityClass, SliceType sliceType) {
        return new SliceQueryProperties<>(entityMeta, entityClass, sliceType);
    }

    protected SliceQueryProperties<T>  limit(int limit) {
        Validator.validateTrue(limit > 0, "The limit '%s' should be strictly positive", limit);
        this.limitO = Optional.fromNullable(limit);
        return this;
    }

    protected SliceQueryProperties<T>  disableLimit() {
        this.limitO = Optional.absent();
        return this;
    }

    protected SliceQueryProperties<T>  fetchSize(int fetchSize) {
        Validator.validateTrue(fetchSize > 0, "The fetchSize '%s' should be strictly positive", fetchSize);
        this.fetchSizeO = Optional.fromNullable(fetchSize);
        if (CollectionUtils.isNotEmpty(partitionKeysIn)) {
            this.orderingModeO = Optional.absent();
            log.warn("Cannot page queries with both ORDER BY and a IN restriction on the partition key; you must either remove the ORDER BY or the IN and sort client side, or disable paging for this query");
        }
        return this;
    }

    protected SliceQueryProperties<T>  bounding(BoundingMode boundingMode) {
        this.boundingMode = boundingMode;
        return this;
    }

    protected SliceQueryProperties<T>  ordering(OrderingMode orderingMode) {
        this.orderingModeO = Optional.fromNullable(orderingMode);
        return this;
    }

    protected SliceQueryProperties<T>  consistency(ConsistencyLevel consistencyLevel) {
        Validator.validateNotNull(consistencyLevel, "The consistency level should not be null");
        this.consistencyLevelO = Optional.fromNullable(consistencyLevel);
        return this;
    }

    protected SliceQueryProperties<T>  partitionKeys(List<Object> partitionKeys) {
        this.partitionKeys = partitionKeys;
        return this;
    }

    protected SliceQueryProperties<T>  partitionKeysName(List<String> partitionKeysName) {
        this.partitionKeysName = partitionKeysName;
        return this;
    }

    protected SliceQueryProperties<T> andPartitionKeysIn(List<Object> partitionKeysIn) {
        this.partitionKeysIn = partitionKeysIn;
        return this;
    }

    protected SliceQueryProperties<T>  lastPartitionKeyName(String lastPartitionKeyName) {
        this.lastPartitionKeyName = lastPartitionKeyName;
        return this;
    }

    protected SliceQueryProperties<T>  fromClusteringKeys(List<Object> fromClusteringKeys) {
        this.fromClusteringKeys = fromClusteringKeys;
        return this;
    }

    protected SliceQueryProperties<T>  fromClusteringKeysName(List<String> fromClusteringKeysName) {
        this.fromClusteringKeysName = fromClusteringKeysName;
        return this;
    }

    protected SliceQueryProperties<T>  toClusteringKeys(List<Object> toClusteringKeys) {
        this.toClusteringKeys = toClusteringKeys;
        return this;
    }

    protected SliceQueryProperties<T>  toClusteringKeysName(List<String> toClusteringKeysName) {
        this.toClusteringKeysName = toClusteringKeysName;
        return this;
    }

    protected SliceQueryProperties<T>  withClusteringKeys(List<Object> withClusteringKeys) {
        this.withClusteringKeys = withClusteringKeys;
        return this;
    }

    protected SliceQueryProperties<T>  withClusteringKeysName(List<String> withClusteringKeysName) {
        this.withClusteringKeysName = withClusteringKeysName;
        return this;
    }

    protected SliceQueryProperties<T>  andClusteringKeysIn(List<Object> clusteringsKeysIn) {
        this.clusteringsKeysIn = clusteringsKeysIn;
        return this;
    }

    protected SliceQueryProperties<T>  lastClusteringKeyName(String lastClusteringKeyName) {
        this.lastClusteringKeyName = lastClusteringKeyName;
        return this;
    }

    protected SliceQueryProperties<T>  asyncListeners(FutureCallback<Object>[] asyncListeners) {
        Validator.validateNotEmpty(asyncListeners,"The provided async listeners should not be null");
        this.asyncListeners = asyncListeners;
        return this;
    }

    // Public access

    public RegularStatement generateWhereClauseForSelect(Select from) {
        final Select.Where where = from.where();

        // Partition keys
        for (String partitionKeyName : partitionKeysName) {
            where.and(eq(partitionKeyName, bindMarker(partitionKeyName)));
        }

        if (isNotBlank(lastPartitionKeyName)) {
            where.and(in(lastPartitionKeyName, bindMarker("partitionComponentsIn")));
        }

        // Clustering keys
        if (isNotEmpty(withClusteringKeys)) {
            for (String withClusteringName : withClusteringKeysName) {
                where.and(eq(withClusteringName, bindMarker(withClusteringName)));
            }

            if (isNotBlank(lastClusteringKeyName)) {
                where.and(in(lastClusteringKeyName, bindMarker("clusteringKeysIn")));
            }
        } else {
            if (isNotEmpty(fromClusteringKeys)) {
                boundingMode.buildFromClusteringKeys(where, clusteringOrder, fromClusteringKeysName);
            }

            if (isNotEmpty(toClusteringKeys)) {
                boundingMode.buildToClusteringKeys(where, clusteringOrder, toClusteringKeysName);
            }
        }

        // ORDER BY
        if (orderingModeO.isPresent()) {

            final Select statement;
            final OrderingMode orderingMode = orderingModeO.get();
            if (orderingMode.isReverse()) {
                statement = where.orderBy(desc(clusteringOrder.getClusteringColumnName()));
            } else {
                statement = where.orderBy(asc(clusteringOrder.getClusteringColumnName()));
            }
            // LIMIT
            if (limitO.isPresent()) {
                statement.limit(bindMarker("limitSize"));
            }

            return statement;
        } else {
            // LIMIT
            if (limitO.isPresent()) {
                where.limit(bindMarker("limitSize"));
            }

            return where;

        }
    }

    public Delete.Where generateWhereClauseForDelete(Delete delete) {
        final Delete.Where where = delete.where();

        // Partition keys
        for (String partitionKeyName : partitionKeysName) {
            where.and(eq(partitionKeyName, bindMarker(partitionKeyName)));
        }

        if (isNotBlank(lastPartitionKeyName)) {
            where.and(in(lastPartitionKeyName, bindMarker("partitionComponentsIn")));
        }

        // Clustering keys
        if (isNotEmpty(withClusteringKeys)) {
            for (String withClusteringName : withClusteringKeysName) {
                where.and(eq(withClusteringName, bindMarker(withClusteringName)));
            }
        }
        return where;
    }

    public Object[] getBoundValues() {
        List<Object> boundValues = new LinkedList<>();
        // Partition keys
        boundValues.addAll(entityMeta.forTranscoding().encodePartitionComponents(partitionKeys));

        if (isNotEmpty(partitionKeysIn)) {
            boundValues.add(entityMeta.forTranscoding().encodePartitionComponentsIN(partitionKeysIn));
        }

        // Clustering keys
        if (isNotEmpty(withClusteringKeys)) {
            boundValues.addAll(entityMeta.forTranscoding().encodeClusteringKeys(withClusteringKeys));

            if (isNotEmpty(clusteringsKeysIn)) {
                boundValues.add(entityMeta.forTranscoding().encodeClusteringKeysIN(clusteringsKeysIn));
            }
        } else {
            if (isNotEmpty(fromClusteringKeys)) {
                boundValues.addAll(entityMeta.forTranscoding().encodeClusteringKeys(fromClusteringKeys));
            }

            if (isNotEmpty(toClusteringKeys)) {
                boundValues.addAll(entityMeta.forTranscoding().encodeClusteringKeys(toClusteringKeys));
            }
        }

        // LIMIT
        if (limitO.isPresent()) {
            boundValues.add(limitO.get());
        }

        return boundValues.toArray();
    }

    public void setFetchSizeToStatement(Statement statement) {
        if (fetchSizeO.isPresent()) {
            statement.setFetchSize(fetchSizeO.get());
        }
    }

    public ConsistencyLevel getConsistencyLevelOr(ConsistencyLevel defaultConsistencyLevel) {
        return consistencyLevelO.or(defaultConsistencyLevel);
    }

    public Class<T> getEntityClass() {
        return entityClass;
    }

    public EntityMeta getEntityMeta() {
        return entityMeta;
    }

    public List<Object> getPartitionKeys() {
        return partitionKeys;
    }

    public List<Object> getWithClusteringKeys() {
        return withClusteringKeys;
    }

    public FutureCallback<Object>[] getAsyncListeners() {
        return asyncListeners;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        SliceQueryProperties that = (SliceQueryProperties) o;

        return Objects.equals(this.sliceType, that.sliceType) &&
                Objects.equals(this.entityClass, that.entityClass) &&
                Objects.equals(this.partitionKeysName, that.partitionKeysName) &&
                Objects.equals(this.lastPartitionKeyName, that.lastPartitionKeyName) &&
                Objects.equals(this.fromClusteringKeysName, that.fromClusteringKeysName) &&
                Objects.equals(this.toClusteringKeysName, that.toClusteringKeysName) &&
                Objects.equals(this.withClusteringKeysName, that.withClusteringKeysName) &&
                Objects.equals(this.lastClusteringKeyName, that.lastClusteringKeyName) &&
                Objects.equals(this.boundingMode, that.boundingMode) &&
                Objects.equals(this.orderingModeO, that.orderingModeO) &&
                Objects.equals(this.limitO, that.limitO);
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.sliceType,
                this.entityClass,
                this.partitionKeysName,
                this.lastPartitionKeyName,
                this.fromClusteringKeysName,
                this.toClusteringKeysName,
                this.withClusteringKeysName,
                this.lastClusteringKeyName,
                this.boundingMode,
                this.orderingModeO,
                this.limitO);
    }

    public static enum SliceType {
        SELECT, ITERATE, DELETE;
    }
}
TOP

Related Classes of info.archinnov.achilles.query.slice.SliceQueryProperties

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.