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

net.oneandone.troilus.WriteQueryDataImpl Maven / Gradle / Ivy

There is a newer version: 0.18
Show newest version
/*
 * Copyright 1&1 Internet AG, https://github.com/1and1/
 * 
 * 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 net.oneandone.troilus;


import static com.datastax.driver.core.querybuilder.QueryBuilder.addAll;
import static com.datastax.driver.core.querybuilder.QueryBuilder.appendAll;
import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
import static com.datastax.driver.core.querybuilder.QueryBuilder.discardAll;
import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
import static com.datastax.driver.core.querybuilder.QueryBuilder.prependAll;
import static com.datastax.driver.core.querybuilder.QueryBuilder.putAll;
import static com.datastax.driver.core.querybuilder.QueryBuilder.removeAll;
import static com.datastax.driver.core.querybuilder.QueryBuilder.set;
import static com.datastax.driver.core.querybuilder.QueryBuilder.ttl;
import static com.datastax.driver.core.querybuilder.QueryBuilder.update;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import net.oneandone.troilus.java7.interceptor.WriteQueryData;

import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.Clause;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;


 
/**
 * write query data implementation
 *
 */
class WriteQueryDataImpl implements WriteQueryData {

    private final ImmutableMap keys;
    private final ImmutableList whereConditions;
    
    private final ImmutableMap> valuesToMutate;
    private final ImmutableMap> setValuesToAdd;
    private final ImmutableMap> setValuesToRemove;
    private final ImmutableMap> listValuesToAppend;
    private final ImmutableMap> listValuesToPrepend;
    private final ImmutableMap> listValuesToRemove;
    private final ImmutableMap>> mapValuesToMutate;
    
    private final ImmutableList onlyIfConditions;
    private final Boolean ifNotExists;
    
    

