Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.impetus.client.cassandra.datahandler.CassandraDataHandlerBase Maven / Gradle / Ivy
/**
* Copyright 2012 Impetus Infotech.
*
* Licensed 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.impetus.client.cassandra.datahandler;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.persistence.PersistenceException;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EmbeddableType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.PluralAttribute;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.ListType;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.SetType;
import org.apache.cassandra.db.marshal.TypeParser;
import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.serializers.ListSerializer;
import org.apache.cassandra.serializers.MapSerializer;
import org.apache.cassandra.serializers.SetSerializer;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.serializers.UTF8Serializer;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.CounterColumn;
import org.apache.cassandra.thrift.CounterSuperColumn;
import org.apache.cassandra.thrift.CqlMetadata;
import org.apache.cassandra.thrift.SuperColumn;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.impetus.client.cassandra.CassandraClientBase;
import com.impetus.client.cassandra.common.CassandraConstants;
import com.impetus.client.cassandra.schemamanager.CassandraDataTranslator;
import com.impetus.client.cassandra.thrift.ThriftDataResultHelper;
import com.impetus.client.cassandra.thrift.ThriftRow;
import com.impetus.kundera.Constants;
import com.impetus.kundera.KunderaException;
import com.impetus.kundera.cache.ElementCollectionCacheManager;
import com.impetus.kundera.client.EnhanceEntity;
import com.impetus.kundera.db.DataRow;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.MetadataUtils;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.EntityMetadata.Type;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.metadata.model.type.AbstractManagedType;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.property.PropertyAccessException;
import com.impetus.kundera.property.PropertyAccessor;
import com.impetus.kundera.property.PropertyAccessorFactory;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.property.accessor.LongAccessor;
import com.impetus.kundera.utils.KunderaCoreUtils;
import com.impetus.kundera.utils.TimestampGenerator;
/**
* Base class for all Cassandra Data Handlers.
*
* @author amresh.singh
*/
public abstract class CassandraDataHandlerBase
{
/** The log. */
private static Logger log = LoggerFactory.getLogger(CassandraDataHandlerBase.class);
/** The thrift translator. */
protected final ThriftDataResultHelper thriftTranslator = new ThriftDataResultHelper();
/** The client base. */
private final CassandraClientBase clientBase;
/** The kundera metadata. */
protected final KunderaMetadata kunderaMetadata;
/** The generator. */
protected final TimestampGenerator generator;
/**
* Instantiates a new cassandra data handler base.
*
* @param clientBase
* the client base
* @param kunderaMetadata
* the kundera metadata
* @param generator
* the generator
*/
public CassandraDataHandlerBase(final CassandraClientBase clientBase, final KunderaMetadata kunderaMetadata,
final TimestampGenerator generator)
{
this.generator = generator;
this.clientBase = clientBase;
this.kunderaMetadata = kunderaMetadata;
}
/**
* From thrift row.
*
* @param
* the element type
* @param clazz
* the clazz
* @param m
* the m
* @param tr
* the cr
* @return the e
* @throws Exception
* the exception
*/
public E fromThriftRow(Class clazz, EntityMetadata m, DataRow tr) throws Exception
{
// Instantiate a new instance
E e = null;
// Set row-key. Note:
// Get a name->field map for super-columns
Map columnNameToFieldMap = new HashMap();
Map superColumnNameToFieldMap = new HashMap();
MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap, superColumnNameToFieldMap,
kunderaMetadata);
Collection embeddedCollection = null;
Field embeddedCollectionField = null;
for (SuperColumn sc : tr.getColumns())
{
if (e == null)
{
// Instantiate a new instance
e = clazz.newInstance();
// Set row-key.
PropertyAccessorHelper.setId(e, m, tr.getId());
}
String scName = PropertyAccessorFactory.STRING.fromBytes(String.class, sc.getName());
String scNamePrefix = null;
if (scName.indexOf(Constants.EMBEDDED_COLUMN_NAME_DELIMITER) != -1)
{
scNamePrefix = MetadataUtils.getEmbeddedCollectionPrefix(scName);
embeddedCollectionField = superColumnNameToFieldMap.get(scNamePrefix);
embeddedCollection = MetadataUtils.getEmbeddedCollectionInstance(embeddedCollectionField);
Object embeddedObject = populateEmbeddedObject(sc, m);
embeddedCollection.add(embeddedObject);
PropertyAccessorHelper.set(e, embeddedCollectionField, embeddedCollection);
}
else
{
boolean intoRelations = false;
if (scName.equals(Constants.FOREIGN_KEY_EMBEDDED_COLUMN_NAME))
{
intoRelations = true;
}
for (Column column : sc.getColumns())
{
if (column != null)
{
String name = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
byte[] value = column.getValue();
if (value == null)
{
continue;
}
if (intoRelations)
{
String foreignKeys = PropertyAccessorFactory.STRING.fromBytes(String.class, value);
Set keys = MetadataUtils.deserializeKeys(foreignKeys);
}
else
{
// set value of the field in the bean
Field field = columnNameToFieldMap.get(name);
Object embeddedObject = PropertyAccessorHelper.getObject(e, scName);
PropertyAccessorHelper.set(embeddedObject, field, value);
}
}
}
}
}
if (log.isInfoEnabled())
{
log.info("Returning entity {} for class {}", e, clazz);
}
return e;
}
/**
* From thrift row.
*
* @param clazz
* the clazz
* @param m
* the m
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param consistencyLevel
* the consistency level
* @param rowIds
* the row ids
* @return the list
* @throws Exception
* the exception
*/
public List fromThriftRow(Class> clazz, EntityMetadata m, List relationNames, boolean isWrapReq,
ConsistencyLevel consistencyLevel, Object... rowIds) throws Exception
{
List entities = new ArrayList();
if (rowIds != null)
{
for (Object rowKey : rowIds)
{
Object e = fromThriftRow(clazz, m, rowKey, relationNames, isWrapReq, consistencyLevel);
if (e != null)
{
entities.add(e);
}
}
}
return entities;
}
/**
* From thrift row.
*
* @param clazz
* the clazz
* @param m
* the m
* @param rowKey
* the row key
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param consistencyLevel
* the consistency level
* @return the object
* @throws Exception
* the exception
*/
public abstract Object fromThriftRow(Class> clazz, EntityMetadata m, Object rowKey, List relationNames,
boolean isWrapReq, ConsistencyLevel consistencyLevel) throws Exception;
/**
* Populate embedded object.
*
* @param sc
* the sc
* @param m
* the m
* @return the object
* @throws Exception
* the exception
*/
private Object populateEmbeddedObject(SuperColumn sc, EntityMetadata m) throws Exception
{
Field embeddedCollectionField = null;
Object embeddedObject = null;
String scName = PropertyAccessorFactory.STRING.fromBytes(String.class, sc.getName());
String scNamePrefix = null;
// Get a name->field map for super-columns
Map columnNameToFieldMap = new HashMap();
Map superColumnNameToFieldMap = new HashMap();
MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap, superColumnNameToFieldMap,
kunderaMetadata);
// If this super column is variable in number (name#sequence format)
if (scName.indexOf(Constants.EMBEDDED_COLUMN_NAME_DELIMITER) != -1)
{
StringTokenizer st = new StringTokenizer(scName, Constants.EMBEDDED_COLUMN_NAME_DELIMITER);
if (st.hasMoreTokens())
{
scNamePrefix = st.nextToken();
}
embeddedCollectionField = superColumnNameToFieldMap.get(scNamePrefix);
Class> embeddedClass = PropertyAccessorHelper.getGenericClass(embeddedCollectionField);
// must have a default no-argument constructor
try
{
embeddedClass.getConstructor();
}
catch (NoSuchMethodException nsme)
{
throw new PersistenceException(embeddedClass.getName()
+ " is @Embeddable and must have a default no-argument constructor.");
}
embeddedObject = embeddedClass.newInstance();
for (Column column : sc.getColumns())
{
String name = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
byte[] value = column.getValue();
if (value == null)
{
continue;
}
Field columnField = columnNameToFieldMap.get(name);
PropertyAccessorHelper.set(embeddedObject, columnField, value);
}
}
else
{
Field superColumnField = superColumnNameToFieldMap.get(scName);
Class superColumnClass = superColumnField.getType();
embeddedObject = superColumnClass.newInstance();
for (Column column : sc.getColumns())
{
String name = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
byte[] value = column.getValue();
if (value == null)
{
continue;
}
// set value of the field in the bean
Field columnField = columnNameToFieldMap.get(name);
PropertyAccessorHelper.set(embeddedObject, columnField, value);
}
}
return embeddedObject;
}
/**
* Helper method to convert @Entity to ThriftRow.
*
* @param e
* the e
* @param id
* the id
* @param m
* the m
* @param columnFamily
* the colmun family
* @param columnTTLs
* TODO
* @return the base data accessor. thrift row
* @throws Exception
* the exception
*/
public Collection toThriftRow(Object e, Object id, EntityMetadata m, String columnFamily,
Object columnTTLs) throws Exception
{
// timestamp to use in thrift column objects
long timestamp = generator.getTimestamp();
// Add super columns to thrift row
return onColumnOrSuperColumnThriftRow(/* tr, */m, e, id, timestamp, columnTTLs);
}
/**
* Gets the thrift row.
*
* @param id
* the id
* @param columnFamily
* the column family
* @param thriftRows
* the thrift rows
* @return the thrift row
*/
private ThriftRow getThriftRow(Object id, String columnFamily, Map thriftRows)
{
ThriftRow tr = thriftRows.get(columnFamily);
if (tr == null)
{
tr = new ThriftRow();
tr.setColumnFamilyName(columnFamily); // column-family name
tr.setId(id); // Id
thriftRows.put(columnFamily, tr);
}
return tr;
}
/**
* To index thrift row.
*
* @param e
* the e
* @param m
* the m
* @param columnFamily
* the column family
* @return the list
*/
public List toIndexThriftRow(Object e, EntityMetadata m, String columnFamily)
{
List indexThriftRows = new ArrayList();
byte[] rowKey = getThriftColumnValue(e, m.getIdAttribute());
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
// Add thrift rows for embeddables
Map embeddables = metaModel.getEmbeddables(m.getEntityClazz());
EntityType entityType = metaModel.entity(m.getEntityClazz());
for (String embeddedFieldName : embeddables.keySet())
{
EmbeddableType embeddedColumn = embeddables.get(embeddedFieldName);
// Index embeddable only when specified by user
Field embeddedField = (Field) entityType.getAttribute(embeddedFieldName).getJavaMember();
if (!MetadataUtils.isEmbeddedAtributeIndexable(embeddedField))
{
continue;
}
Object embeddedObject = PropertyAccessorHelper.getObject(e,
(Field) entityType.getAttribute(embeddedFieldName).getJavaMember());
if (embeddedObject == null)
{
continue;
}
if (embeddedObject instanceof Collection)
{
ElementCollectionCacheManager ecCacheHandler = ElementCollectionCacheManager.getInstance();
for (Object obj : (Collection) embeddedObject)
{
for (Object column : embeddedColumn.getAttributes())
{
Attribute columnAttribute = (Attribute) column;
String columnName = columnAttribute.getName();
if (!MetadataUtils.isColumnInEmbeddableIndexable(embeddedField, columnName))
{
continue;
}
// Column Value
String id = (String) CassandraDataTranslator.decompose(
((AbstractAttribute) m.getIdAttribute()).getBindableJavaType(), rowKey, false);
String superColumnName = ecCacheHandler.getElementCollectionObjectName(id, obj);
ThriftRow tr = constructIndexTableThriftRow(columnFamily, embeddedFieldName, obj,
columnAttribute, rowKey, superColumnName);
if (tr != null)
{
indexThriftRows.add(tr);
}
}
}
}
else
{
for (Object column : embeddedColumn.getAttributes())
{
Attribute columnAttribute = (Attribute) column;
String columnName = columnAttribute.getName();
Class> columnClass = ((AbstractAttribute) columnAttribute).getBindableJavaType();
if (!MetadataUtils.isColumnInEmbeddableIndexable(embeddedField, columnName)
|| columnClass.equals(byte[].class))
{
continue;
}
// No EC Name
ThriftRow tr = constructIndexTableThriftRow(columnFamily, embeddedFieldName, embeddedObject,
(Attribute) column, rowKey, "");
if (tr != null)
{
indexThriftRows.add(tr);
}
}
}
}
return indexThriftRows;
}
/**
* Constructs Thrift Tow (each record) for Index Table.
*
* @param columnFamily
* Column family Name for Index Table
* @param embeddedFieldName
* the embedded field name
* @param obj
* Embedded Object instance
* @param column
* Instance of {@link Column}
* @param rowKey
* Name of Index Column
* @param ecValue
* Name of embeddable object in Element Collection cache (usually
* in the form of #
* @return Instance of {@link ThriftRow}
*/
private ThriftRow constructIndexTableThriftRow(String columnFamily, String embeddedFieldName, Object obj,
Attribute column, byte[] rowKey, String ecValue)
{
// Column Name
Field columnField = (Field) column.getJavaMember();
byte[] indexColumnName = PropertyAccessorHelper.get(obj, columnField);
ThriftRow tr = null;
if (indexColumnName != null && indexColumnName.length != 0 && rowKey != null)
{
// Construct Index Table Thrift Row
tr = new ThriftRow();
tr.setColumnFamilyName(columnFamily); // Index column-family name
tr.setId(embeddedFieldName + Constants.INDEX_TABLE_ROW_KEY_DELIMITER + column.getName()); // Id
SuperColumn thriftSuperColumn = new SuperColumn();
thriftSuperColumn.setName(indexColumnName);
Column thriftColumn = new Column();
thriftColumn.setName(rowKey);
thriftColumn.setValue(ecValue.getBytes());
thriftColumn.setTimestamp(generator.getTimestamp());
thriftSuperColumn.addToColumns(thriftColumn);
tr.addSuperColumn(thriftSuperColumn);
}
return tr;
}
/**
* Gets the foreign keys from join table.
*
* @param
* the element type
* @param inverseJoinColumnName
* the inverse join column name
* @param columns
* the columns
* @param columnJavaType
* the column java type
* @return the foreign keys from join table
*/
public List getForeignKeysFromJoinTable(String inverseJoinColumnName, List columns,
Class columnJavaType)
{
List foreignKeys = new ArrayList();
if (columns == null || columns.isEmpty())
{
return foreignKeys;
}
for (Column c : columns)
{
try
{
// Thrift Column name
String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, c.getName());
// Thrift Column Value
byte[] thriftColumnValue = c.getValue();
if (null == thriftColumnValue)
{
continue;
}
if (thriftColumnName != null && thriftColumnName.startsWith(inverseJoinColumnName))
{
Object val = PropertyAccessorHelper.getObject(columnJavaType, thriftColumnValue);
foreignKeys.add(val);
}
}
catch (PropertyAccessException e)
{
continue;
}
}
return foreignKeys;
}
/**
* Populate entity.
*
* @param tr
* the tr
* @param m
* the m
* @param entity
* the entity
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @return the object
*/
public Object populateEntity(ThriftRow tr, EntityMetadata m, Object entity, List relationNames,
boolean isWrapReq)
{
Map relations = new HashMap();
try
{
boolean isCql3Enabled = clientBase.isCql3Enabled(m);
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
EntityType entityType = metaModel.entity(m.getEntityClazz());
for (Column column : tr.getColumns())
{
if (column != null)
{
String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
if ((CassandraConstants.CQL_KEY.equalsIgnoreCase(thriftColumnName) || ((AbstractAttribute) m
.getIdAttribute()).getJPAColumnName().equals(thriftColumnName)) && tr.getId() == null)
{
entity = KunderaCoreUtils.initialize(m, entity, null);
setId(m, entity, column.getValue(), isCql3Enabled);
}
else
{
entity = onColumn(column, m, entity, entityType, relationNames, isWrapReq, relations,
isCql3Enabled);
String discriminatorColumn = ((AbstractManagedType) entityType).getDiscriminatorColumn();
String discriminatorValue = ((AbstractManagedType) entityType).getDiscriminatorValue();
if (thriftColumnName != null
&& thriftColumnName.equals(discriminatorColumn)
&& column.getValue() != null
&& !PropertyAccessorFactory.STRING.fromBytes(String.class, column.getValue()).equals(
discriminatorValue))
{
entity = null;
break;
}
}
}
}
// Add all super columns to entity
Collection embeddedCollection = null;
Field embeddedCollectionField = null;
boolean mappingProcessed = false;
Map columnNameToFieldMap = new HashMap();
Map superColumnNameToFieldMap = new HashMap();
for (SuperColumn superColumn : tr.getSuperColumns())
{
if (superColumn != null)
{
entity = KunderaCoreUtils.initialize(m, entity, tr.getId());
String scName = PropertyAccessorFactory.STRING.fromBytes(String.class, superColumn.getName());
String scNamePrefix = null;
// Map to hold property-name=>foreign-entity relations
Map> foreignKeysMap = new HashMap>();
// Get a name->field map for super-columns
if (!mappingProcessed)
{
MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap,
superColumnNameToFieldMap, kunderaMetadata);
mappingProcessed = true;
}
if (scName.indexOf(Constants.EMBEDDED_COLUMN_NAME_DELIMITER) != -1)
{
scNamePrefix = MetadataUtils.getEmbeddedCollectionPrefix(scName);
embeddedCollectionField = superColumnNameToFieldMap.get(scNamePrefix);
if (embeddedCollection == null)
{
embeddedCollection = MetadataUtils.getEmbeddedCollectionInstance(embeddedCollectionField);
}
Object embeddedObject = MetadataUtils.getEmbeddedGenericObjectInstance(embeddedCollectionField);
scrollOverSuperColumn(m, relationNames, isWrapReq, relations, entityType, superColumn,
embeddedObject, columnNameToFieldMap);
Collection collection = PropertyAccessorHelper.getCollectionInstance(embeddedCollectionField);
collection.add(embeddedObject);
PropertyAccessorHelper.set(entity, embeddedCollectionField, collection);
embeddedCollection.add(embeddedObject);
// Add this embedded object to cache
ElementCollectionCacheManager.getInstance().addElementCollectionCacheMapping(tr.getId(),
embeddedObject, scName);
}
else
{
if (superColumnNameToFieldMap.containsKey(scName))
{
Field field = superColumnNameToFieldMap.get(scName);
Object embeddedObj = PropertyAccessorHelper.getObject(entity, field);
if (embeddedObj == null)
{
embeddedObj = field.getType().newInstance();
}
// column
scrollOverSuperColumn(m, relationNames, isWrapReq, relations, entityType, superColumn,
embeddedObj, columnNameToFieldMap);
PropertyAccessorHelper.set(entity, field, embeddedObj);
}
else
{
scrollOverSuperColumn(m, relationNames, isWrapReq, relations, entityType, superColumn,
entity, isCql3Enabled);
}
}
}
}
mappingProcessed = false;
for (CounterColumn counterColumn : tr.getCounterColumns())
{
if (counterColumn != null)
{
entity = KunderaCoreUtils.initialize(m, entity, tr.getId());
onCounterColumn(counterColumn, m, entity, entityType, relationNames, isWrapReq, relations,
isCql3Enabled);
}
}
for (CounterSuperColumn counterSuperColumn : tr.getCounterSuperColumns())
{
if (counterSuperColumn != null)
{
entity = KunderaCoreUtils.initialize(m, entity, tr.getId());
String scName = PropertyAccessorFactory.STRING
.fromBytes(String.class, counterSuperColumn.getName());
String scNamePrefix = null;
// Map to hold property-name=>foreign-entity relations
Map> foreignKeysMap = new HashMap>();
// Get a name->field map for super-columns
if (!mappingProcessed)
{
MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap,
superColumnNameToFieldMap, kunderaMetadata);
mappingProcessed = true;
}
if (scName.indexOf(Constants.EMBEDDED_COLUMN_NAME_DELIMITER) != -1)
{
scNamePrefix = MetadataUtils.getEmbeddedCollectionPrefix(scName);
embeddedCollectionField = superColumnNameToFieldMap.get(scNamePrefix);
if (embeddedCollection == null)
{
embeddedCollection = MetadataUtils.getEmbeddedCollectionInstance(embeddedCollectionField);
}
Object embeddedObject = MetadataUtils.getEmbeddedGenericObjectInstance(embeddedCollectionField);
scrollOverCounterSuperColumn(m, relationNames, isWrapReq, relations, entityType,
counterSuperColumn, embeddedObject, columnNameToFieldMap);
embeddedCollection.add(embeddedObject);
// Add this embedded object to cache
ElementCollectionCacheManager.getInstance().addElementCollectionCacheMapping(tr.getId(),
embeddedObject, scName);
}
else
{
if (superColumnNameToFieldMap.containsKey(scName))
{
Field field = superColumnNameToFieldMap.get(scName);
Object embeddedObj = field.getType().newInstance();
// column
scrollOverCounterSuperColumn(m, relationNames, isWrapReq, relations, entityType,
counterSuperColumn, embeddedObj, columnNameToFieldMap);
PropertyAccessorHelper.set(entity, field, embeddedObj);
}
else
{
scrollOverCounterSuperColumn(m, relationNames, isWrapReq, relations, entityType,
counterSuperColumn, entity, isCql3Enabled);
}
}
}
}
if (embeddedCollection != null && !embeddedCollection.isEmpty())
{
PropertyAccessorHelper.set(entity, embeddedCollectionField, embeddedCollection);
}
}
catch (Exception e)
{
log.error("Eror while retrieving data, Caused by: .", e);
throw new PersistenceException(e);
}
if (entity != null && tr.getId() != null)
{
PropertyAccessorHelper.setId(entity, m, tr.getId());
}
return isWrapReq && relations != null && !relations.isEmpty() ? new EnhanceEntity(entity,
PropertyAccessorHelper.getId(entity, m), relations) : entity;
}
/**
* Sets the id.
*
* @param m
* the m
* @param entity
* the entity
* @param columnValue
* the column value
* @param isCql3Enabled
* the is cql3 enabled
*/
private void setId(EntityMetadata m, Object entity, Object columnValue, boolean isCql3Enabled)
{
if (isCql3Enabled && !m.getType().equals(Type.SUPER_COLUMN_FAMILY))
{
setFieldValueViaCQL(entity, columnValue, m.getIdAttribute());
}
else
{
setFieldValue(entity, columnValue, m.getIdAttribute());
}
}
/**
* Scroll over super column.
*
* @param m
* the m
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param relations
* the relations
* @param entityType
* the entity type
* @param superColumn
* the super column
* @param embeddedObject
* the embedded object
* @param isCql3Enabled
* the is cql3 enabled
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private void scrollOverSuperColumn(EntityMetadata m, List relationNames, boolean isWrapReq,
Map relations, EntityType entityType, SuperColumn superColumn, Object embeddedObject,
boolean isCql3Enabled) throws InstantiationException, IllegalAccessException
{
for (Column column : superColumn.getColumns())
{
embeddedObject = onColumn(column, m, embeddedObject, entityType, relationNames, isWrapReq, relations,
isCql3Enabled);
}
}
/**
* Scroll over counter super column.
*
* @param m
* the m
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param relations
* the relations
* @param entityType
* the entity type
* @param superColumn
* the super column
* @param embeddedObject
* the embedded object
* @param isCql3Enabled
* the is cql3 enabled
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private void scrollOverCounterSuperColumn(EntityMetadata m, List relationNames, boolean isWrapReq,
Map relations, EntityType entityType, CounterSuperColumn superColumn,
Object embeddedObject, boolean isCql3Enabled) throws InstantiationException, IllegalAccessException
{
for (CounterColumn column : superColumn.getColumns())
{
onCounterColumn(column, m, embeddedObject, entityType, relationNames, isWrapReq, relations, isCql3Enabled);
}
}
/**
* Scroll over counter super column.
*
* @param m
* the m
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param relations
* the relations
* @param entityType
* the entity type
* @param superColumn
* the super column
* @param embeddedObject
* the embedded object
* @param superColumnFieldMap
* the super column field map
*/
private void scrollOverCounterSuperColumn(EntityMetadata m, List relationNames, boolean isWrapReq,
Map relations, EntityType entityType, CounterSuperColumn superColumn,
Object embeddedObject, Map superColumnFieldMap)
{
for (CounterColumn column : superColumn.getColumns())
{
String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
String thriftColumnValue = new Long(column.getValue()).toString();
PropertyAccessorHelper.set(embeddedObject, superColumnFieldMap.get(thriftColumnName), thriftColumnValue);
}
}
/**
* Scroll over super column.
*
* @param m
* the m
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param relations
* the relations
* @param entityType
* the entity type
* @param superColumn
* the super column
* @param embeddedObject
* the embedded object
* @param superColumnFieldMap
* the super column field map
*/
private void scrollOverSuperColumn(EntityMetadata m, List relationNames, boolean isWrapReq,
Map relations, EntityType entityType, SuperColumn superColumn, Object embeddedObject,
Map superColumnFieldMap)
{
for (Column column : superColumn.getColumns())
{
String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
byte[] thriftColumnValue = column.getValue();
PropertyAccessorHelper.set(embeddedObject, superColumnFieldMap.get(thriftColumnName), thriftColumnValue);
}
}
/**
* On column.
*
* @param column
* the column
* @param m
* the m
* @param entity
* the entity
* @param entityType
* the entity type
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param relations
* the relations
* @param isCql3Enabled
* the is cql3 enabled
* @return the object
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private Object onColumn(Column column, EntityMetadata m, Object entity, EntityType entityType,
List relationNames, boolean isWrapReq, Map relations, boolean isCql3Enabled)
throws InstantiationException, IllegalAccessException
{
String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
byte[] thriftColumnValue = column.getValue();
String discriminatorColumn = ((AbstractManagedType) entityType).getDiscriminatorColumn();
String discriminatorValue = ((AbstractManagedType) entityType).getDiscriminatorValue();
if (!thriftColumnName.equals(discriminatorColumn))
{
if (m.isCounterColumnType())
{
if (thriftColumnName.equals(((AbstractAttribute) m.getIdAttribute()).getJPAColumnName()))
{
return populateViaThrift(m, entity, entityType, relationNames, relations, thriftColumnName,
column.getValue(), isCql3Enabled);
}
else
{
LongAccessor accessor = new LongAccessor();
Long value = accessor.fromBytes(Long.class, column.getValue());
return populateViaThrift(m, entity, entityType, relationNames, relations, thriftColumnName,
value != null ? value.toString() : null, isCql3Enabled);
}
}
return populateViaThrift(m, entity, entityType, relationNames, relations, thriftColumnName,
thriftColumnValue, isCql3Enabled);
}
return entity;
}
/**
* On counter column.
*
* @param column
* the column
* @param m
* the m
* @param entity
* the entity
* @param entityType
* the entity type
* @param relationNames
* the relation names
* @param isWrapReq
* the is wrap req
* @param relations
* the relations
* @param isCql3Enabled
* the is cql3 enabled
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private void onCounterColumn(CounterColumn column, EntityMetadata m, Object entity, EntityType entityType,
List relationNames, boolean isWrapReq, Map relations, boolean isCql3Enabled)
throws InstantiationException, IllegalAccessException
{
String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName());
String thriftColumnValue = new Long(column.getValue()).toString();
populateViaThrift(m, entity, entityType, relationNames, relations, thriftColumnName, thriftColumnValue,
isCql3Enabled);
}
/**
* Populate via thrift.
*
* @param m
* the m
* @param entity
* the entity
* @param entityType
* the entity type
* @param relationNames
* the relation names
* @param relations
* the relations
* @param thriftColumnName
* the thrift column name
* @param thriftColumnValue
* the thrift column value
* @param isCql3Enabled
* the is cql3 enabled
* @return the object
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private Object populateViaThrift(EntityMetadata m, Object entity, EntityType entityType,
List relationNames, Map relations, String thriftColumnName,
Object thriftColumnValue, boolean isCql3Enabled) throws InstantiationException, IllegalAccessException
{
if (relationNames == null || !relationNames.contains(thriftColumnName))
{
if (thriftColumnValue != null)
{
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
String fieldName = m.getFieldName(thriftColumnName);
Attribute attribute = fieldName != null ? entityType.getAttribute(fieldName) : null;
if (attribute != null)
{
entity = KunderaCoreUtils.initialize(m, entity, null);
if (!attribute.isAssociation())
{
String idColumnName = ((AbstractAttribute) m.getIdAttribute()).getJPAColumnName();
if (!metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())
&& thriftColumnName.equals(idColumnName))
{
setId(m, entity, thriftColumnValue, isCql3Enabled);
PropertyAccessorHelper.setId(entity, m, (byte[]) thriftColumnValue);
}
// remove super column family check and populate
// embedded
if (isCql3Enabled && !m.isCounterColumnType())
{
if (metaModel.isEmbeddable(((AbstractAttribute) attribute).getBindableJavaType()))
{
if (attribute.isCollection())
{
// element collection
entity = setElementCollection(entity, thriftColumnValue, metaModel, attribute);
}
else
{
entity = setUdtValue(entity, thriftColumnValue, metaModel, attribute);
}
}
else
{
setFieldValueViaCQL(entity, thriftColumnValue, attribute);
}
}
else
{
setFieldValue(entity, thriftColumnValue, attribute);
}
}
}
else if (metaModel.isEmbeddable(((AbstractAttribute) m.getIdAttribute()).getBindableJavaType()))
{
entity = populateCompositeId(m, entity, thriftColumnName, thriftColumnValue, metaModel,
m.getIdAttribute(), m.getEntityClazz());
}
else if (clientBase.getCqlMetadata() != null)
{
if (entity == null)
{
entity = new HashMap();
}
if (entity instanceof HashMap)
{
composeAndAdd((HashMap) entity, clientBase.getCqlMetadata(), thriftColumnValue,
thriftColumnName);
}
}
}
}
else
{
// populate relation.
if (relationNames != null && relationNames.contains(thriftColumnName) && thriftColumnValue != null)
{
String fieldName = m.getFieldName(thriftColumnName);
Attribute attribute = fieldName != null ? entityType.getAttribute(fieldName) : null;
EntityMetadata relationMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,
((AbstractAttribute) attribute).getBindableJavaType());
Object value;
if (isCql3Enabled && !m.getType().equals(Type.SUPER_COLUMN_FAMILY))
{
value = getFieldValueViaCQL(thriftColumnValue, relationMetadata.getIdAttribute());
}
else
{
value = PropertyAccessorHelper.getObject(relationMetadata.getIdAttribute().getJavaType(),
(byte[]) thriftColumnValue);
}
relations.put(thriftColumnName, value);
if (entity == null)
{
entity = KunderaCoreUtils.initialize(m, entity, null);
}
// prepare EnhanceEntity and return it
}
}
return entity;
}
/**
* Compose and add.
*
* @param entity
* the entity
* @param cqlMetadata
* the cql metadata
* @param thriftColumnValue
* the thrift column value
* @param thriftColumnName
* the thrift column name
*/
private void composeAndAdd(HashMap entity, CqlMetadata cqlMetadata, Object thriftColumnValue,
String thriftColumnName)
{
byte[] columnName = thriftColumnName.getBytes();
Map schemaTypes = this.clientBase.getCqlMetadata().getValue_types();
AbstractType> type = null;
try
{
type = TypeParser.parse(schemaTypes.get(ByteBuffer.wrap((byte[]) columnName)));
}
catch (SyntaxException | ConfigurationException e)
{
log.error(e.getMessage());
throw new KunderaException("Error while parsing CQL Type " + e);
}
entity.put(thriftColumnName, type.compose(ByteBuffer.wrap((byte[]) thriftColumnValue)));
}
/**
* Sets the udt value.
*
* @param entity
* the entity
* @param thriftColumnValue
* the thrift column value
* @param metaModel
* the meta model
* @param attribute
* the attribute
* @return the object
*/
private Object setUdtValue(Object entity, Object thriftColumnValue, MetamodelImpl metaModel, Attribute attribute)
{
List fieldNames = new ArrayList();
List> fieldTypes = new ArrayList>();
String val = null;
// get from cqlMetadata, details of types and names (for maintaining
// order)
Map schemaTypes = this.clientBase.getCqlMetadata().getValue_types();
for (Map.Entry schemaType : schemaTypes.entrySet())
{
UTF8Serializer utf8Serializer = UTF8Serializer.instance;
String key = utf8Serializer.deserialize((schemaType.getKey()));
if (key.equals(((AbstractAttribute) attribute).getJavaMember().getName()))
{
val = schemaType.getValue();
break;
}
}
UserType userType = null;
try
{
userType = UserType.getInstance(new TypeParser(val.substring(val.indexOf("("), val.length())));
}
catch (ConfigurationException | SyntaxException e)
{
log.error(e.getMessage());
throw new KunderaException("Error while getting instance of UserType " + e);
}
fieldNames = userType.fieldNames();
fieldTypes = userType.allTypes();
Field field = (Field) ((AbstractAttribute) attribute).getJavaMember();
Class embeddedClass = ((AbstractAttribute) attribute).getBindableJavaType();
Object embeddedObject = KunderaCoreUtils.createNewInstance(embeddedClass);
Object finalValue = populateEmbeddedRecursive((ByteBuffer.wrap((byte[]) thriftColumnValue)), fieldTypes,
fieldNames, embeddedObject, metaModel);
PropertyAccessorHelper.set(entity, field, finalValue);
return entity;
}
/**
* Populate embedded recursive.
*
* @param value
* the value
* @param types
* the types
* @param fieldNames
* the field names
* @param entity
* the entity
* @param metaModel
* the meta model
* @return the object
*/
public Object populateEmbeddedRecursive(ByteBuffer value, List> types, List fieldNames,
Object entity, MetamodelImpl metaModel)
{
ByteBuffer input = value.duplicate();
EmbeddableType emb = metaModel.embeddable(entity.getClass());
for (int i = 0; i < types.size(); i++)
{
if (!input.hasRemaining())
return entity;
AbstractType> type = types.get(i);
String name = new String(fieldNames.get(i).array()); // JPA name,
// convert to
// column name
Field fieldToSet = null;
AbstractAttribute attribute = null;
// change this if possible
for (Object attr : emb.getAttributes())
{
if (((AbstractAttribute) attr).getJPAColumnName().equals(name))
{
attribute = (AbstractAttribute) attr;
break;
}
}
fieldToSet = (Field) attribute.getJavaMember();
Class embeddedClass = attribute.getBindableJavaType();
int size = input.getInt();
if (size < 0)
{
continue;
}
ByteBuffer field = ByteBufferUtil.readBytes(input, size);
if (type.getClass().getSimpleName().equals("UserType"))
{
List subFieldNames = ((UserType) type).fieldNames();// ok
List> subfieldTypes = ((UserType) type).fieldTypes();
// create entity with type_name and populate fields, set entity
// in parent object after exit
Object embeddedObjectChild = KunderaCoreUtils.createNewInstance(embeddedClass);
Object processedEntity = populateEmbeddedRecursive(field, subfieldTypes, subFieldNames,
embeddedObjectChild, metaModel);
PropertyAccessorHelper.set(entity, fieldToSet, processedEntity);
}
else
{
boolean flag = true;
if (type.getClass().getSimpleName().equals("MapType"))
{
if (((MapType) type).getValuesType().getClass().getSimpleName().equals("UserType"))
{
flag = false;
// create instance of embedded object (UserType)
setElementCollectionMap((MapType) type, field, entity, fieldToSet, metaModel, embeddedClass,
false);
}
}
else if (type.getClass().getSimpleName().equals("ListType"))
{
if (((ListType) type).getElementsType().getClass().getSimpleName().equals("UserType"))
{
flag = false;
setElementCollectionList((ListType) type, field, entity, fieldToSet, metaModel, embeddedClass,
false);
}
}
else if (type.getClass().getSimpleName().equals("SetType"))
{
if (((SetType) type).getElementsType().getClass().getSimpleName().equals("UserType"))
{
flag = false;
setElementCollectionSet((SetType) type, field, entity, fieldToSet, metaModel, embeddedClass,
false);
}
}
if (flag)
{
TypeSerializer serializer = type.getSerializer();
serializer.validate(field);
Object finalValue = serializer.deserialize(field);
PropertyAccessorHelper.set(entity, fieldToSet, finalValue);
}
}
}
return entity;
}
/**
* Sets the field value.
*
* @param entity
* the entity
* @param thriftColumnValue
* the thrift column value
* @param attribute
* the attribute
*/
private void setFieldValue(Object entity, Object thriftColumnValue, Attribute attribute)
{
if (attribute != null)
{
try
{
if (thriftColumnValue.getClass().isAssignableFrom(String.class))
{
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), (String) thriftColumnValue);
}
else if (CassandraDataTranslator.isCassandraDataTypeClass(((AbstractAttribute) attribute)
.getBindableJavaType()))
{
Object decomposed = null;
try
{
Class> clazz = ((AbstractAttribute) attribute).getBindableJavaType();
decomposed = CassandraDataTranslator.decompose(clazz, thriftColumnValue, false);
}
catch (Exception e)
{
String tableName = entity.getClass().getSimpleName();
String fieldName = attribute.getName();
String msg = "Decomposing failed for `" + tableName + "`.`" + fieldName
+ "`, did you set the correct type in your entity class?";
log.error(msg, e);
throw new KunderaException(msg, e);
}
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), decomposed);
}
else
{
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), (byte[]) thriftColumnValue);
}
}
catch (PropertyAccessException pae)
{
log.warn("Error while setting field value, Caused by: .", pae);
}
}
}
/**
* Sets the field value via cql.
*
* @param entity
* the entity
* @param thriftColumnValue
* the thrift column value
* @param attribute
* the attribute
*/
private void setFieldValueViaCQL(Object entity, Object thriftColumnValue, Attribute attribute)
{
if (attribute != null)
{
try
{
if (attribute.isCollection())
{
setCollectionValue(entity, thriftColumnValue, attribute);
}
else if (CassandraDataTranslator.isCassandraDataTypeClass(((AbstractAttribute) attribute)
.getBindableJavaType()))
{
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), CassandraDataTranslator
.decompose(((AbstractAttribute) attribute).getBindableJavaType(), thriftColumnValue, true));
}
else
{
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), (byte[]) thriftColumnValue);
}
}
catch (PropertyAccessException pae)
{
log.warn("Error while setting field{} value via CQL, Caused by: .", attribute.getName(), pae);
}
}
}
/**
* Sets the element collection.
*
* @param entity
* the entity
* @param thriftColumnValue
* the thrift column value
* @param metaModel
* the meta model
* @param attribute
* the attribute
* @return the object
*/
private Object setElementCollection(Object entity, Object thriftColumnValue, MetamodelImpl metaModel,
Attribute attribute)
{
String cqlColumnMetadata = null;
Map schemaTypes = this.clientBase.getCqlMetadata().getValue_types();
for (Map.Entry schemaType : schemaTypes.entrySet())
{
String key = UTF8Serializer.instance.deserialize((schemaType.getKey()));
if (key.equals(((AbstractAttribute) attribute).getJavaMember().getName()))
{
cqlColumnMetadata = schemaType.getValue();
}
}
Field field = (Field) ((AbstractAttribute) attribute).getJavaMember();
Class embeddedClass = ((AbstractAttribute) attribute).getBindableJavaType();
if (List.class.isAssignableFrom(((Field) attribute.getJavaMember()).getType()))
{
ListType listType = null;
try
{
listType = ListType.getInstance(new TypeParser(cqlColumnMetadata.substring(
cqlColumnMetadata.indexOf("("), cqlColumnMetadata.length())));
}
catch (ConfigurationException | SyntaxException e)
{
log.error(e.getMessage());
throw new KunderaException("Error while getting instance of ListType " + e);
}
return setElementCollectionList(listType, ByteBuffer.wrap((byte[]) thriftColumnValue), entity, field,
metaModel, embeddedClass, true);
}
else if (Set.class.isAssignableFrom(((Field) attribute.getJavaMember()).getType()))
{
SetType setType = null;
try
{
setType = SetType.getInstance(new TypeParser(cqlColumnMetadata.substring(
cqlColumnMetadata.indexOf("("), cqlColumnMetadata.length())));
}
catch (ConfigurationException | SyntaxException e)
{
log.error(e.getMessage());
throw new KunderaException("Error while getting instance of SetType " + e);
}
return setElementCollectionSet(setType, ByteBuffer.wrap((byte[]) thriftColumnValue), entity, field,
metaModel, embeddedClass, true);
}
else if (Map.class.isAssignableFrom(((Field) attribute.getJavaMember()).getType()))
{
MapType mapType = null;
try
{
mapType = MapType.getInstance(new TypeParser(cqlColumnMetadata.substring(
cqlColumnMetadata.indexOf("("), cqlColumnMetadata.length())));
}
catch (ConfigurationException | SyntaxException e)
{
log.error(e.getMessage());
throw new KunderaException("Error while getting instance of MapType " + e);
}
return setElementCollectionMap(mapType, ByteBuffer.wrap((byte[]) thriftColumnValue), entity, field,
metaModel, embeddedClass, true);
}
return entity;
}
/**
* Sets the element collection map.
*
* @param mapType
* the cql column metadata
* @param thriftColumnValue
* the thrift column value
* @param entity
* the entity
* @param field
* the field
* @param metaModel
* the meta model
* @param embeddedObject
* the embedded object
* @return the object
*/
private Object setElementCollectionMap(MapType mapType, ByteBuffer thriftColumnValue, Object entity, Field field,
MetamodelImpl metaModel, Class embeddedClass, boolean useNativeProtocol2)
{
Map result = new HashMap();
MapSerializer mapSerializer = mapType.getSerializer();
Map outputCollection = new HashMap();
if (useNativeProtocol2)
{
outputCollection.putAll(mapSerializer.deserializeForNativeProtocol(thriftColumnValue, 2));
}
else
{
outputCollection.putAll((Map) mapSerializer.deserialize(thriftColumnValue));
}
UserType usertype = (UserType) mapType.getValuesType();
for (Object key : outputCollection.keySet())
{
Object embeddedObject = KunderaCoreUtils.createNewInstance(embeddedClass);
Object value = populateEmbeddedRecursive((ByteBuffer) outputCollection.get(key), usertype.allTypes(),
usertype.fieldNames(), embeddedObject, metaModel);
result.put(key, value);
}
PropertyAccessorHelper.set(entity, field, result);
return entity;
}
/**
* Sets the element collection set.
*
* @param setType
* the cql column metadata
* @param thriftColumnValue
* the thrift column value
* @param entity
* the entity
* @param field
* the field
* @param metaModel
* the meta model
* @param embeddedObject
* the embedded object
* @return the object
*/
private Object setElementCollectionSet(SetType setType, ByteBuffer thriftColumnValue, Object entity, Field field,
MetamodelImpl metaModel, Class embeddedClass, boolean useNativeProtocol2)
{
SetSerializer setSerializer = setType.getSerializer();
Collection outputCollection = new ArrayList();
if (useNativeProtocol2)
{
outputCollection.addAll((Collection) setSerializer.deserializeForNativeProtocol(thriftColumnValue, 2));
}
else
{
outputCollection.addAll((Collection) setSerializer.deserialize(thriftColumnValue));
}
UserType usertype = (UserType) setType.getElementsType();
Collection result = new HashSet();
Iterator collectionItems = outputCollection.iterator();
while (collectionItems.hasNext())
{
Object embeddedObject = KunderaCoreUtils.createNewInstance(embeddedClass);
Object value = populateEmbeddedRecursive((ByteBuffer) collectionItems.next(), usertype.allTypes(),
usertype.fieldNames(), embeddedObject, metaModel);
result.add(value);
}
PropertyAccessorHelper.set(entity, field, result);
return entity;
}
/**
* Sets the element collection list.
*
* @param listType
* the cql column metadata
* @param thriftColumnValue
* the thrift column value
* @param entity
* the entity
* @param field
* the field
* @param metaModel
* the meta model
* @param embeddedObject
* the embedded object
* @return the object
*/
private Object setElementCollectionList(ListType listType, ByteBuffer thriftColumnValue, Object entity,
Field field, MetamodelImpl metaModel, Class embeddedClass, boolean useNativeProtocol2)
{
ListSerializer listSerializer = listType.getSerializer();
Collection outputCollection = new ArrayList();
if (useNativeProtocol2)
{
outputCollection.addAll((Collection) listSerializer.deserializeForNativeProtocol(thriftColumnValue, 2));
}
else
{
outputCollection.addAll((Collection) listSerializer.deserialize(thriftColumnValue));
}
UserType usertype = (UserType) listType.getElementsType();
Collection result = new ArrayList();
Iterator collectionItems = outputCollection.iterator();
while (collectionItems.hasNext())
{
Object embeddedObject = KunderaCoreUtils.createNewInstance(embeddedClass);
Object value = populateEmbeddedRecursive((ByteBuffer) collectionItems.next(), usertype.allTypes(),
usertype.fieldNames(), embeddedObject, metaModel);
result.add(value);
}
PropertyAccessorHelper.set(entity, field, result);
return entity;
}
/**
* Gets the field value via cql.
*
* @param thriftColumnValue
* the thrift column value
* @param attribute
* the attribute
* @return the field value via cql
*/
private Object getFieldValueViaCQL(Object thriftColumnValue, Attribute attribute)
{
PropertyAccessor> accessor = PropertyAccessorFactory.getPropertyAccessor((Field) attribute.getJavaMember());
Object objValue;
try
{
if (CassandraDataTranslator.isCassandraDataTypeClass(((AbstractAttribute) attribute).getBindableJavaType()))
{
objValue = CassandraDataTranslator.decompose(((AbstractAttribute) attribute).getBindableJavaType(),
thriftColumnValue, true);
return objValue;
}
else
{
objValue = accessor.fromBytes(((AbstractAttribute) attribute).getBindableJavaType(),
(byte[]) thriftColumnValue);
return objValue;
}
}
catch (PropertyAccessException pae)
{
log.warn("Error while setting field{} value via CQL, Caused by: .", attribute.getName(), pae);
}
return null;
}
/**
* On column or super column thrift row.
*
* @param m
* the m
* @param e
* the e
* @param id
* the id
* @param timestamp
* the timestamp2
* @param columnTTLs
* TODO
* @return the collection
*/
private Collection onColumnOrSuperColumnThriftRow(EntityMetadata m, Object e, Object id, long timestamp,
Object columnTTLs)
{
// Iterate through Super columns
Map thriftRows = new HashMap();
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
EntityType entityType = metaModel.entity(m.getEntityClazz());
Set attributes = entityType.getAttributes();
for (Attribute attribute : attributes)
{
String tableName = ((AbstractAttribute) attribute).getTableName() != null ? ((AbstractAttribute) attribute)
.getTableName() : m.getTableName();
ThriftRow tr = getThriftRow(id, tableName, thriftRows);
if (!attribute.getName().equals(m.getIdAttribute().getName()) && !attribute.isAssociation())
{
Field field = (Field) ((Attribute) attribute).getJavaMember();
byte[] name = ByteBufferUtil.bytes(((AbstractAttribute) attribute).getJPAColumnName()).array();
// if attribute is embeddable.
if (metaModel.isEmbeddable(attribute.isCollection() ? ((PluralAttribute) attribute)
.getBindableJavaType() : attribute.getJavaType()))
{
Map thriftSuperColumns = onEmbeddable(timestamp, tr, m, e, id, attribute);
if (thriftSuperColumns != null)
{
for (String columnFamilyName : thriftSuperColumns.keySet())
{
ThriftRow thriftRow = getThriftRow(id, columnFamilyName, thriftRows);
if (m.isCounterColumnType())
{
thriftRow.addCounterSuperColumn((CounterSuperColumn) thriftSuperColumns
.get(columnFamilyName));
}
else
{
thriftRow.addSuperColumn((SuperColumn) thriftSuperColumns.get(columnFamilyName));
}
}
}
}
else
{
Object value = getColumnValue(m, e, attribute);
if (m.getType().equals(Type.SUPER_COLUMN_FAMILY))
{
prepareSuperColumn(tr, m, value, name, timestamp);
}
else
{
int ttl = getTTLForColumn(columnTTLs, attribute);
prepareColumn(tr, m, value, name, timestamp, ttl);
}
}
}
}
// Add discriminator column.
onDiscriminatorColumn(thriftRows.get(m.getTableName()), timestamp, entityType);
return thriftRows.values();
}
/**
* On discriminator column.
*
* @param tr
* the tr
* @param timestamp
* the timestamp
* @param entityType
* the entity type
*/
private void onDiscriminatorColumn(ThriftRow tr, long timestamp, EntityType entityType)
{
String discrColumn = ((AbstractManagedType) entityType).getDiscriminatorColumn();
String discrValue = ((AbstractManagedType) entityType).getDiscriminatorValue();
// No need to check for empty or blank, as considering it as valid name
// for nosql!
if (discrColumn != null && discrValue != null)
{
Column column = prepareColumn(PropertyAccessorHelper.getBytes(discrValue),
PropertyAccessorHelper.getBytes(discrColumn), timestamp, 0);
tr.addColumn(column);
}
}
/**
* Determined TTL for a given column.
*
* @param columnTTLs
* the column tt ls
* @param attribute
* the attribute
* @return the TTL for column
*/
private int getTTLForColumn(Object columnTTLs, Attribute attribute)
{
Integer ttl = null;
if (columnTTLs != null)
{
if (columnTTLs instanceof Map)
{
ttl = (Integer) (columnTTLs == null ? 0 : ((Map) columnTTLs).get(((AbstractAttribute) attribute)
.getJPAColumnName()));
}
else if (columnTTLs instanceof Integer)
{
ttl = (Integer) columnTTLs;
}
}
return ttl == null ? 0 : ttl;
}
/**
* Gets the column value.
*
* @param m
* the m
* @param e
* the e
* @param attribute
* the attribute
* @return the column value
*/
private Object getColumnValue(EntityMetadata m, Object e, Attribute attribute)
{
Field field = (Field) ((Attribute) attribute).getJavaMember();
Object value;
if (!m.isCounterColumnType())
{
value = getThriftColumnValue(e, attribute);
}
else
{
value = PropertyAccessorHelper.getString(e, field);
}
return value;
}
/**
* Gets the thrift column value.
*
* @param e
* the e
* @param attribute
* the attribute
* @return the thrift column value
*/
protected byte[] getThriftColumnValue(Object e, Attribute attribute)
{
byte[] value = null;
Field field = (Field) ((Attribute) attribute).getJavaMember();
try
{
if (attribute != null && field.get(e) != null)
{
if (CassandraDataTranslator.isCassandraDataTypeClass(((AbstractAttribute) attribute)
.getBindableJavaType()))
{
value = CassandraDataTranslator.compose(((AbstractAttribute) attribute).getBindableJavaType(),
field.get(e), false);
}
else
{
value = PropertyAccessorHelper.get(e, field);
}
}
}
catch (IllegalArgumentException iae)
{
log.error("Error while persisting data, Caused by: .", iae);
throw new IllegalArgumentException(iae);
}
catch (IllegalAccessException iace)
{
log.error("Error while persisting data, Caused by: .", iace);
}
return value;
}
/**
* Prepare column.
*
* @param tr
* the tr
* @param m
* the m
* @param value
* the value
* @param name
* the name
* @param timestamp
* the timestamp
* @param ttl
* TODO
*/
private void prepareColumn(ThriftRow tr, EntityMetadata m, Object value, byte[] name, long timestamp, int ttl)
{
if (value != null)
{
if (m.isCounterColumnType())
{
CounterColumn counterColumn = prepareCounterColumn((String) value, name);
tr.addCounterColumn(counterColumn);
}
else
{
Column column = prepareColumn((byte[]) value, name, timestamp, ttl);
tr.addColumn(column);
}
}
}
/**
* Prepare super column.
*
* @param tr
* the tr
* @param m
* the m
* @param value
* the value
* @param name
* the name
* @param timestamp
* the timestamp
*/
private void prepareSuperColumn(ThriftRow tr, EntityMetadata m, Object value, byte[] name, long timestamp)
{
if (value != null)
{
if (m.isCounterColumnType())
{
CounterSuperColumn counterSuper = new CounterSuperColumn();
counterSuper.setName(name);
CounterColumn counterColumn = prepareCounterColumn((String) value, name);
List subCounterColumn = new ArrayList();
subCounterColumn.add(counterColumn);
counterSuper.setColumns(subCounterColumn);
tr.addCounterSuperColumn(counterSuper);
}
else
{
SuperColumn superCol = new SuperColumn();
superCol.setName(name);
Column column = prepareColumn((byte[]) value, name, timestamp, 0);
List subColumn = new ArrayList();
subColumn.add(column);
superCol.setColumns(subColumn);
tr.addSuperColumn(superCol);
}
}
}
/**
* Prepare column.
*
* @param value
* the value
* @param name
* the name
* @param timestamp
* the timestamp
* @param ttl
* TODO
* @return the column
*/
private Column prepareColumn(byte[] value, byte[] name, long timestamp, int ttl)
{
Column column = new Column();
column.setName(name);
column.setValue(value);
column.setTimestamp(timestamp);
if (ttl != 0)
{
column.setTtl(ttl);
}
return column;
}
/**
* Prepare counter column.
*
* @param value
* the value
* @param name
* the name
* @return the counter column
*/
private CounterColumn prepareCounterColumn(String value, byte[] name)
{
CounterColumn counterColumn = new CounterColumn();
counterColumn.setName(name);
LongAccessor accessor = new LongAccessor();
counterColumn.setValue(accessor.fromString(LongAccessor.class, value));
return counterColumn;
}
/**
* On embeddable.
*
* @param timestamp2
* the timestamp2
* @param tr
* the tr
* @param m
* the m
* @param e
* the e
* @param id
* the id
* @param embeddableAttrib
* the embeddable attrib
* @return the map
*/
private Map onEmbeddable(long timestamp2, ThriftRow tr, EntityMetadata m, Object e, Object id,
Attribute embeddableAttrib)
{
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
EmbeddableType superColumn = metaModel.embeddable(((AbstractAttribute) embeddableAttrib).getBindableJavaType());
Field superColumnField = (Field) embeddableAttrib.getJavaMember();
Object superColumnObject = PropertyAccessorHelper.getObject(e, superColumnField);
// If Embedded object is a Collection, there will be variable number
// of super columns one for each object in collection.
// Key for each super column will be of the format "#
// On the other hand, if embedded object is not a Collection, it
// would simply be embedded as ONE super column.
String superColumnName = null;
if (superColumnObject != null && superColumnObject instanceof Collection)
{
ElementCollectionCacheManager ecCacheHandler = ElementCollectionCacheManager.getInstance();
// Check whether it's first time insert or updation
if (ecCacheHandler.isCacheEmpty())
{ // First time insert
int count = 0;
for (Object obj : (Collection) superColumnObject)
{
superColumnName = ((AbstractAttribute) embeddableAttrib).getJPAColumnName()
+ Constants.EMBEDDED_COLUMN_NAME_DELIMITER + count;
if (m.isCounterColumnType())
{
CounterSuperColumn thriftSuperColumn = (CounterSuperColumn) buildThriftCounterSuperColumn(
m.getTableName(), superColumnName, superColumn, obj).get(m.getTableName());
tr.addCounterSuperColumn(thriftSuperColumn);
}
else
{
SuperColumn thriftSuperColumn = (SuperColumn) buildThriftSuperColumn(m.getTableName(),
superColumnName, timestamp2, superColumn, obj).get(m.getTableName());
tr.addSuperColumn(thriftSuperColumn);
}
ecCacheHandler.addElementCollectionCacheMapping(id, obj, superColumnName);
count++;
}
}
else
{
// Updation, Check whether this object is already in cache,
// which means we already have a super column
// Otherwise we need to generate a fresh embedded column
// name
int lastEmbeddedObjectCount = ecCacheHandler.getLastElementCollectionObjectCount(id);
for (Object obj : (Collection) superColumnObject)
{
superColumnName = ecCacheHandler.getElementCollectionObjectName(id, obj);
if (superColumnName == null)
{ // Fresh row
superColumnName = ((AbstractAttribute) embeddableAttrib).getJPAColumnName()
+ Constants.EMBEDDED_COLUMN_NAME_DELIMITER + (++lastEmbeddedObjectCount);
}
Map thriftSuperColumn = buildThriftSuperColumn(timestamp2, m, id, superColumn,
superColumnName, obj);
if (m.isCounterColumnType())
{
tr.addCounterSuperColumn((CounterSuperColumn) thriftSuperColumn.get(m.getTableName()));
}
else
{
tr.addSuperColumn((SuperColumn) thriftSuperColumn.get(m.getTableName()));
}
ecCacheHandler.addElementCollectionCacheMapping(id, obj, superColumnName);
}
}
}
else if (superColumnObject != null)
{
superColumnName = ((AbstractAttribute) embeddableAttrib).getJPAColumnName();
return buildThriftSuperColumn(timestamp2, m, id, superColumn, superColumnName, superColumnObject);
}
return null;
}
/**
* Builds the thrift super column.
*
* @param timestamp2
* the timestamp2
* @param m
* the m
* @param id
* the id
* @param superColumn
* the super column
* @param superColumnName
* the super column name
* @param obj
* the obj
* @return the map
*/
private Map buildThriftSuperColumn(long timestamp2, EntityMetadata m, Object id,
EmbeddableType superColumn, String superColumnName, Object obj)
{
Map thriftSuperColumns = null;
if (m.isCounterColumnType())
{
thriftSuperColumns = buildThriftCounterSuperColumn(m.getTableName(), superColumnName, superColumn, obj);
}
else
{
thriftSuperColumns = buildThriftSuperColumn(m.getTableName(), superColumnName, timestamp2, superColumn, obj);
}
return thriftSuperColumns;
}
/**
* Builds the thrift counter super column.
*
* @param tableName
* the table name
* @param superColumnName
* the super column name
* @param superColumn
* the super column
* @param counterSuperColumnObject
* the counter super column object
* @return the counter super column
*/
private Map buildThriftCounterSuperColumn(String tableName, String superColumnName,
EmbeddableType superColumn, Object counterSuperColumnObject)
{
Map thriftCounterSuperColumns = new HashMap();
Iterator iter = superColumn.getAttributes().iterator();
List thriftColumns = new ArrayList();
while (iter.hasNext())
{
Attribute column = iter.next();
Field field = (Field) column.getJavaMember();
String name = ((AbstractAttribute) column).getJPAColumnName();
String value = null;
try
{
value = PropertyAccessorHelper.getString(counterSuperColumnObject, field);
}
catch (PropertyAccessException exp)
{
// This is an entity column to be persisted in a super column
// family. It will be stored as a super column that would
// have just one column with the same name
if (log.isInfoEnabled())
{
log.info(exp.getMessage()
+ ". Possible case of entity column in a super column family. Will be treated as a super column.");
}
value = counterSuperColumnObject.toString();
}
if (null != value)
{
try
{
CounterColumn thriftColumn = new CounterColumn();
thriftColumn.setName(PropertyAccessorFactory.STRING.toBytes(name));
thriftColumn.setValue(Long.parseLong(value));
thriftColumns.add(thriftColumn);
tableName = ((AbstractAttribute) column).getTableName() != null ? ((AbstractAttribute) column)
.getTableName() : tableName;
CounterSuperColumn thriftSuperColumn = (CounterSuperColumn) thriftCounterSuperColumns
.get(tableName);
if (thriftSuperColumn == null)
{
thriftSuperColumn = new CounterSuperColumn();
thriftSuperColumn.setName(PropertyAccessorFactory.STRING.toBytes(superColumnName));
thriftCounterSuperColumns.put(tableName, thriftSuperColumn);
}
thriftSuperColumn.addToColumns(thriftColumn);
}
catch (NumberFormatException nfe)
{
log.error("For counter column arguments should be numeric type, Caused by: .", nfe);
throw new KunderaException(nfe);
}
}
}
return thriftCounterSuperColumns;
}
/**
* Builds the thrift super column.
*
* @param tableName
* the table name
* @param superColumnName
* the super column name
* @param timestamp
* the timestamp
* @param superColumn
* the super column
* @param superColumnObject
* the super column object
* @return the super column
* @throws PropertyAccessException
* the property access exception
*/
private Map buildThriftSuperColumn(String tableName, String superColumnName, long timestamp,
EmbeddableType superColumn, Object superColumnObject) throws PropertyAccessException
{
Map tableToSuperColumns = new HashMap();
List thriftColumns = new ArrayList();
Iterator iter = superColumn.getAttributes().iterator();
while (iter.hasNext())
{
AbstractAttribute column = (AbstractAttribute) iter.next();
Field field = (Field) column.getJavaMember();
String name = column.getJPAColumnName();
byte[] value = null;
try
{
value = PropertyAccessorHelper.get(superColumnObject, field);
}
catch (PropertyAccessException exp)
{
// This is an entity column to be persisted in a super column
// family. It will be stored as a super column that would
// have just one column with the same name
if (log.isInfoEnabled())
{
log.info(exp.getMessage()
+ ". Possible case of entity column in a super column family. Will be treated as a super column.");
}
value = superColumnObject.toString().getBytes();
}
if (null != value)
{
Column thriftColumn = new Column();
thriftColumn.setName(PropertyAccessorFactory.STRING.toBytes(name));
thriftColumn.setValue(value);
thriftColumn.setTimestamp(timestamp);
thriftColumns.add(thriftColumn);
String columnFamilyName = ((AbstractAttribute) column).getTableName() != null ? ((AbstractAttribute) column)
.getTableName() : tableName;
SuperColumn thriftSuperColumn = (SuperColumn) tableToSuperColumns.get(tableName);
if (thriftSuperColumn == null)
{
thriftSuperColumn = new SuperColumn();
thriftSuperColumn.setName(PropertyAccessorFactory.STRING.toBytes(superColumnName));
tableToSuperColumns.put(columnFamilyName, thriftSuperColumn);
}
thriftSuperColumn.addToColumns(thriftColumn);
}
}
return tableToSuperColumns;
}
/**
* Populate composite id.
*
* @param m
* the m
* @param entity
* the entity
* @param thriftColumnName
* the thrift column name
* @param thriftColumnValue
* the thrift column value
* @param metaModel
* the meta model
* @param attribute
* the attribute
* @param entityClazz
* the entity clazz
* @return the object
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private Object populateCompositeId(EntityMetadata m, Object entity, String thriftColumnName,
Object thriftColumnValue, MetamodelImpl metaModel, Attribute attribute, Class entityClazz)
throws InstantiationException, IllegalAccessException
{
Class javaType = ((AbstractAttribute) attribute).getBindableJavaType();
if (metaModel.isEmbeddable(javaType))
{
EmbeddableType compoundKey = metaModel.embeddable(javaType);
Object compoundKeyObject = null;
try
{
Set attributes = compoundKey.getAttributes();
entity = KunderaCoreUtils.initialize(entityClazz, entity);
for (Attribute compoundAttribute : attributes)
{
compoundKeyObject = compoundKeyObject == null ? getCompoundKey(attribute, entity)
: compoundKeyObject;
if (metaModel.isEmbeddable(((AbstractAttribute) compoundAttribute).getBindableJavaType()))
{
Object compoundObject = populateCompositeId(m, compoundKeyObject, thriftColumnName,
thriftColumnValue, metaModel, compoundAttribute, javaType);
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), compoundObject);
}
else if (((AbstractAttribute) compoundAttribute).getJPAColumnName().equals(thriftColumnName))
{
setFieldValueViaCQL(compoundKeyObject, thriftColumnValue, compoundAttribute);
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), compoundKeyObject);
break;
}
}
}
catch (IllegalArgumentException iaex)
{
// ignore as it might not represented within entity.
// No need for any logger message
}
catch (Exception e)
{
log.error("Error while retrieving data, Caused by: .", e);
throw new PersistenceException(e);
}
}
return entity;
}
/**
* Gets the compound key.
*
* @param attribute
* the attribute
* @param entity
* the entity
* @return the compound key
* @throws InstantiationException
* the instantiation exception
* @throws IllegalAccessException
* the illegal access exception
*/
private Object getCompoundKey(Attribute attribute, Object entity) throws InstantiationException,
IllegalAccessException
{
Object compoundKeyObject = null;
if (entity != null)
{
compoundKeyObject = PropertyAccessorHelper.getObject(entity, (Field) attribute.getJavaMember());
if (compoundKeyObject == null)
{
compoundKeyObject = ((AbstractAttribute) attribute).getBindableJavaType().newInstance();
}
}
return compoundKeyObject;
}
/**
* Populates collection field(s) into entity.
*
* @param entity
* the entity
* @param thriftColumnValue
* the thrift column value
* @param attribute
* the attribute
*/
private void setCollectionValue(Object entity, Object thriftColumnValue, Attribute attribute)
{
try
{
ByteBuffer valueByteBuffer = ByteBuffer.wrap((byte[]) thriftColumnValue);
if (Collection.class.isAssignableFrom(((Field) attribute.getJavaMember()).getType()))
{
Class> genericClass = PropertyAccessorHelper.getGenericClass((Field) attribute.getJavaMember());
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), CassandraDataTranslator
.decompose(((Field) attribute.getJavaMember()).getType(), valueByteBuffer, genericClass, true));
}
else if (((Field) attribute.getJavaMember()).getType().isAssignableFrom(Map.class))
{
List> mapGenericClasses = PropertyAccessorHelper.getGenericClasses((Field) attribute
.getJavaMember());
PropertyAccessorHelper.set(entity, (Field) attribute.getJavaMember(), CassandraDataTranslator
.decompose(((Field) attribute.getJavaMember()).getType(), valueByteBuffer, mapGenericClasses,
true));
}
}
catch (Exception e)
{
log.error("Error while setting field{} value via CQL, Caused by: .", attribute.getName(), e);
throw new PersistenceException(e);
}
}
}