package com.alvazan.orm.api.z8spi.meta; import java.util.Arrays; import com.alvazan.orm.api.base.anno.NoSqlDiscriminatorColumn; import com.alvazan.orm.api.z8spi.Row; import com.alvazan.orm.api.z8spi.conv.StandardConverters; import com.alvazan.orm.api.z8spi.conv.StorageTypeEnum; @SuppressWarnings({ "rawtypes" }) @NoSqlDiscriminatorColumn(value="id") public class DboColumnIdMeta extends DboColumnMeta { protected String columnValueType; protected transient byte[] cachedKeyPrefix; public byte[] formVirtRowKey(byte[] byteVal) { if(!owner.isVirtualCf()) return byteVal; else if(cachedKeyPrefix == null) { initCachedKey(); } byte[] newKey = new byte[cachedKeyPrefix.length+byteVal.length]; for(int i = 0; i < cachedKeyPrefix.length; i++) { newKey[i] = cachedKeyPrefix[i]; } for(int i = 0; i < byteVal.length; i++) { newKey[i+cachedKeyPrefix.length] = byteVal[i]; } return newKey; } public byte[] unformVirtRowKey(byte[] virtKey) { if(!owner.isVirtualCf()) return virtKey; else if(cachedKeyPrefix == null) initCachedKey(); int virtKeyLen = virtKey[0] & 0xFF; byte[] realKey = new byte[virtKey.length-1-virtKeyLen]; for(int i = 0; i < realKey.length;i++) { realKey[i] = virtKey[1+virtKeyLen+i]; } return realKey; } public static String fetchTableNameIfVirtual(byte[] virtKey) { int tableLen = virtKey[0] & 0xFF; byte[] bytesName = Arrays.copyOfRange(virtKey, 1, tableLen+1); String s = new String(bytesName); return s; } private void initCachedKey() { String cf = owner.getColumnFamily(); byte[] asBytes = StandardConverters.convertToBytes(cf); int len = asBytes.length; byte prefix = (byte) len; cachedKeyPrefix = new byte[asBytes.length+1]; cachedKeyPrefix[0] = prefix; for(int i = 0; i < asBytes.length; i++) { cachedKeyPrefix[i+1] = asBytes[i]; } } @Override public String getIndexTableName() { return getStorageType().getIndexTableName(); } public Class getClassType() { return ConverterUtil.classForName(columnValueType); } public StorageTypeEnum getStorageType() { Class fieldType = getClassType(); return ConverterUtil.getStorageType(fieldType); } public void setup(DboTableMeta owner, String colName, Class valuesType, boolean isIndexed) { if(owner.getColumnFamily() == null) throw new IllegalArgumentException("The owner passed in must have a non-null column family name"); else if(colName == null) throw new IllegalStateException("colName parameter must not be null"); byte[] asBytes = StandardConverters.convertToBytes(owner.getColumnFamily()); if(asBytes.length > 255) throw new IllegalArgumentException("Column family names converted using utf8 must be less than 255 bytes. your col family="+owner.getColumnFamily()+" is too long"); this.owner = owner; setColumnName(colName); //NOTE: We don't call super.setup here BECAUSE super.setup calls owner.addColumn and this is the row key //and so we call owner.setRowKeyMeta here instead owner.setRowKeyMeta(this); id = owner.getColumnFamily()+":"+getColumnName(); Class newType = ConverterUtil.translateType(valuesType); this.columnValueType = newType.getName(); this.isIndexed = isIndexed; } @Override public void translateToColumn(InfoForIndex<TypedRow> info) { TypedRow entity = info.getEntity(); RowToPersist row = info.getRow(); Object id = entity.getRowKey(); if(id == null) throw new IllegalArgumentException("rowKey cannot be null"); byte[] byteVal = convertToStorage2(id); byte[] virtualKey = formVirtRowKey(byteVal); row.setKeys(byteVal, virtualKey); addIndexInfo(info, id, byteVal); //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 } public void translateFromColumn(Row row, TypedRow entity) { byte[] virtualKey = row.getKey(); byte[] notVirtKey = unformVirtRowKey(virtualKey); Object pk = convertFromStorage2(notVirtKey); entity.setRowKey(pk); } @Override public boolean isPartitionedByThisColumn() { return false; } @Override public String fetchColumnValueAsString(TypedRow row) { throw new UnsupportedOperationException("only used by partitioning and can't partition a primary key column....that is kind of useless"); } }