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

com.flipkart.hbaseobjectmapper.codec.BestSuitCodec Maven / Gradle / Ivy

Go to download

HBase ORM is a light-weight, thread-safe and performant library that enables: [1] object-oriented access of HBase rows (Data Access Object) with minimal code and good testability [2] reading from and/or writing to HBase tables in Hadoop MapReduce jobs

There is a newer version: 1.19
Show newest version
package com.flipkart.hbaseobjectmapper.codec;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flipkart.hbaseobjectmapper.exceptions.BadHBaseLibStateException;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * This is an implementation of {@link Codec} that:
 * 
    *
  1. uses HBase's native methods to serialize objects of data types {@link Boolean}, {@link Short}, {@link Integer}, {@link Long}, {@link Float}, {@link Double}, {@link String} and {@link BigDecimal}
  2. *
  3. uses Jackson's JSON serializer for all other data types
  4. *
  5. serializes null as null
  6. *
*

* This codec takes the following {@link com.flipkart.hbaseobjectmapper.Flag Flag}s: *

    *
  • serializeAsString: When passed, it indicates this codec to store field value in it's string representation (e.g. 560034 is serialized into a byte[] that represents the string "560034"). Note that, this flag applies only to fields of data types in point 1 above.
  • *
*/ public class BestSuitCodec implements Codec { private static final Map fromBytesMethodNames = new HashMap() { { put(Boolean.class, "toBoolean"); put(Short.class, "toShort"); put(Integer.class, "toInt"); put(Long.class, "toLong"); put(Float.class, "toFloat"); put(Double.class, "toDouble"); put(String.class, "toString"); put(BigDecimal.class, "toBigDecimal"); } }; private static final Map nativeCounterParts = new HashMap() { { put(Boolean.class, boolean.class); put(Short.class, short.class); put(Long.class, long.class); put(Integer.class, int.class); put(Float.class, float.class); put(Double.class, double.class); } }; private static final Map fromBytesMethods, toBytesMethods; private static final Map constructors; static { try { fromBytesMethods = new HashMap<>(fromBytesMethodNames.size()); toBytesMethods = new HashMap<>(fromBytesMethodNames.size()); constructors = new HashMap<>(fromBytesMethodNames.size()); Method fromBytesMethod, toBytesMethod; Constructor constructor; for (Map.Entry e : fromBytesMethodNames.entrySet()) { Class clazz = e.getKey(); String toDataTypeMethodName = e.getValue(); fromBytesMethod = Bytes.class.getDeclaredMethod(toDataTypeMethodName, byte[].class); toBytesMethod = Bytes.class.getDeclaredMethod("toBytes", nativeCounterParts.containsKey(clazz) ? nativeCounterParts.get(clazz) : clazz); constructor = clazz.getConstructor(String.class); fromBytesMethods.put(clazz, fromBytesMethod); toBytesMethods.put(clazz, toBytesMethod); constructors.put(clazz, constructor); } } catch (Exception ex) { throw new BadHBaseLibStateException(ex); } } private final ObjectMapper objectMapper; /** * Construct an object of class {@link BestSuitCodec} with custom instance of Jackson's Object Mapper * * @param objectMapper Instance of Jackson's Object Mapper */ public BestSuitCodec(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } /** * Construct an object of class {@link BestSuitCodec} */ public BestSuitCodec() { this(getObjectMapper()); } private static ObjectMapper getObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return objectMapper; } /* * @inherit */ @Override public byte[] serialize(Serializable object, Map flags) throws SerializationException { if (object == null) return null; Class clazz = object.getClass(); if (toBytesMethods.containsKey(clazz)) { boolean serializeAsString = isSerializeAsStringOn(flags); try { Method toBytesMethod = toBytesMethods.get(clazz); return serializeAsString ? Bytes.toBytes(String.valueOf(object)) : (byte[]) toBytesMethod.invoke(null, object); } catch (Exception e) { throw new SerializationException(String.format("Could not serialize value of type %s using HBase's native methods", clazz.getName()), e); } } else { try { return objectMapper.writeValueAsBytes(object); } catch (Exception e) { throw new SerializationException("Could not serialize object to JSON using Jackson", e); } } } /* * @inherit */ @Override public Serializable deserialize(byte[] bytes, Type type, Map flags) throws DeserializationException { if (bytes == null) return null; if (type instanceof Class && fromBytesMethods.containsKey(type)) { boolean serializeAsString = isSerializeAsStringOn(flags); try { Serializable fieldValue; if (serializeAsString) { Constructor constructor = constructors.get(type); fieldValue = (Serializable) constructor.newInstance(Bytes.toString(bytes)); } else { Method method = fromBytesMethods.get(type); fieldValue = (Serializable) method.invoke(null, new Object[]{bytes}); } return fieldValue; } catch (Exception e) { throw new DeserializationException("Could not deserialize byte array into an object using HBase's native methods", e); } } else { try { return objectMapper.readValue(bytes, objectMapper.constructType(type)); } catch (Exception e) { throw new DeserializationException("Could not deserialize JSON into an object using Jackson", e); } } } /* * @inherit */ @Override public boolean canDeserialize(Type type) { JavaType javaType = objectMapper.constructType(type); return objectMapper.canDeserialize(javaType); } private boolean isSerializeAsStringOn(Map flags) { return flags != null && flags.get("serializeAsString") != null && flags.get("serializeAsString").equalsIgnoreCase("true"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy