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

me.prettyprint.hom.CollectionMapperHelper Maven / Gradle / Ivy

There is a newer version: 3.0-04
Show newest version
package me.prettyprint.hom;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import me.prettyprint.cassandra.serializers.ObjectSerializer;
import me.prettyprint.hector.api.beans.HColumn;
import me.prettyprint.hom.cache.HectorObjectMapperException;

import com.google.common.base.Splitter;

public class CollectionMapperHelper {
  private ReflectionHelper reflectionHelper = new ReflectionHelper();
  private ObjectSerializer objSer = ObjectSerializer.get();

  public String createCollectionItemColName(String propName, int order) {
    return propName + ":" + order;
  }

  public CollectionItemColName parseCollectionItemColName(String colName) {
    try {
      Iterable split = Splitter.on(':').split(colName);
      Iterator iter = split.iterator();
      return new CollectionItemColName(iter.next(), Integer.parseInt(iter.next()));
    } catch (Throwable e) {
      throw new HectorObjectMapperException("exception while parsing collection item column name, "
          + colName, e);
    }
  }

  public byte[] createCollectionInfoColValue(Collection coll) {
    return String.valueOf(coll.getClass().getName() + ":" + coll.size()).getBytes();
  }

  public CollectionInfoColValue parseCollectionInfoColValue(byte[] val) {
    try {
      String tmp = new String(val);
      Iterable split = Splitter.on(':').split(tmp);
      Iterator iter = split.iterator();
      return new CollectionInfoColValue(iter.next(), Integer.parseInt(iter.next()));
    } catch (Throwable e) {
      throw new HectorObjectMapperException("exception while parsing collection info column value",
          e);
    }
  }

  @SuppressWarnings("rawtypes")
  public void instantiateCollection(Object obj, HColumn col,
      PropertyMappingDefinition md) {
    CollectionInfoColValue colValue = parseCollectionInfoColValue(col.getValue());
    try {
      // type name is Class that needs instantiating. examine for special class
      // features, like ArrayList taking a size hint in constructor
      Collection collObj;
      Class clazz = Class.forName(colValue.getCollTypeName());
      if (ArrayList.class.isAssignableFrom(clazz)) {
        Constructor cons = ArrayList.class.getConstructor(int.class);
        collObj = cons.newInstance(colValue.getSize());
      } else {
        collObj = (Collection) clazz.newInstance();
      }

      // now save collection to object
      PropertyDescriptor pd = md.getPropDesc();
      if (null == pd.getWriteMethod()) {
        throw new RuntimeException("property, " + pd.getName()
            + ", does not have a setter and therefore cannot be set");
      }

      pd.getWriteMethod().invoke(obj, collObj);
    } catch (Throwable e) {
      throw new HectorObjectMapperException("exception while instantiating Collection type, "
          + colValue.getCollTypeName(), e);
    }
  }

  @SuppressWarnings("unchecked")
  public boolean addColumnToCollection(CFMappingDef cfMapDef, Object obj, String colName,
      byte[] colValue) {
    // if can parse, then at least adheres to formatting
    CollectionItemColName collColumnName;
    try {
      collColumnName = parseCollectionItemColName(colName);
    } catch (HectorObjectMapperException e) {
      return false;
    }

    // get property from mapping def - if not there, then isn't a collection
    // (but probably a problem elsewhere)
    PropertyMappingDefinition md = cfMapDef.getPropMapByPropName(collColumnName.getPropertyName());
    if (null == md) {
      return false;
    }

    Collection coll;
    try {
      coll = (Collection) reflectionHelper.invokeGetter(obj, md);
    } catch (HectorObjectMapperException e) {
      return false;
    }

    Object value = deserializeCollectionValue(colValue);
    coll.add(value);
    return true;
  }

  public byte[] serializeCollectionValue(Object obj) {
    return objSer.toBytes(obj);
  }

  public Object deserializeCollectionValue(byte[] bytes) {
    return objSer.fromBytes(bytes);
  }

  // ------------------------------------------------

  public class CollectionItemColName {
    private String propertyName;
    private int order;

    public CollectionItemColName(String propertyName, int order) {
      this.propertyName = propertyName;
      this.order = order;
    }

    public String getPropertyName() {
      return propertyName;
    }

    public int getOrder() {
      return order;
    }

    private CollectionMapperHelper getOuterType() {
      return CollectionMapperHelper.this;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + getOuterType().hashCode();
      result = prime * result + order;
      result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      CollectionItemColName other = (CollectionItemColName) obj;
      if (!getOuterType().equals(other.getOuterType()))
        return false;
      if (order != other.order)
        return false;
      if (propertyName == null) {
        if (other.propertyName != null)
          return false;
      } else if (!propertyName.equals(other.propertyName))
        return false;
      return true;
    }

    @Override
    public String toString() {
      return "CollectionItemColName [propertyName=" + propertyName + ", order=" + order + "]";
    }
  }

  public class CollectionInfoColValue {
    private String collTypeName;
    private int size;

    public CollectionInfoColValue(String collTypeName, int size) {
      this.collTypeName = collTypeName;
      this.size = size;
    }

    public String getCollTypeName() {
      return collTypeName;
    }

    public int getSize() {
      return size;
    }

    private CollectionMapperHelper getOuterType() {
      return CollectionMapperHelper.this;
    }

    @Override
    public String toString() {
      return "CollectionInfoColValue [collTypeName=" + collTypeName + ", size=" + size + "]";
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + getOuterType().hashCode();
      result = prime * result + ((collTypeName == null) ? 0 : collTypeName.hashCode());
      result = prime * result + size;
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      CollectionInfoColValue other = (CollectionInfoColValue) obj;
      if (!getOuterType().equals(other.getOuterType()))
        return false;
      if (collTypeName == null) {
        if (other.collTypeName != null)
          return false;
      } else if (!collTypeName.equals(other.collTypeName))
        return false;
      if (size != other.size)
        return false;
      return true;
    }
  }
}