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

com.basho.riak.client.convert.JSONConverter 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.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