Package com.alvazan.orm.impl.meta.data

Source Code of com.alvazan.orm.impl.meta.data.MetaIdField

package com.alvazan.orm.impl.meta.data;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import javassist.util.proxy.Proxy;

import com.alvazan.orm.api.base.spi.KeyGenerator;
import com.alvazan.orm.api.z5api.NoSqlSession;
import com.alvazan.orm.api.z8spi.Row;
import com.alvazan.orm.api.z8spi.conv.Converter;
import com.alvazan.orm.api.z8spi.conv.StorageTypeEnum;
import com.alvazan.orm.api.z8spi.meta.DboColumnIdMeta;
import com.alvazan.orm.api.z8spi.meta.DboColumnMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.api.z8spi.meta.IndexData;
import com.alvazan.orm.api.z8spi.meta.InfoForIndex;
import com.alvazan.orm.api.z8spi.meta.ReflectionUtil;
import com.alvazan.orm.api.z8spi.meta.RowToPersist;
import com.alvazan.orm.impl.meta.data.collections.CacheLoadCallback;

//NOTE: T is the entity type NOT the type of the id!!!
public class MetaIdField<OWNER> extends MetaAbstractField<OWNER> {

  private Converter converter;
 
  private boolean useGenerator;
  private KeyGenerator generator;
  private Method method;
  private MetaAbstractClass<OWNER> metaClass;
  private DboColumnIdMeta metaDbo = new DboColumnIdMeta();

  public DboColumnMeta getMetaDbo() {
    return metaDbo;
  }
 
  @Override
  public String toString() {
    return "MetaField [field='" + field.getDeclaringClass().getName()+"."+field.getName()+"(field type=" +field.getType()+ ")";
  }

  public void translateFromColumn(Row row, OWNER entity, NoSqlSession session) {
    byte[] virtKey = row.getKey();
    byte[] nonVirtKey = metaDbo.unformVirtRowKey(virtKey);
    Object entityId = converter.convertFromNoSql(nonVirtKey);
    ReflectionUtil.putFieldValue(entity, field, entityId);
  }
 
  @Override
  public void translateToColumn(InfoForIndex<OWNER> info) {
    OWNER entity = info.getEntity();
    RowToPersist row = info.getRow();
   
    Object id = fillInAndFetchId(entity);
    byte[] byteVal = converter.convertToNoSql(id);
    byte[] virtualKey = metaDbo.formVirtRowKey(byteVal);
    row.setKeys(byteVal, virtualKey);
   
    StorageTypeEnum storageType = metaDbo.getStorageType();
    addIndexInfo(info, id, byteVal, storageType);
    //NOTICE: there is no call to remove because if an id is changed, it is a new entity and we only need to add index not remove since
    //the old entity was not deleted during this save....we remove from index on remove of old entity only
  }

  @Override
  public Object fetchField(Object entity) {
    throw new UnsupportedOperationException("only used for partitioning and id can't partition.  easy to implement if anyone else starts using this though, but for now unsupported");
  }

  @Override
  public String translateToString(Object fieldsValue) {
    throw new UnsupportedOperationException("only used for partitioning and id can't partition.  easy to implement if anyone else starts using this though, but for now unsupported");
  }
 
  @Override
  public void removingEntity(InfoForIndex<OWNER> info, List<IndexData> indexRemoves, byte[] pk) {
    removingThisEntity(info, indexRemoves, pk);
  }
 
  public Object fillInAndFetchId(OWNER entity) {
    Object idInEntity = ReflectionUtil.fetchFieldValue(entity, field);
    Object id = idInEntity;
    if(!useGenerator) {
      if(id == null)
        throw new IllegalArgumentException("Entity has @NoSqlEntity(usegenerator=false) but this entity has no id="+entity);
      return id;
    } else if(id != null) {
      //to make it easier on users, we now check and read in from database if they have not already
     
      //OKAY, we definitely do NOT want them setting their own id when autogeneration is used as IF you set the id on TWO entities
      //to the same id and add both of them, you end up with a corrupt index in that you have duplicates of two values pointing to
      //the same exact primary key.
//      if(!(entity instanceof NoSqlProxy))
//        throw new IllegalArgumentException("Uhm, uh, you have useGenerator=true(the default) on @NoSqlId annotation and the entity you " +
//            "passed in was NOT read from the database!!!!  You supplied " +
//            "your own id which could exist in the database...this will cause LARGE issues with indexing so we don't allow it, please don't set the id OR you" +
//            " are using a primitive for your key which is not a good idea either if you are going to use a generator(use Integer or String or Long instead)");
      return id;
    }
   
    Object newId = generator.generateNewKey(entity);
    ReflectionUtil.putFieldValue(entity, field, newId);
    return newId;
  }

  @SuppressWarnings("unchecked")
  public void setup(DboTableMeta tableMeta, IdInfo info, Field field, String columnName,  boolean isIndexed) {
    this.method = info.getIdMethod();
    this.method.setAccessible(true);
    this.useGenerator = info.isUseGenerator();
    this.generator = info.getGen();
    this.converter = info.getConverter()
    this.metaClass = info.getMetaClass();
    metaDbo.setup(tableMeta, columnName, field.getType(), isIndexed);
    super.setup(field, columnName);
  }

  public Converter getConverter() {
    return converter;
  }

  public Method getIdMethod() {
    return method;
  }

  public OWNER convertIdToProxy(NoSqlSession session, Object entityId, CacheLoadCallback cacheLoadCallback) {
    if(entityId == null)
      return null;
    OWNER proxy = createProxy(entityId, session, cacheLoadCallback);
    ReflectionUtil.putFieldValue(proxy, field, entityId);
    return proxy;
  }
 
  @SuppressWarnings("unchecked")
  private OWNER createProxy(Object entityId, NoSqlSession session, CacheLoadCallback cacheLoadCallback) {
    Class<?> subclassProxyClass = metaClass.getProxyClass();
    Proxy inst = (Proxy) ReflectionUtil.create(subclassProxyClass);
    inst.setHandler(new NoSqlProxyImpl<OWNER>(session, metaClass, entityId, cacheLoadCallback));
    return (OWNER) inst;
  }

  @Override
  protected Object unwrapIfNeeded(Object value) {
    return value; // no need to unwrap keys
  }

  @Override
  public byte[] translateValue(Object value) {
    return converter.convertToNoSql(value);
  }

  public DboColumnIdMeta getMetaIdDbo() {
    return metaDbo;
  }

  public Object translateFromBytes(byte[] val) {
    return converter.convertFromNoSql(val);
  }

  public boolean isAutoGen() {
    return useGenerator;
  }

  public byte[] convertIdToNonVirtKey(Object pk) {
    return converter.convertToNoSql(pk);
  }

  public byte[] formVirtRowKey(byte[] rowKey) {
    byte[] virtKey = metaDbo.formVirtRowKey(rowKey);
    return virtKey;
  }

  public byte[] unformVirtRowKey(byte[] virtualKey) {
    return metaDbo.unformVirtRowKey(virtualKey);
  }

}
TOP

Related Classes of com.alvazan.orm.impl.meta.data.MetaIdField

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.