com.basho.riak.client.DefaultRiakObject Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of riak-client Show documentation
Show all versions of riak-client Show documentation
HttpClient-based client for Riak
/*
* 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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.basho.riak.client.builders.RiakObjectBuilder;
import com.basho.riak.client.cap.VClock;
import com.basho.riak.client.convert.RiakKey;
import com.basho.riak.client.query.indexes.BinIndex;
import com.basho.riak.client.query.indexes.IntIndex;
import com.basho.riak.client.query.indexes.RiakIndexes;
import com.basho.riak.client.util.CharsetUtils;
import com.basho.riak.client.util.UnmodifiableIterator;
import java.util.HashSet;
/**
* The default implementation of {@link IRiakObject}
*
* Is as immutable as possible. Value
, content-type
, links
and user meta data
are all mutable.
* It is safe to use the instances of this class from multiple threads.
*
*
* Due to the large number of arguments to the constructor the *best* way to create instances is with a {@link RiakObjectBuilder}.
*
*
* @author russell
*/
public class DefaultRiakObject implements IRiakObject {
/**
* The default content type assigned when persisted in Riak if non is provided.
*/
public static String DEFAULT_CONTENT_TYPE = "application/octet-stream";
private final String bucket;
@RiakKey private final String key;
private final VClock vclock;
private final String vtag;
private final long lastModified;
private final boolean isDeleted;
private final Object linksLock = new Object();
private final Collection links;
private final Object userMetaLock = new Object();
private final Map userMeta;
private final RiakIndexes indexes;
private volatile String contentType;
private volatile byte[] value;
/**
* Large number of arguments due to largely immutable nature. Use {@link RiakObjectBuilder} to create instances.
*
* @param bucket the bucket the object is stored in
* @param key the key it is stored under
* @param vclock the vclock, if available
* @param vtag the version tag, if relevant
* @param lastModified the last modified date from Riak (if relevant)
* @param contentType the content-type of the value
* @param value a byte[] of the data payload to store in Riak. Note: this is cloned on construction of this instance.
* @param links the List of {@link RiakLink}s from this object. Note: this is copied.
* @param userMeta the {@link Map} of user meta data to store/stored with this object. Note: this is copied.
* @param indexes the {@link RiakIndexes} for this object. These will be copied to a new {@link RiakIndexes}
*/
public DefaultRiakObject(String bucket, String key, VClock vclock, String vtag, final Date lastModified,
String contentType, byte[] value, final Collection links, final Map userMeta,
final RiakIndexes indexes, final boolean isDeleted) {
if (bucket == null) {
throw new IllegalArgumentException("Bucket cannot be null");
}
this.bucket = bucket;
this.key = key;
this.isDeleted = isDeleted;
this.vclock = vclock;
this.vtag = vtag;
this.lastModified = lastModified == null ? 0 : lastModified.getTime();
safeSetContentType(contentType);
this.value = copy(value);
this.links = copy(links);
this.userMeta = copy(userMeta);
this.indexes = RiakIndexes.from(indexes);
}
/**
* Copy the value array.
* @param value
* @return a clone of value or null (if value was null)
*/
private byte[] copy(byte[] value) {
if (value == null) {
return null;
} else {
return value.clone();
}
}
/**
* Copy the user meta data
* @param userMeta
* @return a copy of user meta data or any empty map
*/
private Map copy(Map userMeta) {
Map copy;
if (userMeta == null) {
copy = new HashMap();
} else {
copy = new HashMap(userMeta);
}
return copy;
}
/**
* Copy the Collection
* @param the type
* @param l the collection to copy
* @return a copy of the collection (or an empty collection if l
is null)
*/
private Collection copy(Collection l) {
Collection copy;
if (l == null) {
copy = new ArrayList();
} else {
copy = new ArrayList(l);
}
return copy;
}
/**
* If content-type is null set the content-type to DEFAULT_CONTENT_TYPE
* @param contentType
*/
private void safeSetContentType(String contentType) {
if (contentType == null) {
this.contentType = DEFAULT_CONTENT_TYPE;
} else {
this.contentType = contentType;
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getBucket()
*/
public String getBucket() {
return bucket;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getVClock()
*/
public VClock getVClock() {
return vclock;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getKey()
*/
public String getKey() {
return key;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getVtag()
*/
public String getVtag() {
return vtag;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getLastModified()
*/
public Date getLastModified() {
Date lastModified = null;
if (this.lastModified != 0) {
lastModified = new Date(this.lastModified);
}
return lastModified;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getContentType()
*/
public String getContentType() {
return contentType;
}
/**
* NOTE: a copy is returned. Mutating the return value will not effect the state of this instance.
* @see com.basho.riak.client.IRiakObject#getMeta()
*/
public Map getMeta() {
return new HashMap(userMeta);
}
/**
* @return a *cop* of this object's data payload.
* @see com.basho.riak.client.IRiakObject#getValue()
*/
public byte[] getValue() {
return copy(value);
}
// mutate
/**
* Note: Copies the value.
*
* @param a byte[] to store in Riak.
*/
public void setValue(byte[] value) {
this.value = copy(value);
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#setValue(java.lang.String)
*/
public void setValue(String value) {
this.value = CharsetUtils.utf8StringToBytes(value);
this.contentType = CharsetUtils.addUtf8Charset(contentType);
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#setContentType(java.lang.String)
*/
public void setContentType(String contentType) {
safeSetContentType(contentType);
}
/**
* an {@link UnmodifiableIterator} view on the RiakLinks
*/
public Iterator iterator() {
return new UnmodifiableIterator(getLinks().iterator());
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#addLink(com.basho.riak.client.RiakLink)
*/
public IRiakObject addLink(RiakLink link) {
if (link != null) {
synchronized (linksLock) {
links.add(link);
}
}
return this;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#removeLink(com.basho.riak.client.RiakLink)
*/
public IRiakObject removeLink(final RiakLink link) {
synchronized (linksLock) {
this.links.remove(link);
}
return this;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#hasLinks()
*/
public boolean hasLinks() {
synchronized (linksLock) {
return !links.isEmpty();
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#numLinks()
*/
public int numLinks() {
synchronized (linksLock) {
return links.size();
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getLinks()
*/
public List getLinks() {
synchronized (linksLock) {
return new ArrayList(links);
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#hasLink(com.basho.riak.client.RiakLink)
*/
public boolean hasLink(final RiakLink riakLink) {
synchronized (linksLock) {
return links.contains(riakLink);
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#addUsermeta(java.lang.String, java.lang.String)
*/
public IRiakObject addUsermeta(String key, String value) {
synchronized (userMetaLock) {
userMeta.put(key, value);
}
return this;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#hasUsermeta()
*/
public boolean hasUsermeta() {
synchronized (userMetaLock) {
return !userMeta.isEmpty();
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#hasUsermeta(java.lang.String)
*/
public boolean hasUsermeta(String key) {
synchronized (userMetaLock) {
return userMeta.containsKey(key);
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getUsermeta(java.lang.String)
*/
public String getUsermeta(String key) {
synchronized (userMetaLock) {
return userMeta.get(key);
}
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#removeUsermeta(java.lang.String)
*/
public IRiakObject removeUsermeta(String key) {
synchronized (userMetaLock) {
userMeta.remove(key);
}
return this;
}
/**
* return an unmodifiable view of the user meta entries. Attempts to modify
* will throw UnsupportedOperationException.
*/
public Iterable> userMetaEntries() {
return Collections.unmodifiableCollection(userMeta.entrySet());
}
/*
* (non-Javadoc)
*
* @see com.basho.riak.newapi.RiakObject#getVClockAsString()
*/
public String getVClockAsString() {
if (vclock != null) {
return vclock.asString();
}
return null;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#getValueAsString()
*/
public String getValueAsString() {
return CharsetUtils.asString(value, CharsetUtils.getCharset(contentType));
}
/*
* (non-Javadoc)
*
* @see com.basho.riak.client.IRiakObject#allBinIndexes()
*/
public Map> allBinIndexes() {
return indexes.getBinIndexes();
}
/*
* (non-Javadoc)
*
* @see com.basho.riak.client.IRiakObject#getBinIndex(java.lang.String)
*/
public Set getBinIndex(String name) {
return indexes.getBinIndex(name);
}
/*
* @depricated
* @see #allIntIndexesV2()
*/
@Deprecated
public Map> allIntIndexes() {
Map> longMap = indexes.getIntIndexes();
Map> intMap = new HashMap>(longMap.size());
for (Map.Entry> e : longMap.entrySet()) {
Set longSet = e.getValue();
Set intSet = new HashSet(longSet.size());
for (Long l : longSet) {
intSet.add(l.intValue());
}
intMap.put(e.getKey(), intSet);
}
return intMap;
}
/*
* (non-Javadoc)
*
* @see #allIntIndexesV2(java.lang.String)
*/
public Map> allIntIndexesV2() {
return indexes.getIntIndexes();
}
/*
* @depricated
* @see #getIntIndexV2(java.lang.String)
*/
@Deprecated
public Set getIntIndex(String name) {
Set longSet = indexes.getIntIndex(name);
Set intSet = new HashSet(longSet.size());
for (Long l : longSet) {
intSet.add(l.intValue());
}
return intSet;
}
/*
* (non-Javadoc)
*
* @see com.basho.riak.client.IRiakObject#getIntIndexV2(java.lang.String)
*/
public Set getIntIndexV2(String name) {
return indexes.getIntIndex(name);
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#addIndex(java.lang.String, java.lang.String)
*/
public IRiakObject addIndex(String index, String value) {
indexes.add(index, value);
return this;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#addIndex(java.lang.String, long)
*/
public IRiakObject addIndex(String index, long value) {
indexes.add(index, value);
return this;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#removeIndex(com.basho.riak.client.query.indexes.BinIndex)
*/
public IRiakObject removeBinIndex(String index) {
indexes.removeAll(BinIndex.named(index));
return this;
}
/* (non-Javadoc)
* @see com.basho.riak.client.IRiakObject#removeIndex(com.basho.riak.client.query.indexes.IntIndex)
*/
public IRiakObject removeIntIndex(String index) {
indexes.removeAll(IntIndex.named(index));
return this;
}
@Override
public boolean isDeleted() {
return this.isDeleted;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy