com.basho.riak.client.convert.JSONConverter 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.convert;
import static com.basho.riak.client.convert.KeyUtil.getKey;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.basho.riak.client.IRiakObject;
import com.basho.riak.client.RiakLink;
import com.basho.riak.client.builders.RiakObjectBuilder;
import com.basho.riak.client.cap.VClock;
import com.basho.riak.client.http.util.Constants;
import com.basho.riak.client.query.indexes.RiakIndexes;
/**
* Converts a RiakObject's value to an instance of T. T must have a field
* annotated with {@link RiakKey} or you must construct the converter with a key to use. RiakObject's value *must* be a JSON string.
*
*
* At present user meta data and {@link RiakLink}s are not converted. This means
* they are essentially lost in translation.
*
*
* @author russell
*
*/
public class JSONConverter implements Converter {
// Object mapper per domain class is expensive, a singleton (and ThreadSafe) will do.
private static final ObjectMapper OBJECT_MAPPER= new ObjectMapper();
static {
OBJECT_MAPPER.registerModule(new RiakJacksonModule());
OBJECT_MAPPER.registerModule(new JodaModule());
}
private final Class clazz;
private final String bucket;
private final UsermetaConverter usermetaConverter;
private final RiakIndexConverter riakIndexConverter;
private final RiakLinksConverter riakLinksConverter;
private String defaultKey;
/**
* Create a JSONConverter for creating instances of clazz
from
* JSON and instances of {@link IRiakObject} with a JSON payload from
* instances of clazz
*
* @param clazz the type to convert to/from
* @param bucket the bucket
*/
public JSONConverter(Class clazz, String bucket) {
this(clazz, bucket, null);
}
/**
* Create a JSONConverter for creating instances of clazz
from
* JSON and instances of {@link IRiakObject} with a JSON payload from
* instances of clazz
*
* @param clazz the type to convert to/from
* @param bucket the bucket
* @param defaultKey
* for cases where clazz
does not have a
* {@link RiakKey} annotated field, pass the key to use in this
* conversion.
*/
public JSONConverter(Class clazz, String bucket, String defaultKey) {
this.clazz = clazz;
this.bucket = bucket;
this.defaultKey = defaultKey;
this.usermetaConverter = new UsermetaConverter();
this.riakIndexConverter = new RiakIndexConverter();
this.riakLinksConverter = new RiakLinksConverter();
}
/**
* Converts domainObject
to a JSON string and sets that as the
* payload of a {@link IRiakObject}. Also set the content-type
* to application/json;charset=UTF-8
*
* @param domainObject
* to be converted
* @param vclock
* the vector clock from Riak
*/
public IRiakObject fromDomain(T domainObject, VClock vclock) throws ConversionException {
try {
String key = getKey(domainObject, this.defaultKey);
final byte[] value = OBJECT_MAPPER.writeValueAsBytes(domainObject);
Map usermetaData = usermetaConverter.getUsermetaData(domainObject);
RiakIndexes indexes = riakIndexConverter.getIndexes(domainObject);
Collection links = riakLinksConverter.getLinks(domainObject);
return RiakObjectBuilder.newBuilder(bucket, key)
.withValue(value)
.withVClock(vclock)
.withUsermeta(usermetaData)
.withIndexes(indexes)
.withLinks(links)
.withContentType(Constants.CTYPE_JSON_UTF8)
.build();
} catch (JsonProcessingException e) {
throw new ConversionException(e);
} catch (IOException e) {
throw new ConversionException(e);
}
}
/**
* Converts the value
of riakObject
to an instance
* of T
.
*
* @param riakObject
* the {@link IRiakObject} to convert to instance of
* T
. NOTE: riakObject.getValue()
must be a
* JSON string. The charset from
* riakObject.getContentType()
is used.
*/
public T toDomain(final IRiakObject riakObject) throws ConversionException {
if (riakObject == null) {
return null;
} else if (riakObject.isDeleted()) {
try {
final T domainObject = clazz.newInstance();
TombstoneUtil.setTombstone(domainObject, true);
VClockUtil.setVClock(domainObject, riakObject.getVClock());
KeyUtil.setKey(domainObject, riakObject.getKey());
return domainObject;
} catch (InstantiationException ex) {
throw new ConversionException("POJO does not provide no-arg constructor",ex);
} catch (IllegalAccessException ex) {
throw new ConversionException(ex);
}
} else {
try {
final T domainObject = OBJECT_MAPPER.readValue(riakObject.getValue(), clazz);
KeyUtil.setKey(domainObject, riakObject.getKey());
VClockUtil.setVClock(domainObject, riakObject.getVClock());
usermetaConverter.populateUsermeta(riakObject.getMeta(), domainObject);
riakIndexConverter.populateIndexes(new RiakIndexes(riakObject.allBinIndexes(), riakObject.allIntIndexesV2()), domainObject);
riakLinksConverter.populateLinks(riakObject.getLinks(), domainObject);
return domainObject;
} catch (JsonProcessingException e) {
throw new ConversionException(e);
} catch (IOException e) {
throw new ConversionException(e);
}
}
}
/**
* Returns the {@link ObjectMapper} being used.
* This is a convenience method to allow changing its behavior.
* @return The Jackson ObjectMapper
*/
public static ObjectMapper getObjectMapper() {
return OBJECT_MAPPER;
}
/**
* Convenient method to register a Jackson module into the singleton Object mapper used by domain objects.
* @param jacksonModule Module to register.
*/
public static void registerJacksonModule(final Module jacksonModule) {
OBJECT_MAPPER.registerModule(jacksonModule);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy