/*
* 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.jbrisbin.riak.pbc;
import static com.google.protobuf.ByteString.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.basho.riak.client.IRiakObject;
import com.basho.riak.client.RiakLink;
import com.basho.riak.client.cap.VClock;
import com.basho.riak.pbc.RPB;
import com.google.protobuf.ByteString;
/**
* @author Jon Brisbin <jon@jbrisbin.com>
*/
public class RiakObject implements IRiakObject, Buildable<RPB.RpbContent> {
private final Object userMetaDataLock = new Object();
private String bucket;
private String key;
private VClock vclock;
private ByteString vtag;
private String contentType;
private String contentEncoding;
private String charset;
private List<RiakLink> links = Collections.synchronizedList(new ArrayList<RiakLink>());
private Map<String, String> userMetaData = new LinkedHashMap<String, String>();
private Integer lastModified;
private Integer lastModifiedUsec;
private ByteString value;
private RPB.RpbContent.Builder builder = RPB.RpbContent.newBuilder();
public RiakObject() {
}
public RiakObject(String bucket, String key, String contentType, String value) {
this.bucket = bucket;
this.key = key;
setContentType(contentType);
setValue(value);
}
public RiakObject(String bucket, String key, String contentType, byte[] value) {
this.bucket = bucket;
this.key = key;
setContentType(contentType);
setValue(value);
}
public RiakObject(String bucket, String key, byte[] value) {
this.bucket = bucket;
this.key = key;
setValue(value);
}
@Override public String getBucket() {
return bucket;
}
@Override public byte[] getValue() {
return (null != value ? value.toByteArray() : null);
}
@Override public String getValueAsString() {
return (null != value ? value.toStringUtf8() : null);
}
@Override public VClock getVClock() {
return vclock;
}
@Override public String getVClockAsString() {
return (null != vclock ? vclock.asString() : null);
}
@Override public String getKey() {
return key;
}
@Override public String getVtag() {
return (null != vtag ? vtag.toStringUtf8() : null);
}
@Override public Date getLastModified() {
Date d = null;
if (lastModified != null && lastModifiedUsec != null) {
long t = (lastModified * 1000L) + (lastModifiedUsec / 100L);
d = new Date(t);
}
return d;
}
@Override public String getContentType() {
return contentType;
}
public String getContentEncoding() {
return contentEncoding;
}
public String getCharset() {
return charset;
}
@Override public List<RiakLink> getLinks() {
return links;
}
@Override public boolean hasLinks() {
return !links.isEmpty();
}
@Override public int numLinks() {
return links.size();
}
@Override public boolean hasLink(RiakLink riakLink) {
return links.contains(riakLink);
}
@Override public Map<String, String> getMeta() {
return userMetaData;
}
@Override public boolean hasUsermeta() {
return !userMetaData.isEmpty();
}
@Override public boolean hasUsermeta(String key) {
return userMetaData.containsKey(key);
}
@Override public String getUsermeta(String key) {
return userMetaData.get(key);
}
@Override public Iterable<Map.Entry<String, String>> userMetaEntries() {
return userMetaData.entrySet();
}
public void setValue(ByteString byteString) {
this.value = byteString;
this.builder.setValue(byteString);
}
@Override public void setValue(byte[] bytes) {
this.value = copyFrom(bytes);
this.builder.setValue(this.value);
}
@Override public void setValue(String val) {
if (null != val) {
this.value = copyFromUtf8(val);
this.builder.setValue(this.value);
}
}
@Override public void setContentType(String contentType) {
this.contentType = contentType;
this.builder.setContentType(copyFromUtf8(contentType));
}
public void setContentType(ByteString contentType) {
this.contentType = contentType.toStringUtf8();
this.builder.setContentType(contentType);
}
public void setContentEncoding(String contentEncoding) {
this.contentEncoding = contentEncoding;
this.builder.setContentEncoding(copyFromUtf8(contentEncoding));
}
public void setContentEncoding(ByteString contentEncoding) {
this.contentEncoding = contentEncoding.toStringUtf8();
this.builder.setContentEncoding(contentEncoding);
}
public void setCharset(String charset) {
this.charset = charset;
builder.setCharset(copyFromUtf8(charset));
}
public void setVtag(ByteString vtag) {
this.vtag = vtag;
builder.setVtag(vtag);
}
public void setLastModified(Integer lastModified) {
this.lastModified = lastModified;
}
public void setLastModifiedUsec(Integer lastModifiedUsec) {
this.lastModifiedUsec = lastModifiedUsec;
}
@Override public IRiakObject addLink(RiakLink riakLink) {
links.add(riakLink);
return this;
}
@Override public IRiakObject removeLink(RiakLink riakLink) {
links.remove(riakLink);
return this;
}
@Override public IRiakObject addUsermeta(String key, String val) {
userMetaData.put(key, val);
return this;
}
@Override public IRiakObject removeUsermeta(String key) {
userMetaData.remove(key);
return this;
}
@Override public Iterator<RiakLink> iterator() {
return links.iterator();
}
@Override public RPB.RpbContent build() {
if (null != lastModified)
builder.setLastMod(lastModified);
if (null != lastModifiedUsec)
builder.setLastModUsecs(lastModifiedUsec);
for (Map.Entry<String, String> mentry : userMetaData.entrySet()) {
String mkey = mentry.getKey();
String mval = mentry.getValue();
RPB.RpbPair.Builder pairBuilder = RPB.RpbPair.newBuilder();
pairBuilder.setKey(copyFromUtf8(mkey));
pairBuilder.setValue(copyFromUtf8(mval));
builder.addUsermeta(pairBuilder);
}
for (RiakLink riakLink : links) {
RPB.RpbLink.Builder linkBuilder = RPB.RpbLink.newBuilder();
linkBuilder.setBucket(copyFromUtf8(riakLink.getBucket()));
linkBuilder.setKey(copyFromUtf8(riakLink.getKey()));
linkBuilder.setTag(copyFromUtf8(riakLink.getTag()));
builder.addLinks(linkBuilder);
}
return builder.build();
}
@Override public String toString() {
return "RiakObject{" +
"userMetaDataLock=" + userMetaDataLock +
", bucket=" + bucket +
", key=" + key +
", vclock=" + vclock +
", vtag=" + vtag +
", contentType='" + contentType + '\'' +
", contentEncoding='" + contentEncoding + '\'' +
", charset='" + charset + '\'' +
", links=" + links +
", userMetaData=" + userMetaData +
", lastModified=" + lastModified +
", lastModifiedUsec=" + lastModifiedUsec +
", value=" + value +
", builder=" + builder +
'}';
}
}