    /**
     * constructor
     */
    WriteQueryDataImpl() {
        this(ImmutableMap.of(),
             ImmutableList.of(),
             ImmutableMap.>of(),
             ImmutableMap.>of(),
             ImmutableMap.>of(),
             ImmutableMap.>of(),
             ImmutableMap.>of(),
             ImmutableMap.>of(),
             ImmutableMap.>>of(),
             ImmutableList.of(),
             null);
    }

    
    private WriteQueryDataImpl(ImmutableMap keys, 
                               ImmutableList whereConditions, 
                               ImmutableMap> valuesToMutate, 
                               ImmutableMap> setValuesToAdd,
                               ImmutableMap> setValuesToRemove,
                               ImmutableMap> listValuesToAppend, 
                               ImmutableMap> listValuesToPrepend,
                               ImmutableMap> listValuesToRemove,
                               ImmutableMap>> mapValuesToMutate,
                               ImmutableList onlyIfConditions,
                               Boolean ifNotExists) {
        this.keys = keys;
        this.whereConditions = whereConditions;
        this.valuesToMutate = valuesToMutate;
        this.setValuesToAdd = setValuesToAdd;
        this.setValuesToRemove = setValuesToRemove;
        this.listValuesToAppend = listValuesToAppend;
        this.listValuesToPrepend = listValuesToPrepend;
        this.listValuesToRemove = listValuesToRemove;
        this.mapValuesToMutate = mapValuesToMutate;
        this.onlyIfConditions = onlyIfConditions;
        this.ifNotExists = ifNotExists;
    }
    
    
    @Override
    public WriteQueryDataImpl keys(ImmutableMap keys) {
        return new WriteQueryDataImpl(keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
    
    @Override
    public WriteQueryDataImpl whereConditions(ImmutableList whereConditions) {
        return new WriteQueryDataImpl(this.keys, 
                                      whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
    
    @Override
    public WriteQueryDataImpl valuesToMutate(ImmutableMap> valuesToMutate) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
 
    @Override
    public WriteQueryDataImpl setValuesToAdd(ImmutableMap> setValuesToAdd) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
    
    @Override
    public WriteQueryDataImpl setValuesToRemove(ImmutableMap> setValuesToRemove) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
 
    @Override
    public WriteQueryDataImpl listValuesToAppend(ImmutableMap> listValuesToAppend) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
   
    @Override
    public WriteQueryDataImpl listValuesToPrepend(ImmutableMap> listValuesToPrepend) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }
 
    @Override
    public WriteQueryDataImpl listValuesToRemove(ImmutableMap> listValuesToRemove) {
         return new WriteQueryDataImpl(this.keys, 
                                       this.whereConditions,
                                       this.valuesToMutate, 
                                       this.setValuesToAdd,
                                       this.setValuesToRemove,
                                       this.listValuesToAppend,
                                       this.listValuesToPrepend,
                                       listValuesToRemove,
                                       this.mapValuesToMutate,
                                       this.onlyIfConditions,
                                       this.ifNotExists);
    }
 
    @Override
    public WriteQueryDataImpl mapValuesToMutate(ImmutableMap>> mapValuesToMutate) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      mapValuesToMutate,
                                      this.onlyIfConditions,
                                      this.ifNotExists);
    }

    @Override
    public WriteQueryDataImpl onlyIfConditions(ImmutableList onlyIfConditions) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      onlyIfConditions,
                                      this.ifNotExists);
    }

    @Override
    public WriteQueryDataImpl ifNotExists(Boolean ifNotExists) {
        return new WriteQueryDataImpl(this.keys, 
                                      this.whereConditions,
                                      this.valuesToMutate, 
                                      this.setValuesToAdd,
                                      this.setValuesToRemove,
                                      this.listValuesToAppend,
                                      this.listValuesToPrepend,
                                      this.listValuesToRemove,
                                      this.mapValuesToMutate,
                                      this.onlyIfConditions,
                                      ifNotExists);
    }
    
    
    @Override
    public ImmutableMap getKeys() {
        return keys;
    }

    @Override
    public  boolean hasKey(ColumnName name) {
        return hasKey(name.getName());
    }
    
    @Override
    public boolean hasKey(String name) {
        return getKeys().containsKey(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  T getKey(ColumnName name) {
        return (T) getKey(name.getName());
    }

    @Override
    public Object getKey(String name) {
        return getKeys().get(name);
    }
    
    @Override
    public ImmutableList getWhereConditions() {
        return whereConditions;
    }

    @Override
    public ImmutableMap> getValuesToMutate() {
        return valuesToMutate;
    }

    @Override
    public  boolean hasValueToMutate(ColumnName name) {
        return hasValueToMutate(name.getName());
    }
    
    @Override
    public boolean hasValueToMutate(String name) {
        return getValuesToMutate().containsKey(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  T getValueToMutate(ColumnName name) {
        return (T) getValueToMutate(name.getName());
    }
    
    @Override
    public Object getValueToMutate(String name) {
        Optional optional = getValuesToMutate().get(name);
        if (optional == null) {
            return null;
        } else {
            return optional.orNull();
        }
    }
    
    @Override
    public ImmutableMap> getSetValuesToAdd() {
        return setValuesToAdd;
    }
    
    @Override
    public  boolean hasSetValuesToAdd(ColumnName> name) {
        return hasSetValuesToAdd(name.getName());
    }
    
    @Override
    public boolean hasSetValuesToAdd(String name) {
        return setValuesToAdd.containsKey(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableSet getSetValuesToAdd(ColumnName> name) {
        return (ImmutableSet) getSetValuesToAdd(name.getName());
    }
    
    @Override
    public ImmutableSet getSetValuesToAdd(String name) {
        ImmutableSet values = setValuesToAdd.get(name);
        if (values == null) {
            return ImmutableSet.of();
        } else {
            return values;
        }
    }    
    
    @Override
    public  boolean hasSetValuesToAddOrSet(ColumnName> name) {
        return hasSetValuesToAddOrSet(name.getName());
    }
    
    @Override
    public boolean hasSetValuesToAddOrSet(String name) {
        return hasSetValuesToAdd(name) || hasValueToMutate(name);
    }

    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableSet getSetValuesToAddOrSet(ColumnName> name) {
        return (ImmutableSet) getSetValuesToAddOrSet(name.getName());
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public ImmutableSet getSetValuesToAddOrSet(String name) {
        ImmutableSet valuesToAdd = getSetValuesToAdd(name);
        ImmutableSet valuesToMutate = (ImmutableSet) getValueToMutate(name);
        if (valuesToMutate == null) {
            return valuesToAdd;
        } else {
            return ImmutableSet.builder().addAll(valuesToAdd).addAll(valuesToMutate).build();
        }
    }

    @Override
    public ImmutableMap> getSetValuesToRemove() {
        return setValuesToRemove;
    }
    
    @Override
    public  boolean hasSetValuesToRemove(ColumnName> name) {
        return hasSetValuesToRemove(name.getName());
    }
    
    @Override
    public boolean hasSetValuesToRemove(String name) {
        return setValuesToRemove.containsKey(name);
    }

    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableSet getSetValuesToRemove(ColumnName> name) {
        return (ImmutableSet) getSetValuesToRemove(name.getName());
    }
    
    @Override
    public ImmutableSet getSetValuesToRemove(String name) {
        ImmutableSet values = setValuesToRemove.get(name);
        if (values == null) {
            return ImmutableSet.of();
        } else {
            return values;
        }
    }
    
    
    @Override
    public ImmutableMap> getListValuesToAppend() {
        return listValuesToAppend;
    }
    
    @Override
    public  boolean hasListValuesToAppend(ColumnName> name) {
        return hasListValuesToAppend(name.getName());
    }
    
    @Override
    public boolean hasListValuesToAppend(String name) {
        return listValuesToAppend.containsKey(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableList getListValuesToAppend(ColumnName> name) {
        return (ImmutableList) getListValuesToAppend(name.getName());
    }
    
    @Override
    public ImmutableList getListValuesToAppend(String name) {
        ImmutableList values = listValuesToAppend.get(name);
        if (values == null) {
            return ImmutableList.of();
        } else  {
            return values;
        }
    }
    
    @Override
    public ImmutableMap> getListValuesToPrepend() {
        return listValuesToPrepend;
    }
    
    @Override
    public  boolean hasListValuesToPrepend(ColumnName> name) {
        return hasListValuesToPrepend(name.getName());
    }
    
    @Override
    public boolean hasListValuesToPrepend(String name) {
        return listValuesToPrepend.containsKey(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableList getListValuesToPrepend(ColumnName> name) {
        return (ImmutableList) getListValuesToPrepend(name.getName());
    }
    
    @Override
    public ImmutableList getListValuesToPrepend(String name) {
        ImmutableList values = listValuesToPrepend.get(name);
        if (values == null) {
            return ImmutableList.of();
        } else {
            return values;
        }
    }
    
    @Override
    public  boolean hasListValuesToAddOrSet(ColumnName> name) {
        return hasListValuesToAddOrSet(name.getName());
    }
    
    @Override
    public boolean hasListValuesToAddOrSet(String name) {
        return hasListValuesToAppend(name) || hasListValuesToPrepend(name) || hasValueToMutate(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableList getListValuesToAddOrSet(ColumnName> name) {
        return (ImmutableList) getListValuesToAddOrSet(name.getName());
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public ImmutableList getListValuesToAddOrSet(String name) {
        ImmutableList valuesToAppend = getListValuesToAppend(name);
        ImmutableList valuesToPrepend = getListValuesToPrepend(name);
        ImmutableList valuesToMutate = (ImmutableList) getValueToMutate(name);
        
        if (valuesToMutate == null) {
            return ImmutableList.builder().addAll(valuesToAppend).addAll(valuesToPrepend).build();
        } else {
            return ImmutableList.builder().addAll(valuesToAppend).addAll(valuesToPrepend).addAll(valuesToMutate).build();
        }
    }
    
    @Override
    public ImmutableMap> getListValuesToRemove() {
        return listValuesToRemove;
    }
    
    @Override
    public  boolean hasListValuesToRemove(ColumnName> name) {
        return hasListValuesToRemove(name.getName());
    }
    
    @Override
    public boolean hasListValuesToRemove(String name) {
        return listValuesToRemove.containsKey(name);
    }

    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableList getListValuesToRemove(ColumnName> name) {
        return (ImmutableList) getListValuesToRemove(name.getName());
    }
    
    @Override
    public ImmutableList getListValuesToRemove(String name) {
        ImmutableList values = listValuesToRemove.get(name);
        if (values == null) {
            return ImmutableList.of();
        } else {
            return values;
        }
    }
    
    @Override
    public ImmutableMap>> getMapValuesToMutate() {
        return mapValuesToMutate;
    }
    
    @Override
    public  boolean hasMapValuesToMutate(ColumnName> name) {
        return hasMapValuesToMutate(name.getName());
    }
    
    @Override
    public boolean hasMapValuesToMutate(String name) {
        return mapValuesToMutate.containsKey(name);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public  ImmutableMap> getMapValuesToMutate(ColumnName> name) {
        Map> result = Maps.newHashMap();
        for (Entry> entry : getMapValuesToMutate(name.getName()).entrySet()) {
            result.put((T) entry.getKey(), (Optional) entry.getValue()); 
        }
        return ImmutableMap.copyOf(result);
    }
    
    @Override
    public ImmutableMap> getMapValuesToMutate(String name) {
        ImmutableMap> values = mapValuesToMutate.get(name);
        if (values == null) {
            return ImmutableMap.of();
        } else {
            return values;
        }
    }

    @Override
    public ImmutableList getOnlyIfConditions() {
        return onlyIfConditions;
    }
    
    @Override
    public Boolean getIfNotExits() {
        return ifNotExists;
    }
    
    
  
    
    /**
     * @param data   the query data
     * @param ctx    the context
     * @return the query data as statement
     */
    static ListenableFuture toStatementAsync(WriteQueryData data, Context ctx) {
        
        if (isKeyOnlyStatement(data)) {
            Map> valuesToMUtate = Maps.newHashMap();
            for (Entry entry : data.getKeys().entrySet()) {
                valuesToMUtate.put(entry.getKey(), Optional.of(entry.getValue()));
            }
            
            data = data.valuesToMutate(ImmutableMap.copyOf(valuesToMUtate)).keys(ImmutableMap.of());
        }
        
        
        if ((data.getIfNotExits() != null) || (data.getKeys().isEmpty() && data.getWhereConditions().isEmpty())) {
            return toInsertStatementAsync(data, ctx);
        } else {
            return toUpdateStatementAsync(data, ctx);
        }
    }
    
    
    private static ListenableFuture toInsertStatementAsync(WriteQueryData data,Context ctx) {
        Insert insert = insertInto(ctx.getDbSession().getTablename());
        
        List values = Lists.newArrayList();
        
        for(Entry> entry : data.getValuesToMutate().entrySet()) {
            insert.value(entry.getKey(), bindMarker());  
            values.add(ctx.toStatementValue(entry.getKey(), entry.getValue().orNull())); 
        }
        
        if (data.getIfNotExits() != null) {
            insert.ifNotExists();
            if (ctx.getSerialConsistencyLevel() != null) {
                insert.setSerialConsistencyLevel(ctx.getSerialConsistencyLevel());
            }
        }

        if (ctx.getTtlSec() != null) {
            insert.using(ttl(bindMarker()));  
            values.add((Integer) ctx.getTtlSec());
        }

        
        ListenableFuture preparedStatementFuture = ctx.getDbSession().prepareAsync(insert);
        return ctx.getDbSession().bindAsync(preparedStatementFuture, values.toArray());
    }
    
    
    
    
    private static ListenableFuture toUpdateStatementAsync(WriteQueryData data, Context ctx) {
        com.datastax.driver.core.querybuilder.Update update = update(ctx.getDbSession().getTablename());
        
        
        for (Clause onlyIfCondition : data.getOnlyIfConditions()) {
            update.onlyIf(onlyIfCondition);
        }

        
        // key-based update
        if (data.getWhereConditions().isEmpty()) {
            List values = Lists.newArrayList();
            
            
            if (ctx.getTtlSec() != null) {
                update.using(QueryBuilder.ttl(bindMarker())); 
                values.add((Integer) ctx.getTtlSec()); 
            }
            
            for (Entry> entry : data.getValuesToMutate().entrySet()) {
                update.with(set(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue().orNull()));
            }

            for (Entry> entry : data.getSetValuesToAdd().entrySet()) {
                update.with(addAll(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue()));
            }
            for(Entry> entry : data.getSetValuesToRemove().entrySet()) {
                update.with(removeAll(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue()));
            }

            for (Entry> entry : data.getListValuesToPrepend().entrySet()) {
                update.with(prependAll(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue()));
            } 
            for (Entry> entry : data.getListValuesToAppend().entrySet()) {
                update.with(appendAll(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue()));
            } 
            for (Entry> entry : data.getListValuesToRemove().entrySet()) {
                update.with(discardAll(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue()));
            } 

            for(Entry>> entry : data.getMapValuesToMutate().entrySet()) {
                update.with(putAll(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue()));
            }
            
            
            for(Entry entry : data.getKeys().entrySet()) {
                update.where(eq(entry.getKey(), bindMarker())); 
                values.add(toStatementValue(ctx, entry.getKey(), entry.getValue())); 
            }
            
   
            
            ListenableFuture preparedStatementFuture = ctx.getDbSession().prepareAsync(update);
            return ctx.getDbSession().bindAsync(preparedStatementFuture, values.toArray());
            
        // where condition-based update
        } else {
            for (Entry> entry : data.getValuesToMutate().entrySet()) {
                update.with(set(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue().orNull())));
            }

            for (Entry> entry : data.getSetValuesToAdd().entrySet()) {
                update.with(addAll(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue())));
            }
            for (Entry> entry : data.getSetValuesToRemove().entrySet()) {
                update.with(removeAll(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue())));
            }
            
            for (Entry> entry : data.getListValuesToPrepend().entrySet()) {
                update.with(prependAll(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue())));
            } 
            for (Entry> entry : data.getListValuesToAppend().entrySet()) {
                update.with(appendAll(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue())));
            } 
            for (Entry> entry : data.getListValuesToRemove().entrySet()) {
                update.with(discardAll(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue())));
            } 

            for(Entry>> entry : data.getMapValuesToMutate().entrySet()) {
                update.with(putAll(entry.getKey(), toStatementValue(ctx, entry.getKey(), entry.getValue())));
            }

            if (ctx.getTtlSec() != null) {
                update.using(QueryBuilder.ttl(ctx.getTtlSec().intValue()));
            }

            for (Clause whereCondition : data.getWhereConditions()) {
                update.where(whereCondition);
            }
                        
            return Futures.immediateFuture(update);
        }
    }
    
    
    private static boolean isKeyOnlyStatement(WriteQueryData data) {
        return data.getListValuesToAppend().isEmpty() && 
               data.getListValuesToPrepend().isEmpty() &&
               data.getListValuesToRemove().isEmpty() &&
               data.getMapValuesToMutate().isEmpty() &&
               data.getSetValuesToAdd().isEmpty() &&
               data.getSetValuesToRemove().isEmpty() &&
               data.getValuesToMutate().isEmpty();
    }
    

    private static Object toStatementValue(Context ctx, String name, Object value) {
        return ctx.toStatementValue(name, value);
    }
    
    
    private static ImmutableSet toStatementValue(Context ctx, String name, ImmutableSet values) {
        return ImmutableSet.copyOf(toStatementValue(ctx, name, ImmutableList.copyOf(values))); 
    }

    
    private static ImmutableList toStatementValue(Context ctx, String name, ImmutableList values) {
        
        List result = Lists.newArrayList();

        for (Object value : values) {
            result.add(toStatementValue(ctx, name, value));
        }
        
        return ImmutableList.copyOf(result);
    }
  
    
    private static Map toStatementValue(Context ctx, String name, ImmutableMap> map) {
        Map m = Maps.newHashMap();
        for (Entry> entry : map.entrySet()) {
            m.put(toStatementValue(ctx, name, toStatementValue(ctx, name, entry.getKey())), toStatementValue(ctx, name, entry.getValue().orNull()));
        }
        return m;
    } 
}