Package com.basho.riak.client.api.commands.kv

Source Code of com.basho.riak.client.api.commands.kv.StoreValue$Response

/*
* Copyright 2013 Basho Technologies Inc
*
* 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.basho.riak.client.api.commands.kv;

import com.basho.riak.client.api.cap.Quorum;
import com.basho.riak.client.api.cap.VClock;
import com.basho.riak.client.api.convert.Converter;
import com.basho.riak.client.api.convert.Converter.OrmExtracted;
import com.basho.riak.client.api.convert.ConverterFactory;
import com.basho.riak.client.core.RiakCluster;
import com.basho.riak.client.core.operations.StoreOperation;
import com.basho.riak.client.api.RiakCommand;
import com.basho.riak.client.core.RiakFuture;
import com.basho.riak.client.api.commands.CoreFutureAdapter;
import com.basho.riak.client.api.commands.RiakOption;
import com.basho.riak.client.core.util.BinaryValue;

import java.util.HashMap;
import java.util.Map;

import com.basho.riak.client.core.query.Location;
import com.basho.riak.client.core.query.Namespace;
import com.fasterxml.jackson.core.type.TypeReference;

/*
* @author Dave Rusek <drusek at basho dot com>
* @since 2.0
*/
public final class StoreValue extends RiakCommand<StoreValue.Response, Location>
{
    private final Namespace namespace;
    private final BinaryValue key;
    private final Map<Option<?>, Object> options =
      new HashMap<Option<?>, Object>();
    private final Object value;
    private final TypeReference<?> typeReference;
    private final VClock vclock;
   
    StoreValue(Builder builder)
    {
        this.options.putAll(builder.options);
        this.namespace = builder.namespace;
        this.key = builder.key;
        this.value = builder.value;
        this.typeReference = builder.typeReference;
        this.vclock = builder.vclock;
    }

   
    @SuppressWarnings("unchecked")
    @Override
    protected RiakFuture<Response, Location> executeAsync(RiakCluster cluster)
    {
        Converter converter;
       
        if (typeReference == null)
        {
            converter = ConverterFactory.getInstance().getConverter(value.getClass());
        }
        else
        {
            converter = ConverterFactory.getInstance().getConverter(typeReference);
        }
       
        final OrmExtracted orm = converter.fromDomain(value, namespace, key);
       
        // If there's no vector clock in the object, use one possibly given via
        // the builder.
        if (orm.getRiakObject().getVClock() == null)
        {
            orm.getRiakObject().setVClock(vclock);
        }
       
        RiakFuture<StoreOperation.Response, Location> coreFuture =
            cluster.execute(buildCoreOperation(orm));
       
        CoreFutureAdapter<Response, Location, StoreOperation.Response, Location> future =
            new CoreFutureAdapter<Response, Location, StoreOperation.Response, Location>(coreFuture)
            {
                @Override
                protected Response convertResponse(StoreOperation.Response coreResponse)
                {
                    Namespace ns = orm.getNamespace();
                    BinaryValue key = orm.getKey();
                    if (coreResponse.hasGeneratedKey())
                    {
                        key = coreResponse.getGeneratedKey();
                    }
                   
                    Location loc = new Location(ns, key);
                   
                    return new Response.Builder()
                        .withValues(coreResponse.getObjectList())
                        .withGeneratedKey(coreResponse.getGeneratedKey())
                        .withLocation(loc) // for ORM
                        .build();
                }

                @Override
                protected Location convertQueryInfo(Location coreQueryInfo)
                {
                    return coreQueryInfo;
                }
               
            };
        coreFuture.addListener(future);
        return future;
    }
   
    private StoreOperation buildCoreOperation(OrmExtracted orm)
    {
        StoreOperation.Builder builder;
       
        if (orm.hasKey())
        {
            Location loc = new Location(orm.getNamespace(), orm.getKey());
            builder = new StoreOperation.Builder(loc);
        }
        else
        {
            builder = new StoreOperation.Builder(orm.getNamespace());
        }
       
        builder.withContent(orm.getRiakObject());
       
        for (Map.Entry<Option<?>, Object> opPair : options.entrySet())
        {

            RiakOption<?> option = opPair.getKey();

            if (option == Option.TIMEOUT)
            {
                builder.withTimeout((Integer) opPair.getValue());
            }
            else if (option == Option.RETURN_HEAD)
            {
                builder.withReturnHead((Boolean) opPair.getValue());
            }
            else if (option == Option.ASIS)
            {
                builder.withAsis((Boolean) opPair.getValue());
            }
            else if (option == Option.DW)
            {
                builder.withDw(((Quorum) opPair.getValue()).getIntValue());
            }
            else if (option == Option.IF_NONE_MATCH)
            {
                builder.withIfNoneMatch((Boolean) opPair.getValue());
            }
            else if (option == Option.IF_NOT_MODIFIED)
            {
                builder.withIfNotModified((Boolean) opPair.getValue());
            }
            else if (option == Option.N_VAL)
            {
                builder.withNVal((Integer) opPair.getValue());
            }
            else if (option == Option.PW)
            {
                builder.withPw(((Quorum) opPair.getValue()).getIntValue());
            }
            else if (option == Option.SLOPPY_QUORUM)
            {
                builder.withSloppyQuorum((Boolean) opPair.getValue());
            }
            else if (option == Option.W)
            {
                builder.withW(((Quorum) opPair.getValue()).getIntValue());
            }
            else if (option == Option.RETURN_BODY)
            {
                builder.withReturnBody((Boolean) opPair.getValue());
            }

        }

        return builder.build();
    }
   
