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

com.basho.riak.client.bucket.DefaultBucket Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/*
 * This file is provided to you 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.bucket;

import static com.basho.riak.client.convert.KeyUtil.getKey;

import java.io.IOException;
import java.util.Collection;

import com.basho.riak.client.DefaultRiakClient;
import com.basho.riak.client.DefaultRiakObject;
import com.basho.riak.client.IRiakObject;
import com.basho.riak.client.RiakException;
import com.basho.riak.client.builders.RiakObjectBuilder;
import com.basho.riak.client.cap.ClobberMutation;
import com.basho.riak.client.cap.DefaultResolver;
import com.basho.riak.client.cap.Mutation;
import com.basho.riak.client.cap.Quorum;
import com.basho.riak.client.cap.Retrier;
import com.basho.riak.client.cap.UnresolvedConflictException;
import com.basho.riak.client.convert.Converter;
import com.basho.riak.client.convert.JSONConverter;
import com.basho.riak.client.convert.NoKeySpecifedException;
import com.basho.riak.client.convert.PassThroughConverter;
import com.basho.riak.client.convert.RiakKey;
import com.basho.riak.client.http.util.Constants;
import com.basho.riak.client.operations.DeleteObject;
import com.basho.riak.client.operations.FetchObject;
import com.basho.riak.client.operations.MultiFetchObject;
import com.basho.riak.client.operations.RiakOperation;
import com.basho.riak.client.operations.StoreObject;
import com.basho.riak.client.query.functions.NamedErlangFunction;
import com.basho.riak.client.query.functions.NamedFunction;
import com.basho.riak.client.query.indexes.FetchIndex;
import com.basho.riak.client.query.indexes.RiakIndex;
import com.basho.riak.client.raw.RawClient;
import com.basho.riak.client.util.CharsetUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Default implementation of {@link Bucket} for creating {@link RiakOperation}s
 * on k/v data and accessing {@link BucketProperties}.
 * 
 * 

* Obtain a {@link DefaultBucket} from {@link FetchBucket} or * {@link WriteBucket} operations from * {@link DefaultRiakClient#fetchBucket(String)}, * {@link DefaultRiakClient#createBucket(String)} *

*

*

 *   final String bucketName = UUID.randomUUID().toString();
 *   
 *   Bucket b = client.createBucket(bucketName).execute();
 *   //store something
 *   IRiakObject o = b.store("k", "v").execute();
 *   //fetch it back
 *   IRiakObject fetched = b.fetch("k").execute();
 *   // now update that riak object
 *   b.store("k", "my new value").execute();
 *   //fetch it back again
 *   fetched = b.fetch("k").execute();
 *   //delete it
 *   b.delete("k").execute();
 * 
*

* All operations created by instances of this class are configured with the * {@link Retrier} and {@link RawClient} passed at construction. *

* * @author russell * @see DomainBucket * @see RiakBucket */ public class DefaultBucket implements Bucket { private final String name; private final BucketProperties properties; private final RawClient client; private final Retrier retrier; /** * All {@link RiakOperation}s created by this instance will use the * {@link RawClient} and {@link Retrier} provided here. * * @param name this bucket's name * @param properties the {@link BucketProperties} for this bucket * @param client a {@link RawClient} to use for all {@link RiakOperation}s * @param retrier a {@link Retrier} to use for all {@link RiakOperation}s */ protected DefaultBucket(String name, final BucketProperties properties, final RawClient client, final Retrier retrier) { this.name = name; this.properties = properties; this.client = client; this.retrier = retrier; } // BUCKET PROPS /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.Bucket#getName() */ public String getName() { return name; } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getAllowSiblings() */ public Boolean getAllowSiblings() { return properties.getAllowSiblings(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getLastWriteWins() */ public Boolean getLastWriteWins() { return properties.getLastWriteWins(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getNVal() */ public Integer getNVal() { return properties.getNVal(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getBackend() */ public String getBackend() { return properties.getBackend(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getSmallVClock() */ public Integer getSmallVClock() { return properties.getSmallVClock(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getBigVClock() */ public Integer getBigVClock() { return properties.getBigVClock(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getYoungVClock() */ public Long getYoungVClock() { return properties.getYoungVClock(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getOldVClock() */ public Long getOldVClock() { return properties.getOldVClock(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getPrecommitHooks() */ public Collection getPrecommitHooks() { return properties.getPrecommitHooks(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getPostcommitHooks() */ public Collection getPostcommitHooks() { return properties.getPostcommitHooks(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getR() */ public Quorum getR() { return properties.getR(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getW() */ public Quorum getW() { return properties.getW(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getRW() */ public Quorum getRW() { return properties.getRW(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getDW() */ public Quorum getDW() { return properties.getDW(); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.BucketProperties#getPR() */ public Quorum getPR() { return properties.getPR(); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.BucketProperties#getPW() */ public Quorum getPW() { return properties.getPW(); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.BucketProperties#isBasicQuorum() */ public Boolean getBasicQuorum() { return properties.getBasicQuorum(); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.BucketProperties#isNotFoundOK() */ public Boolean getNotFoundOK() { return properties.getNotFoundOK(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getChashKeyFunction() */ public NamedErlangFunction getChashKeyFunction() { return properties.getChashKeyFunction(); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.BucketProperties#getLinkWalkFunction() */ public NamedErlangFunction getLinkWalkFunction() { return properties.getLinkWalkFunction(); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.BucketProperties#getSearch() */ public Boolean getSearch() { return properties.getSearch(); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.BucketProperties#isSearchEnabled() */ public boolean isSearchEnabled() { return properties.isSearchEnabled(); } // BUCKET /** * Iterate over the keys for this bucket (Expensive, are you sure?) Beware: * at present all {@link RawClient#listKeys(String)} operations return a * stream of keys. The stream is closed automatically when the iteratore is * weakly reachable. Do not retain a reference to this {@link Iterable} * after you have used it. * * @see RawClient#listKeys(String) */ public Iterable keys() throws RiakException { try { return client.listKeys(name); } catch (IOException e) { throw new RiakException(e); } } /** * Convenience method to create a RiakObject with a payload of * application/octect-stream *

* For example, to get a new {@link IRiakObject} into Riak.

     * IRiakObject myNewObject = bucket.store("k", myByteArray)
     *                              .w(2)  // tunable CAP write quorum
     *                              .returnBody(true) // return the IRiakObject from the store
     *                              .execute(); // perform the operation.
     * 
*

*

* Creates a {@link StoreObject} operation configured with a * {@link Mutation} that copies value and * {@link DefaultRiakObject#DEFAULT_CONTENT_TYPE} over the any existing * value at key or creates a new {@link DefaultRiakObject} with * value and {@link DefaultRiakObject#DEFAULT_CONTENT_TYPE}. *

*

* The {@link StoreObject} is configured with the {@link DefaultResolver} * which means the presence of siblings triggers a * {@link UnresolvedConflictException} *

*

* The {@link StoreObject} is configured with a {@link Converter} that * simply returns what it is given (IE does no conversion). *

* * @param key * the key to store the object under. * @param value * a byte[] of the objects value. * @return a {@link StoreObject} configured to store value at * key on execute(). * @see StoreObject */ public StoreObject store(final String key, final byte[] value) { return new StoreObject(client, name, key, retrier).withMutator(new Mutation() { public IRiakObject apply(IRiakObject original) { if (original == null) { return RiakObjectBuilder.newBuilder(name, key).withValue(value).withContentType(Constants.CTYPE_OCTET_STREAM).build(); } else { original.setValue(value); return original; } } }).withResolver(new DefaultResolver()).withConverter(new PassThroughConverter()); } /** * Convenience methods will create an {@link IRiakObject} with * value as the data payload and * text/plain:charset=utf-8 as the contentType *

* For example, to get a new {@link IRiakObject} into Riak.

     * IRiakObject myNewObject = bucket.store("k", "myValue")
     *                              .w(2)  // tunable CAP write quorum
     *                              .returnBody(true) // return the IRiakObject from the store
     *                              .execute(); // perform the operation.
     * 
*

*

* Creates a {@link StoreObject} operation configured with a * {@link Mutation} that copies value and * {@link Constants#CTYPE_TEXT_UTF8} over the any existing * value at key or creates a new {@link DefaultRiakObject} with * value and {@link Constants#CTYPE_TEXT_UTF8}. *

*

* The {@link StoreObject} is configured with the {@link DefaultResolver} * which means the presence of siblings triggers a * {@link UnresolvedConflictException} *

*

* The {@link StoreObject} is configured with a {@link Converter} that * simply returns what it is given (IE does no conversion). *

* * @param key * the key to store the object under. * @param value * a String of the data to store * @return a {@link StoreObject} configured to store value at * key on execute(). * @see StoreObject */ public StoreObject store(final String key, final String value) { final Mutation m = new Mutation() { public IRiakObject apply(IRiakObject original) { if (original == null) { return RiakObjectBuilder.newBuilder(name, key).withValue(value).withContentType(Constants.CTYPE_TEXT_UTF8).build(); } else { original.setValue(CharsetUtils.utf8StringToBytes(value)); original.setContentType(Constants.CTYPE_TEXT_UTF8); return original; } } }; return store(key, CharsetUtils.utf8StringToBytes(value)).withMutator(m); } /** * Store an instance of T in Riak. Depends on the * {@link Converter} provided to {@link StoreObject} to convert * o from T to {@link IRiakObject}. *

* T must have a field annotated with {@link RiakKey} as the * Key to store this data under. *

* *

* Creates a {@link StoreObject} operation configured with the * {@link JSONConverter} the {@link ClobberMutation} and * {@link DefaultResolver}. *

* * @param * the Type of o * @param o * the data to store * @return a {@link StoreObject} configured to store o at the * {@link RiakKey} annotated key on * execute(). * @see StoreObject * @see DomainBucket */ public StoreObject store(final T o) { @SuppressWarnings("unchecked") Class clazz = (Class) o.getClass(); final String key = getKey(o); if (key == null) { throw new NoKeySpecifedException(o); } Converter converter = getDefaultConverter(clazz); return new StoreObject(client, name, key, retrier) .withConverter(converter) .withMutator(new ClobberMutation(o)) .withResolver(new DefaultResolver()); } private Converter getDefaultConverter(Class clazz) { return getDefaultConverter(clazz, null); } @SuppressWarnings("unchecked") private Converter getDefaultConverter(Class clazz, String key) { Converter converter; if (IRiakObject.class.isAssignableFrom(clazz)) { converter = (Converter) new PassThroughConverter(); } else { if (key != null) { converter = new JSONConverter(clazz, name, key); } else { converter = new JSONConverter(clazz, name); } } return converter; } /** * Store an instance of T in Riak. Depends on the * {@link Converter} provided to {@link StoreObject} to convert * o from T to {@link IRiakObject}. * *

* Creates a {@link StoreObject} operation configured with the * {@link JSONConverter} the {@link ClobberMutation} and * {@link DefaultResolver}. *

* * @param * the Type of o * @param o * the data to store * @return a {@link StoreObject} configured to store o at the * {@link RiakKey} annotated key on * execute(). * @see StoreObject * @see DomainBucket */ public StoreObject store(final String key, final T o) { @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); Converter converter = getDefaultConverter(clazz, key); return new StoreObject(client, name, key, retrier). withConverter(converter) .withMutator(new ClobberMutation(o)).withResolver(new DefaultResolver()); } /** * Creates a {@link FetchObject} operation that returns the data at * o's annotated {@link RiakKey} field as an instance of type * T on execute(). *

* Creates a {@link FetchObject} operation configured with the * {@link JSONConverter} and * {@link DefaultResolver}. *

* * @param * the Type to return * @param o * an instance ot T that has the key annotated with * {@link RiakKey} * @return a {@link FetchObject} * @see FetchObject */ public FetchObject fetch(T o) { @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); final String key = getKey(o); if (key == null) { throw new NoKeySpecifedException(o); } Converter converter = getDefaultConverter(clazz); return new FetchObject(client, name, key, retrier) .withConverter(converter) .withResolver(new DefaultResolver()); } /** * Creates a {@link FetchObject} operation that returns the data at * key as an instance of type T on * execute(). * *

* Creates a {@link FetchObject} operation configured with the * {@link JSONConverter} and * {@link DefaultResolver}. *

* * @param * the Type to return * @param key * the key under which the data is stored * @param type * the Class of the type to return * @return a {@link FetchObject} * @see FetchObject */ public FetchObject fetch(final String key, final Class type) { Converter converter = getDefaultConverter(type, key); return new FetchObject(client, name, key, retrier) .withConverter(converter) .withResolver(new DefaultResolver()); } /** * Creates a {@link FetchObject} that returns the data at key * as an {@link IRiakObject} on execute(). * *

* Creates a {@link FetchObject} with the {@link DefaultResolver} and a {@link Converter} * that does nothing to the {@link IRiakObject}. *

* * @param key the key * @return a {@link FetchObject} * @see FetchObject */ public FetchObject fetch(String key) { return new FetchObject(client, name, key, retrier) .withResolver(new DefaultResolver()) .withConverter(new PassThroughConverter()); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.Object) */ public DeleteObject delete(T o) { final String key = getKey(o); if (key == null) { throw new NoKeySpecifedException(o); } return new DeleteObject(client, name, key, retrier); } /* * (non-Javadoc) * * @see com.basho.riak.newapi.bucket.Bucket#delete(java.lang.String) */ public DeleteObject delete(String key) { return new DeleteObject(client, name, key, retrier); } /* (non-Javadoc) * @see com.basho.riak.client.bucket.Bucket#fetchIndex(com.basho.riak.client.query.indexes.RiakIndex) */ public FetchIndex fetchIndex(RiakIndex index) { return new FetchIndex(client, name, index, retrier); } /** * (non-Javadoc) * @see com.basho.riak.client.bucket.Bucket#multiFetch(java.lang.String[]) */ public MultiFetchObject multiFetch(String[] keys) { return new MultiFetchObject(client, name, Arrays.asList(keys), retrier) .withResolver(new DefaultResolver()) .withConverter(new PassThroughConverter()); } /** * (non-Javadoc) * @see com.basho.riak.client.bucket.Bucket#multiFetch(java.util.List, java.lang.Class) */ public MultiFetchObject multiFetch(List keys, Class type) { Converter converter = getDefaultConverter(type, keys.get(0)); return new MultiFetchObject(client, name, keys, retrier) .withConverter(converter) .withResolver(new DefaultResolver()); } /** * (non-Javadoc) * @see com.basho.riak.client.bucket.Bucket#multiFetch(java.util.List) */ public MultiFetchObject multiFetch(List objs) { T o = objs.get(0); @SuppressWarnings("unchecked") final Class clazz = (Class) o.getClass(); List keyList = new ArrayList(objs.size()); for (T obj : objs) { String key = getKey(obj); if (key == null) { throw new NoKeySpecifedException(o); } keyList.add(key); } Converter converter = getDefaultConverter(clazz); return new MultiFetchObject(client, name, keyList, retrier) .withConverter(converter) .withResolver(new DefaultResolver()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy