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

info.archinnov.achilles.query.cql.AbstractNativeQuery Maven / Gradle / Ivy

There is a newer version: 6.1.0
Show newest version
package info.archinnov.achilles.query.cql;

import com.datastax.driver.core.PagingState;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Statement;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListenableFuture;
import info.archinnov.achilles.async.AchillesFuture;
import info.archinnov.achilles.internal.async.AsyncUtils;
import info.archinnov.achilles.internal.async.RowsWithExecutionInfo;
import info.archinnov.achilles.internal.context.ConfigurationContext;
import info.archinnov.achilles.internal.context.DaoContext;
import info.archinnov.achilles.internal.persistence.operations.NativeQueryMapper;
import info.archinnov.achilles.internal.persistence.operations.TypedMapIterator;
import info.archinnov.achilles.internal.statement.wrapper.NativeQueryLog;
import info.archinnov.achilles.internal.statement.wrapper.NativeStatementWrapper;
import info.archinnov.achilles.type.Empty;
import info.archinnov.achilles.options.Options;
import info.archinnov.achilles.type.TypedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;

import static info.archinnov.achilles.internal.async.AsyncUtils.RESULTSET_TO_ROWS;
import static info.archinnov.achilles.internal.async.AsyncUtils.RESULTSET_TO_ROWS_WITH_EXECUTION_INFO;

public abstract class AbstractNativeQuery> {

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

    protected NativeStatementWrapper nativeStatementWrapper;

    protected DaoContext daoContext;
    protected AsyncUtils asyncUtils = AsyncUtils.Singleton.INSTANCE.get();
    protected NativeQueryMapper mapper = NativeQueryMapper.Singleton.INSTANCE.get();
    protected Optional pagingStateO = Optional.absent();
    protected ExecutorService executorService;

    protected AbstractNativeQuery(DaoContext daoContext, ConfigurationContext configContext, Statement statement, Options options, Object... boundValues) {
        this.daoContext = daoContext;
        this.nativeStatementWrapper = new NativeStatementWrapper(NativeQueryLog.class, statement, boundValues, options.getLWTResultListener());
        this.executorService = configContext.getExecutorService();
    }

    protected abstract T getThis();

    protected ListenableFuture asyncGetInternal(FutureCallback... asyncListeners) {
        log.debug("Get results for native query '{}' asynchronously", nativeStatementWrapper.getStatement());

        if (pagingStateO.isPresent()) {
            nativeStatementWrapper.setPagingState(pagingStateO.get());
        }

        final ListenableFuture resultSetFuture = daoContext.execute(nativeStatementWrapper);

        final ListenableFuture futureRows = asyncUtils.transformFuture(resultSetFuture, RESULTSET_TO_ROWS_WITH_EXECUTION_INFO);

        Function rowsToTypedMaps = new Function() {
            @Override
            public TypedMapsWithPagingState apply(RowsWithExecutionInfo rows) {
                final List typedMaps = mapper.mapRows(rows.getRows());
                return new TypedMapsWithPagingState(typedMaps, rows.getExecutionInfo().getPagingState());
            }
        };

        final ListenableFuture futureTypedMap = asyncUtils.transformFuture(futureRows, rowsToTypedMaps);

        asyncUtils.maybeAddAsyncListeners(futureTypedMap, asyncListeners);

        return futureTypedMap;
    }

    protected AchillesFuture asyncGetFirstInternal(FutureCallback... asyncListeners) {
        log.debug("Get first result for native query '{}' asynchronously", nativeStatementWrapper.getStatement());
        final ListenableFuture resultSetFuture = daoContext.execute(nativeStatementWrapper);
        final ListenableFuture> futureRows = asyncUtils.transformFuture(resultSetFuture, RESULTSET_TO_ROWS);

        Function, TypedMap> rowsToTypedMap = new Function, TypedMap>() {
            @Override
            public TypedMap apply(List rows) {
                List result = mapper.mapRows(rows);
                if (result.isEmpty()) {
                    return null;
                } else {
                    return result.get(0);
                }
            }
        };
        final ListenableFuture futureTypedMap = asyncUtils.transformFuture(futureRows, rowsToTypedMap);

        asyncUtils.maybeAddAsyncListeners(futureTypedMap, asyncListeners);

        return asyncUtils.buildInterruptible(futureTypedMap);
    }

    protected AchillesFuture asyncExecuteInternal(FutureCallback... asyncListeners) {
        log.debug("Execute native query '{}' asynchronously", nativeStatementWrapper.getStatement());
        final ListenableFuture resultSetFuture = daoContext.execute(nativeStatementWrapper);
        final ListenableFuture futureEmpty = asyncUtils.transformFutureToEmpty(resultSetFuture, executorService);

        asyncUtils.maybeAddAsyncListeners(futureEmpty, asyncListeners);
        return asyncUtils.buildInterruptible(futureEmpty);
    }

    protected AchillesFuture> asyncIterator(Optional fetchSizeO, FutureCallback... asyncListeners) {
        final Statement statement = nativeStatementWrapper.getStatement();
        log.debug("Execute native query {} and return iterator", statement);

        if (fetchSizeO.isPresent()) {
            statement.setFetchSize(fetchSizeO.get());
        }

        final ListenableFuture futureResultSet = daoContext.execute(nativeStatementWrapper);

        final Function> toTypedMap = new Function>() {
            @Override
            public Iterator apply(ResultSet resultSet) {
                return new TypedMapIterator(resultSet.iterator());
            }
        };

        final ListenableFuture> futureTypedMapIterator = asyncUtils.transformFuture(futureResultSet, toTypedMap, executorService);
        asyncUtils.maybeAddAsyncListeners(futureTypedMapIterator, asyncListeners);
        return asyncUtils.buildInterruptible(futureTypedMapIterator);
    }

    /**
     * Set paging state
     * @param pagingState paging state
     * @return this native query
     */
    public T withPagingState(PagingState pagingState) {
        pagingStateO = Optional.fromNullable(pagingState);
        return getThis();
    }

    /**
     * Set paging state as string
     * @param pagingState paging state as String
     * @return this native query
     */
    public T withPagingState(String pagingState) {
        pagingStateO = Optional.fromNullable(PagingState.fromString(pagingState));
        return getThis();
    }

    /**
     * Set paging state as byte array
     * @param pagingState paging state as byte array
     * @return this native query
     */
    public T withPagingState(byte[] pagingState) {
        pagingStateO = Optional.fromNullable(PagingState.fromBytes(pagingState));
        return getThis();
    }
}