    /**
    * Options For controlling how Riak performs the store operation.
    * <p>
    * These options can be supplied to the {@link StoreValue.Builder} to change
    * how Riak performs the operation. These override the defaults provided
    * by the bucket.
    * </p>
    * @author Dave Rusek <drusek at basho dot com>
    * @since 2.0
    * @see <a href="http://docs.basho.com/riak/latest/dev/advanced/cap-controls/">Replication Properties</a>
    */
   public final static class Option<T> extends RiakOption<T>
   {

       /**
        * Write Quorum.
        * How many replicas to write to before returning a successful response.
        */
       public static final Option<Quorum> W = new Option<Quorum>("W");
       /**
        * Durable Write Quorum.
        * How many replicas to commit to durable storage before returning a successful response.
        */
       public static final Option<Quorum> DW = new Option<Quorum>("DW");
       /**
        * Primary Write Quorum.
        * How many primary nodes must be up when the write is attempted.
        */
       public static final Option<Quorum> PW = new Option<Quorum>("PW");
       /**
        * If Not Modified.
        * Update the value only if the vclock in the supplied object matches the one in the database.
        */
       public static final Option<Boolean> IF_NOT_MODIFIED = new Option<Boolean>("IF_NOT_MODIFIED");
       /**
        * If None Match.
        * Store the value only if this bucket/key combination are not already defined.
        */
       public static final Option<Boolean> IF_NONE_MATCH = new Option<Boolean>("IF_NONE_MATCH");
       /**
        * Return Body.
        * Return the object stored in Riak. Note this will return all siblings.
        */
       public static final Option<Boolean> RETURN_BODY = new Option<Boolean>("RETURN_BODY");
       /**
        * Return Head.
        * Like {@link #RETURN_BODY} except that the value(s) in the object are blank to
        * avoid returning potentially large value(s).
        */
       public static final Option<Boolean> RETURN_HEAD = new Option<Boolean>("RETURN_HEAD");
       /**
        * Timeout.
        * Sets the server-side timeout for this operation. The default in Riak is 60 seconds.
        */
       public static final Option<Integer> TIMEOUT = new Option<Integer>("TIMEOUT");

       public static final Option<Boolean> ASIS = new Option<Boolean>("ASIS");
       public static final Option<Boolean> SLOPPY_QUORUM = new Option<Boolean>("SLOPPY_QUORUM");
       public static final Option<Integer> N_VAL = new Option<Integer>("N_VAL");


       private Option(String name)
       {
           super(name);
       }
   }

   
    public static class Response extends KvResponseBase
    {
        private final BinaryValue generatedKey;
       
        Response(Init<?> builder)
        {
            super(builder);
            this.generatedKey = builder.generatedKey;
        }

        public boolean hasGeneratedKey()
        {
            return generatedKey != null;
        }
       
        public BinaryValue getGeneratedKey()
        {
            return generatedKey;
        }
       
        /**
         * @ExcludeFromJavadoc
         */
        protected static abstract class Init<T extends Init<T>> extends KvResponseBase.Init<T>
        {
            private BinaryValue generatedKey;
           
            T withGeneratedKey(BinaryValue generatedKey)
            {
                this.generatedKey = generatedKey;
                return self();
            }
        }
       
        static class Builder extends Init<Builder>
        {

            @Override
            protected Builder self()
            {
                return this;
            }

            @Override
            Response build()
            {
                return new Response(this);
            }
        }
    }

  public static class Builder
  {

    private final Map<Option<?>, Object> options =
      new HashMap<Option<?>, Object>();
    private final Object value;
        private Namespace namespace;
        private BinaryValue key;
        private TypeReference<?> typeReference;
        private VClock vclock;

       

        public Builder(Object value)
        {
            this.value = value;
        }
       
        public Builder(Object value, TypeReference<?> typeReference)
        {
            this.value = value;
            this.typeReference = typeReference;
        }
       
    public Builder withLocation(Location location)
        {
            this.namespace = location.getNamespace();
            this.key = location.getKey();
            return this;
        }
       
        public Builder withNamespace(Namespace namespace)
        {
            this.namespace = namespace;
            return this;
        }
       
        /**
         * Set the Riak-side timeout value.
         * <p>
         * By default, riak has a 60s timeout for operations. Setting
         * this value will override that default for this operation.
         * </p>
         * @param timeout the timeout in milliseconds to be sent to riak.
         * @return a reference to this object.
         */
        public Builder withTimeout(int timeout)
        {
            withOption(Option.TIMEOUT, timeout);
            return this;
        }
       
    public <T> Builder withOption(Option<T> option, T value)
    {
      options.put(option, value);
      return this;
    }

        /**
         * Set the vector clock.
         * <p>
         * When storing core Java types ({@code HashMap},
         * {@code ArrayList},{@code String}, etc) or non-annotated POJOs this
         * method allows you to specify the vector clock retrieved from a
         * prior fetch operation.
         * </p>
         * @param vclock The vector clock to send to Riak.
         * @return a reference to this object.
         */
        public Builder withVectorClock(VClock vclock)
        {
            this.vclock = vclock;
            return this;
        }
       
    public StoreValue build()
    {
      return new StoreValue(this);
    }
  }
}
TOP

Related Classes of com.basho.riak.client.api.commands.kv.StoreValue$Response

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.