Java tutorial
/******************************************************************************* * * 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.pelops; import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.StringTokenizer; import javax.persistence.PersistenceException; import org.apache.cassandra.thrift.Column; import org.apache.cassandra.thrift.ColumnOrSuperColumn; import org.apache.cassandra.thrift.ColumnParent; import org.apache.cassandra.thrift.ConsistencyLevel; import org.apache.cassandra.thrift.CounterColumn; import org.apache.cassandra.thrift.CounterSuperColumn; import org.apache.cassandra.thrift.SlicePredicate; import org.apache.cassandra.thrift.SliceRange; import org.apache.cassandra.thrift.SuperColumn; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.scale7.cassandra.pelops.Bytes; import org.scale7.cassandra.pelops.Mutator; import org.scale7.cassandra.pelops.Pelops; import org.scale7.cassandra.pelops.Selector; import com.impetus.client.cassandra.common.CassandraIndexHelper; 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.db.SearchResult; import com.impetus.kundera.metadata.MetadataUtils; import com.impetus.kundera.metadata.model.EmbeddedColumn; import com.impetus.kundera.metadata.model.EntityMetadata; import com.impetus.kundera.metadata.model.Relation; 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.query.KunderaQuery.FilterClause; import com.impetus.kundera.query.QueryHandlerException; /** * Provides Pelops utility methods for data held in Column family based stores. * * @author amresh.singh */ final class PelopsDataHandler { /** The timestamp. */ private long timestamp = System.currentTimeMillis(); /** The log. */ private static Log log = LogFactory.getLog(PelopsDataHandler.class); /** * From thrift row. * * @param selector * the selector * @param clazz * the clazz * @param m * the m * @param rowKey * the row key * @param relationNames * the relation names * @param isWrapReq * the is wrap req * @return the object * @throws Exception * the exception */ Object fromThriftRow(Selector selector, Class<?> clazz, EntityMetadata m, String rowKey, List<String> relationNames, boolean isWrapReq, ConsistencyLevel consistencyLevel) throws Exception { List<String> superColumnNames = m.getEmbeddedColumnFieldNames(); Object e = null; if (!superColumnNames.isEmpty()) { if (m.isCounterColumnType()) { List<CounterSuperColumn> thriftCounterSuperColumns = new ArrayList<CounterSuperColumn>(); List<ByteBuffer> rowKeys = new ArrayList<ByteBuffer>(1); rowKeys.add(ByteBufferUtil.bytes(rowKey)); Map<ByteBuffer, List<ColumnOrSuperColumn>> thriftColumnOrSuperColumns = selector .getColumnOrSuperColumnsFromRows(new ColumnParent(m.getTableName()), rowKeys, Selector.newColumnsPredicateAll(true, 10000), consistencyLevel); getThriftCounterSuperColumn(thriftCounterSuperColumns, thriftColumnOrSuperColumns); if (thriftCounterSuperColumns != null) { e = fromCounterSuperColumnThriftRow(clazz, m, new ThriftRow(rowKey, m.getTableName(), null, null, null, thriftCounterSuperColumns), relationNames, isWrapReq); } } else { List<SuperColumn> thriftSuperColumns = selector.getSuperColumnsFromRow(m.getTableName(), rowKey, Selector.newColumnsPredicateAll(true, 10000), consistencyLevel); e = fromSuperColumnThriftRow(clazz, m, new ThriftRow(rowKey, m.getTableName(), null, thriftSuperColumns, null, null), relationNames, isWrapReq); } } else { List<ByteBuffer> rowKeys = new ArrayList<ByteBuffer>(1); ByteBuffer rKeyAsByte = ByteBufferUtil.bytes(rowKey); rowKeys.add(ByteBufferUtil.bytes(rowKey)); Map<ByteBuffer, List<ColumnOrSuperColumn>> columnOrSuperColumnsFromRow = selector .getColumnOrSuperColumnsFromRows(new ColumnParent(m.getTableName()), rowKeys, Selector.newColumnsPredicateAll(true, 10000), consistencyLevel); List<ColumnOrSuperColumn> colList = columnOrSuperColumnsFromRow.get(rKeyAsByte); if (m.isCounterColumnType()) { List<CounterColumn> thriftColumns = new ArrayList<CounterColumn>(colList.size()); for (ColumnOrSuperColumn col : colList) { if (col.super_column == null) { thriftColumns.add(col.getCounter_column()); } else { thriftColumns.addAll(col.getCounter_super_column().getColumns()); } } e = fromCounterColumnThriftRow(clazz, m, new ThriftRow(rowKey, m.getTableName(), null, null, thriftColumns, null), relationNames, isWrapReq); } else { List<Column> thriftColumns = new ArrayList<Column>(colList.size()); for (ColumnOrSuperColumn col : colList) { if (col.super_column == null) { thriftColumns.add(col.getColumn()); } else { thriftColumns.addAll(col.getSuper_column().getColumns()); } } e = fromColumnThriftRow(clazz, m, new ThriftRow(rowKey, m.getTableName(), thriftColumns, null, null, null), relationNames, isWrapReq); } } return e; } /** * @param thriftCounterSuperColumns * @param thriftColumnOrSuperColumns */ private void getThriftCounterSuperColumn(List<CounterSuperColumn> thriftCounterSuperColumns, Map<ByteBuffer, List<ColumnOrSuperColumn>> thriftColumnOrSuperColumns) { for (Map.Entry<ByteBuffer, List<ColumnOrSuperColumn>> entry : thriftColumnOrSuperColumns.entrySet()) { for (ColumnOrSuperColumn col : entry.getValue()) { thriftCounterSuperColumns.add(col.getCounter_super_column()); } } } /** * From thrift row. * * @param selector * the selector * @param clazz * the clazz * @param m * the m * @param relationNames * the relation names * @param isWrapReq * the is wrap req * @param rowIds * the row ids * @return the list * @throws Exception * the exception */ List<Object> fromThriftRow(Selector selector, Class<?> clazz, EntityMetadata m, List<String> relationNames, boolean isWrapReq, ConsistencyLevel consistencyLevel, Object... rowIds) throws Exception { List<Object> entities = new ArrayList<Object>(); if (rowIds != null) { for (Object rowKey : rowIds) { Object e = fromThriftRow(selector, clazz, m, rowKey.toString(), relationNames, isWrapReq, consistencyLevel); if (e != null) { entities.add(e); } } } return entities; } /** * From thrift row. * * @param <E> * the element type * @param clazz * the clazz * @param m * the m * @param tr * the cr * @return the e * @throws Exception * the exception */ // TODO: this is a duplicate code snippet and we need to refactor this. <E> E fromThriftRow(Class<E> clazz, EntityMetadata m, DataRow<SuperColumn> tr) throws Exception { // Instantiate a new instance E e = null; // Set row-key. Note: // PropertyAccessorHelper.setId(e, m, tr.getId()); // Get a name->field map for super-columns Map<String, Field> columnNameToFieldMap = new HashMap<String, Field>(); Map<String, Field> superColumnNameToFieldMap = new HashMap<String, Field>(); MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap, superColumnNameToFieldMap); Collection embeddedCollection = null; Field embeddedCollectionField = null; for (SuperColumn sc : tr.getColumns()) { if (e == null) { // Instantiate a new instance e = clazz.newInstance(); // Set row-key. Note: 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) { Relation relation = m.getRelation(name); String foreignKeys = PropertyAccessorFactory.STRING.fromBytes(String.class, value); Set<String> 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); } } } } } return e; } /** * Fetches data held in Thrift row columns and populates to Entity objects. * * @param clazz * the clazz * @param m * the m * @param thriftRow * the cr * @param relationNames * the relation names * @param isWrapperReq * the is wrapper req * @return the e * @throws Exception * the exception */ Object fromColumnThriftRow(Class<?> clazz, EntityMetadata m, ThriftRow thriftRow, List<String> relationNames, boolean isWrapperReq) throws Exception { // Instantiate a new instance Object entity = null; Map<String, Object> relations = new HashMap<String, Object>(); // Set row-key. // PropertyAccessorHelper.setId(entity, m, thriftRow.getId()); // PropertyAccessorHelper.set(entity, m.getIdColumn().getField(), // thriftRow.getId()); // Iterate through each column // if (m.isCounterColumnType()) // { // for (CounterColumn c : thriftRow.getCounterColumns()) // { // if (entity == null) // { // entity = clazz.newInstance(); // // Set row-key // PropertyAccessorHelper.setId(entity, m, thriftRow.getId()); // } // // String thriftColumnName = // PropertyAccessorFactory.STRING.fromBytes(String.class, c.getName()); // Long thriftColumnValue = c.getValue(); // // if (null == thriftColumnValue) // { // continue; // } // // // Check if this is a property, or a column representing foreign // // keys // com.impetus.kundera.metadata.model.Column column = // m.getColumn(thriftColumnName); // if (column != null) // { // try // { // if ((column.getField().getType().equals(Integer.class) || // column.getField().getType() // .equals(int.class)) // && thriftColumnValue != null) // { // PropertyAccessorHelper.set(entity, column.getField(), // thriftColumnValue.intValue()); // } // else // { // PropertyAccessorHelper.set(entity, column.getField(), // thriftColumnValue); // } // } // catch (PropertyAccessException pae) // { // log.warn(pae.getMessage()); // } // } // else // { // if (relationNames != null && !relationNames.isEmpty() && // relationNames.contains(thriftColumnName)) // { // // relations = new HashMap<String, Object>(); // String value = thriftColumnValue.toString(); // relations.put(thriftColumnName, value); // // prepare EnhanceEntity and return it // } // } // } // } // else // { for (Column c : thriftRow.getColumns()) { if (entity == null) { entity = clazz.newInstance(); // Set row-key PropertyAccessorHelper.setId(entity, m, thriftRow.getId()); } String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, c.getName()); byte[] thriftColumnValue = c.getValue(); if (null == thriftColumnValue) { continue; } // Check if this is a property, or a column representing foreign // keys com.impetus.kundera.metadata.model.Column column = m.getColumn(thriftColumnName); if (column != null) { try { PropertyAccessorHelper.set(entity, column.getField(), thriftColumnValue); } catch (PropertyAccessException pae) { log.warn(pae.getMessage()); } } else { if (relationNames != null && !relationNames.isEmpty() && relationNames.contains(thriftColumnName)) { // relations = new HashMap<String, Object>(); String value = PropertyAccessorFactory.STRING.fromBytes(String.class, thriftColumnValue); relations.put(thriftColumnName, value); // prepare EnhanceEntity and return it } } } return isWrapperReq && relations != null && !relations.isEmpty() ? new EnhanceEntity(entity, thriftRow.getId(), relations) : entity; // return new EnhanceEntity(entity, thriftRow.getId(), relations); } public Object fromCounterColumnThriftRow(Class<?> clazz, EntityMetadata m, ThriftRow thriftRow, List<String> relationNames, boolean isWrapperReq) throws Exception { // Instantiate a new instance Object entity = null; Map<String, Object> relations = new HashMap<String, Object>(); // Set row-key. // PropertyAccessorHelper.setId(entity, m, thriftRow.getId()); // PropertyAccessorHelper.set(entity, m.getIdColumn().getField(), // thriftRow.getId()); // Iterate through each column for (CounterColumn c : thriftRow.getCounterColumns()) { if (entity == null) { entity = clazz.newInstance(); // Set row-key PropertyAccessorHelper.setId(entity, m, thriftRow.getId()); } String thriftColumnName = PropertyAccessorFactory.STRING.fromBytes(String.class, c.getName()); Long thriftColumnValue = c.getValue(); if (null == thriftColumnValue) { continue; } // Check if this is a property, or a column representing foreign // keys com.impetus.kundera.metadata.model.Column column = m.getColumn(thriftColumnName); if (column != null) { try { if ((column.getField().getType().equals(Integer.class) || column.getField().getType().equals(int.class)) && thriftColumnValue != null) { PropertyAccessorHelper.set(entity, column.getField(), thriftColumnValue.intValue()); } else { PropertyAccessorHelper.set(entity, column.getField(), thriftColumnValue); } } catch (PropertyAccessException pae) { log.warn(pae.getMessage()); } } else { if (relationNames != null && !relationNames.isEmpty() && relationNames.contains(thriftColumnName)) { // relations = new HashMap<String, Object>(); String value = thriftColumnValue.toString(); relations.put(thriftColumnName, value); // prepare EnhanceEntity and return it } } } return isWrapperReq && relations != null && !relations.isEmpty() ? new EnhanceEntity(entity, thriftRow.getId(), relations) : entity; } /** * Fetches data held in Thrift row super columns and populates to Entity * objects. * * @param clazz * the clazz * @param m * the m * @param tr * the tr * @param relationNames * the relation names * @param isWrapReq * the is wrap req * @return the object * @throws Exception * the exception */ Object fromSuperColumnThriftRow(Class clazz, EntityMetadata m, ThriftRow tr, List<String> relationNames, boolean isWrapReq) throws Exception { // Instantiate a new instance Object entity = null; // Map to hold property-name=>foreign-entity relations Map<String, Set<String>> foreignKeysMap = new HashMap<String, Set<String>>(); // Get a name->field map for super-columns Map<String, Field> columnNameToFieldMap = new HashMap<String, Field>(); Map<String, Field> superColumnNameToFieldMap = new HashMap<String, Field>(); MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap, superColumnNameToFieldMap); // Add all super columns to entity Collection embeddedCollection = null; Field embeddedCollectionField = null; Map<String, Object> relations = new HashMap<String, Object>(); for (SuperColumn sc : tr.getSuperColumns()) { if (entity == null) { entity = clazz.newInstance(); // Set row-key PropertyAccessorHelper.setId(entity, m, tr.getId()); } String scName = PropertyAccessorFactory.STRING.fromBytes(String.class, sc.getName()); String scNamePrefix = null; // If this super column is variable in number (name#sequence // format) 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); 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); if (columnField != null) { PropertyAccessorHelper.set(embeddedObject, columnField, value); } else if (relationNames != null && !relationNames.isEmpty() && relationNames.contains(name)) { String valueAsStr = PropertyAccessorFactory.STRING.fromBytes(String.class, value); relations.put(name, valueAsStr); } } embeddedCollection.add(embeddedObject); // Add this embedded object to cache ElementCollectionCacheManager.getInstance().addElementCollectionCacheMapping(tr.getId(), embeddedObject, scName); } else { // For embedded super columns, create embedded entities and // add them to parent entity Field superColumnField = superColumnNameToFieldMap.get(scName); Object superColumnObj = null; if (superColumnField != null || (relationNames != null && !relationNames.isEmpty() && relationNames.contains(scName))) { Class superColumnClass = superColumnField != null ? superColumnField.getType() : null; superColumnObj = superColumnClass != null ? superColumnClass.newInstance() : null; for (Column column : sc.getColumns()) { String name = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName()); byte[] value = column.getValue(); Field columnField = columnNameToFieldMap.get(name); if (columnField != null) { try { PropertyAccessorHelper.set(superColumnObj, columnField, value); } catch (PropertyAccessException e) { // This is an entity column to be retrieved // in a // super column family. It's stored as a // super // column that would // have just one column with the same name log.debug(e.getMessage() + ". Possible case of entity column in a super column family. Will be treated as a super column."); com.impetus.kundera.metadata.model.Column col = m.getColumn(name); if (col != null) { superColumnObj = Bytes.toUTF8(value); } } } else { String valueAsStr = PropertyAccessorFactory.STRING.fromBytes(String.class, value); relations.put(name, valueAsStr); } } } if (superColumnField != null) { PropertyAccessorHelper.set(entity, superColumnField, superColumnObj); } } } // } if (embeddedCollection != null && !embeddedCollection.isEmpty()) { PropertyAccessorHelper.set(entity, embeddedCollectionField, embeddedCollection); } // EnhancedEntity e = EntityResolver.getEnhancedEntity(entity, // tr.getId(), foreignKeysMap); return isWrapReq && relations != null && !relations.isEmpty() ? new EnhanceEntity(entity, tr.getId(), relations) : entity; // return new EnhanceEntity(entity, tr.getId(), relations); } public Object fromCounterSuperColumnThriftRow(Class clazz, EntityMetadata m, ThriftRow tr, List<String> relationNames, boolean isWrapReq) throws Exception { // Instantiate a new instance Object entity = null; // Map to hold property-name=>foreign-entity relations Map<String, Set<String>> foreignKeysMap = new HashMap<String, Set<String>>(); // Get a name->field map for super-columns Map<String, Field> columnNameToFieldMap = new HashMap<String, Field>(); Map<String, Field> superColumnNameToFieldMap = new HashMap<String, Field>(); MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap, superColumnNameToFieldMap); // Add all super columns to entity Collection embeddedCollection = null; Field embeddedCollectionField = null; Map<String, Object> relations = new HashMap<String, Object>(); for (CounterSuperColumn sc : tr.getCounterSuperColumns()) { if (entity == null) { entity = clazz.newInstance(); // Set row-key PropertyAccessorHelper.setId(entity, m, tr.getId()); } String scName = PropertyAccessorFactory.STRING.fromBytes(String.class, sc.getName()); String scNamePrefix = null; // If this super column is variable in number (name#sequence // format) 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); for (CounterColumn column : sc.getColumns()) { String name = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName()); Long value = column.getValue(); if (value == null) { continue; } Field columnField = columnNameToFieldMap.get(name); if (columnField != null) { if ((columnField.getType().equals(Integer.class) || columnField.getType().equals(int.class)) && value != null) { int colValue = value.intValue(); PropertyAccessorHelper.set(embeddedObject, columnField, colValue); } else { PropertyAccessorHelper.set(embeddedObject, columnField, value); } // PropertyAccessorHelper.set(embeddedObject, // columnField, value); } else if (relationNames != null && !relationNames.isEmpty() && relationNames.contains(name)) { String valueAsStr = value.toString(); relations.put(name, valueAsStr); } } embeddedCollection.add(embeddedObject); // Add this embedded object to cache ElementCollectionCacheManager.getInstance().addElementCollectionCacheMapping(tr.getId(), embeddedObject, scName); } else { // For embedded super columns, create embedded entities and // add them to parent entity Field superColumnField = superColumnNameToFieldMap.get(scName); Object superColumnObj = null; if (superColumnField != null || (relationNames != null && !relationNames.isEmpty() && relationNames.contains(scName))) { Class superColumnClass = superColumnField != null ? superColumnField.getType() : null; for (CounterColumn column : sc.getColumns()) { String name = PropertyAccessorFactory.STRING.fromBytes(String.class, column.getName()); Long value = column.getValue(); Field columnField = columnNameToFieldMap.get(name); if (columnField != null) { try { if ((columnField.getType().equals(Integer.class) || columnField.getType().equals(int.class)) && value != null) { int colValue = value.intValue(); superColumnObj = populateColumnValue(superColumnClass, colValue, columnField); /* * if(superColumnClass.isPrimitive()) { * superColumnObj = colValue; } else { * superColumnObj = * PropertyAccessorHelper.getObject * (superColumnClass); * PropertyAccessorHelper * .set(superColumnObj, columnField, * colValue); } */} else { superColumnObj = populateColumnValue(superColumnClass, value, columnField); } } catch (PropertyAccessException e) { // This is an entity column to be retrieved // in a // super column family. It's stored as a // super // column that would // have just one column with the same name log.debug(e.getMessage() + ". Possible case of entity column in a super column family. Will be treated as a super column."); com.impetus.kundera.metadata.model.Column col = m.getColumn(name); if (col != null) { superColumnObj = value; } } } else { String valueAsStr = value.toString(); relations.put(name, valueAsStr); } } } if (superColumnField != null) { PropertyAccessorHelper.set(entity, superColumnField, superColumnObj); } } } if (embeddedCollection != null && !embeddedCollection.isEmpty()) { PropertyAccessorHelper.set(entity, embeddedCollectionField, embeddedCollection); } // EnhancedEntity e = EntityResolver.getEnhancedEntity(entity, // tr.getId(), foreignKeysMap); return isWrapReq && relations != null && !relations.isEmpty() ? new EnhanceEntity(entity, tr.getId(), relations) : entity; } /** * @param superColumnClass * @param value * @param columnField * @return */ private Object populateColumnValue(Class superColumnClass, Object value, Field columnField) { Object superColumnObj; if (superColumnClass.isPrimitive()) { superColumnObj = value; } else { superColumnObj = PropertyAccessorHelper.getObject(superColumnClass); PropertyAccessorHelper.set(superColumnObj, columnField, value); } return superColumnObj; } /** * Populate embedded object. * * @param sc * the sc * @param m * the m * @return the object * @throws Exception * the exception */ 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<String, Field> columnNameToFieldMap = new HashMap<String, Field>(); Map<String, Field> superColumnNameToFieldMap = new HashMap<String, Field>(); MetadataUtils.populateColumnAndSuperColumnMaps(m, columnNameToFieldMap, superColumnNameToFieldMap); // 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 * @return the base data accessor. thrift row * @throws Exception * the exception */ ThriftRow toThriftRow(Object e, String id, EntityMetadata m, String columnFamily) throws Exception { // timestamp to use in thrift column objects // long timestamp = System.currentTimeMillis(); ThriftRow tr = new ThriftRow(); tr.setColumnFamilyName(columnFamily); // column-family name tr.setId(id); // Id timestamp = getTimestamp(); // Add super columns to thrift row if (m.isCounterColumnType()) { addCounterSuperColumnsToThriftRow(timestamp, tr, m, e, id); } else { addSuperColumnsToThriftRow(timestamp, tr, m, e, id); } // Add columns to thrift row, only if there is no super column if (m.getEmbeddedColumnsAsList().isEmpty()) { if (m.isCounterColumnType()) { addCounterColumnsToThriftRow(timestamp, tr, m, e); } else { addColumnsToThriftRow(timestamp, tr, m, e); } } // Add relations entities as Foreign keys to a new super column created // internally // addRelationshipsToThriftRow(timestamp, tr, e, m); return tr; } List<ThriftRow> toIndexThriftRow(Object e, EntityMetadata m, String columnFamily) { List<ThriftRow> indexThriftRows = new ArrayList<PelopsDataHandler.ThriftRow>(); byte[] value = PropertyAccessorHelper.get(e, m.getIdColumn().getField()); for (EmbeddedColumn embeddedColumn : m.getEmbeddedColumnsAsList()) { Object embeddedObject = PropertyAccessorHelper.getObject(e, embeddedColumn.getField()); if (embeddedObject == null) { continue; } if (embeddedObject instanceof Collection) { ElementCollectionCacheManager ecCacheHandler = ElementCollectionCacheManager.getInstance(); for (Object obj : (Collection) embeddedObject) { for (com.impetus.kundera.metadata.model.Column column : embeddedColumn.getColumns()) { // Column Value String id = Bytes.toUTF8(value); String superColumnName = ecCacheHandler.getElementCollectionObjectName(id, obj); byte[] indexColumnValue = (id + Constants.INDEX_TABLE_EC_DELIMITER + superColumnName) .getBytes(); ThriftRow tr = constructIndexTableThriftRow(columnFamily, embeddedColumn, obj, column, indexColumnValue); if (tr != null) { indexThriftRows.add(tr); } } } } else { for (com.impetus.kundera.metadata.model.Column column : embeddedColumn.getColumns()) { ThriftRow tr = constructIndexTableThriftRow(columnFamily, embeddedColumn, embeddedObject, column, value); 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 embeddedColumn * Instance of {@link EmbeddedColumn} * @param obj * Embedded Object instance * @param column * Instance of {@link Column} * @param indexColumnValue * Name of Index Column * @return Instance of {@link ThriftRow} */ private ThriftRow constructIndexTableThriftRow(String columnFamily, EmbeddedColumn embeddedColumn, Object obj, com.impetus.kundera.metadata.model.Column column, byte[] indexColumnValue) { // Column Name Field columnField = column.getField(); byte[] indexColumnName = PropertyAccessorHelper.get(obj, columnField); ThriftRow tr = null; if (indexColumnName != null) { // Construct Index Table Thrift Row tr = new ThriftRow(); tr.setColumnFamilyName(columnFamily); // Index column-family name tr.setId(embeddedColumn.getField().getName() + Constants.INDEX_TABLE_ROW_KEY_DELIMITER + column.getField().getName()); // Id Column thriftColumn = new Column(); thriftColumn.setName(indexColumnName); thriftColumn.setValue(indexColumnValue); thriftColumn.setTimestamp(timestamp); tr.addColumn(thriftColumn); } return tr; } /** * Deletes records from inverted index table * * @param entity * @param metadata */ public void deleteRecordsFromIndexTable(Object entity, EntityMetadata metadata, ConsistencyLevel consistencyLevel) { Mutator mutator = Pelops.createMutator(PelopsUtils.generatePoolName(metadata.getPersistenceUnit())); String indexColumnFamily = CassandraIndexHelper.getInvertedIndexTableName(metadata.getTableName()); for (EmbeddedColumn embeddedColumn : metadata.getEmbeddedColumnsAsList()) { Object embeddedObject = PropertyAccessorHelper.getObject(entity, embeddedColumn.getField()); if (embeddedObject != null) { if (embeddedObject instanceof Collection) { for (Object obj : (Collection) embeddedObject) { for (com.impetus.kundera.metadata.model.Column column : embeddedColumn.getColumns()) { String rowKey = embeddedColumn.getField().getName() + Constants.INDEX_TABLE_ROW_KEY_DELIMITER + column.getField().getName(); byte[] columnName = PropertyAccessorHelper.get(obj, column.getField()); if (columnName != null) { mutator.deleteColumn(indexColumnFamily, rowKey, Bytes.fromByteArray(columnName)); } } } } else { for (com.impetus.kundera.metadata.model.Column column : embeddedColumn.getColumns()) { String rowKey = embeddedColumn.getField().getName() + Constants.INDEX_TABLE_ROW_KEY_DELIMITER + column.getField().getName(); byte[] columnName = PropertyAccessorHelper.get(embeddedObject, column.getField()); if (columnName != null) { mutator.deleteColumn(indexColumnFamily, rowKey, Bytes.fromByteArray(columnName)); } } } } } mutator.execute(consistencyLevel); } /** * @param columnFamilyName * @param m * @param filterClauseQueue * @return */ public List<SearchResult> getSearchResults(String columnFamilyName, EntityMetadata m, Queue<FilterClause> filterClauseQueue, String persistenceUnit, ConsistencyLevel consistencyLevel) { Selector selector = Pelops.createSelector(PelopsUtils.generatePoolName(persistenceUnit)); List<SearchResult> searchResults = new ArrayList<SearchResult>(); for (FilterClause o : filterClauseQueue) { SearchResult searchResult = new SearchResult(); FilterClause clause = ((FilterClause) o); String rowKey = clause.getProperty(); String columnName = clause.getValue(); String condition = clause.getCondition(); log.debug("rowKey:" + rowKey + ";columnName:" + columnName + ";condition:" + condition); // TODO: Second check unnecessary but unavoidable as filter clause // property is incorrectly passed as column name // Search based on Primary key if (rowKey.equals(m.getIdColumn().getField().getName()) || rowKey.equals(m.getIdColumn().getName())) { searchResult.setPrimaryKey(columnName); } else { // Search results in the form of thrift columns List<Column> thriftColumns = new ArrayList<Column>(); // EQUAL Operator if (condition.equals("=")) { Column thriftColumn = selector.getColumnFromRow(columnFamilyName, rowKey, columnName, consistencyLevel); thriftColumns.add(thriftColumn); } // LIKE operation else if (condition.equalsIgnoreCase("LIKE")) { searchColumnsInRange(columnFamilyName, consistencyLevel, selector, rowKey, columnName, thriftColumns, columnName.getBytes(), new byte[0]); } // Greater than operator else if (condition.equals(">")) { searchColumnsInRange(columnFamilyName, consistencyLevel, selector, rowKey, columnName, thriftColumns, columnName.getBytes(), new byte[0]); } // Less than Operator else if (condition.equals("<")) { searchColumnsInRange(columnFamilyName, consistencyLevel, selector, rowKey, columnName, thriftColumns, new byte[0], columnName.getBytes()); } // Greater than-equals to operator else if (condition.equals(">=")) { searchColumnsInRange(columnFamilyName, consistencyLevel, selector, rowKey, columnName, thriftColumns, columnName.getBytes(), new byte[0]); } // Less than equal to operator else if (condition.equals("<=")) { searchColumnsInRange(columnFamilyName, consistencyLevel, selector, rowKey, columnName, thriftColumns, new byte[0], columnName.getBytes()); } else { throw new QueryHandlerException(condition + " comparison operator not supported currently for Cassandra Inverted Index"); } // Construct search results out of these thrift columns for (Column thriftColumn : thriftColumns) { byte[] columnValue = thriftColumn.getValue(); String columnValueStr = Bytes.toUTF8(columnValue); PropertyAccessor<?> accessor = PropertyAccessorFactory .getPropertyAccessor(m.getIdColumn().getField()); Object value = null; if (columnValueStr.indexOf(Constants.INDEX_TABLE_EC_DELIMITER) > 0) { String pk = columnValueStr.substring(0, columnValueStr.indexOf(Constants.INDEX_TABLE_EC_DELIMITER)); String ecName = columnValueStr .substring( columnValueStr.indexOf(Constants.INDEX_TABLE_EC_DELIMITER) + Constants.INDEX_TABLE_EC_DELIMITER.length(), columnValueStr.length()); searchResult.setPrimaryKey(pk); searchResult.setEmbeddedColumnName( rowKey.substring(0, rowKey.indexOf(Constants.INDEX_TABLE_ROW_KEY_DELIMITER))); searchResult.addEmbeddedColumnValue(ecName); } else { value = accessor.fromBytes(m.getIdColumn().getField().getClass(), columnValue); searchResult.setPrimaryKey(value); } searchResults.add(searchResult); } } } return searchResults; } /** * Searches <code>searchString</code> into <code>columnFamilyName</code> * (usually a wide row column family) for a given <code>rowKey</code> from * start to finish columns. Adds matching thrift columns into * <code>thriftColumns</code> * * @param columnFamilyName * @param consistencyLevel * @param selector * @param rowKey * @param searchString * @param thriftColumns */ private void searchColumnsInRange(String columnFamilyName, ConsistencyLevel consistencyLevel, Selector selector, String rowKey, String searchString, List<Column> thriftColumns, byte[] start, byte[] finish) { SlicePredicate colPredicate = new SlicePredicate(); SliceRange sliceRange = new SliceRange(); sliceRange.setStart(start); sliceRange.setFinish(finish); colPredicate.setSlice_range(sliceRange); List<Column> allThriftColumns = selector.getColumnsFromRow(columnFamilyName, rowKey, colPredicate, consistencyLevel); for (Column column : allThriftColumns) { String colName = Bytes.toUTF8(column.getName()); // String colValue = Bytes.toUTF8(column.getValue()); if (colName.indexOf(searchString) >= 0) { thriftColumns.add(column); } } } private void addCounterColumnsToThriftRow(long timestamp2, ThriftRow tr, EntityMetadata m, Object e) { List<CounterColumn> counterColumns = new ArrayList<CounterColumn>(); // Iterate through each column-meta and populate that with field values for (com.impetus.kundera.metadata.model.Column column : m.getColumnsAsList()) { Field field = column.getField(); if (!(field.getType().isAssignableFrom(Set.class) || field.getType().isAssignableFrom(Collection.class))) { /* } else { */ String name = column.getName(); try { String value = PropertyAccessorHelper.getString(e, field); if (value != null) { CounterColumn col = new CounterColumn(); col.setName(PropertyAccessorFactory.STRING.toBytes(name)); col.setValue(new Long(value)); counterColumns.add(col); } else { log.debug("skipping column :" + name + " as value is not provided!"); } } catch (PropertyAccessException exp) { log.warn(exp.getMessage()); } } } tr.setCounterColumns(counterColumns); } private void addCounterSuperColumnsToThriftRow(long timestamp2, ThriftRow tr, EntityMetadata m, Object e, String id) { // Iterate through Super columns for (EmbeddedColumn superColumn : m.getEmbeddedColumnsAsList()) { Field superColumnField = superColumn.getField(); 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 "<Embedded object // field name>#<Unique sequence number> // 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) { continue; } if (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 = superColumn.getName() + Constants.EMBEDDED_COLUMN_NAME_DELIMITER + count; CounterSuperColumn thriftSuperColumn = buildThriftCounterSuperColumn(superColumnName, superColumn, obj); tr.addCounterSuperColumn(thriftSuperColumn); 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 = superColumn.getName() + Constants.EMBEDDED_COLUMN_NAME_DELIMITER + (++lastEmbeddedObjectCount); } CounterSuperColumn thriftSuperColumn = buildThriftCounterSuperColumn(superColumnName, superColumn, obj); tr.addCounterSuperColumn(thriftSuperColumn); } } } else { superColumnName = superColumn.getName(); CounterSuperColumn thriftSuperColumn = buildThriftCounterSuperColumn(superColumnName, superColumn, superColumnObject); tr.addCounterSuperColumn(thriftSuperColumn); } } } private CounterSuperColumn buildThriftCounterSuperColumn(String superColumnName, EmbeddedColumn superColumn, Object counterSuperColumnObject) { List<CounterColumn> thriftColumns = new ArrayList<CounterColumn>(); for (com.impetus.kundera.metadata.model.Column column : superColumn.getColumns()) { Field field = column.getField(); String name = column.getName(); 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 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); } catch (NumberFormatException nfe) { log.error("For counter column arguments should be numeric type, error caused by :" + nfe.getMessage()); throw new KunderaException("For counter column,arguments should be numeric type", nfe); } } } CounterSuperColumn thriftSuperColumn = new CounterSuperColumn(); thriftSuperColumn.setName(PropertyAccessorFactory.STRING.toBytes(superColumnName)); thriftSuperColumn.setColumns(thriftColumns); return thriftSuperColumn; } /** * Adds the columns to thrift row. * * @param timestamp * the timestamp * @param tr * the tr * @param m * the m * @param e * the e * @throws Exception * the exception */ private void addColumnsToThriftRow(long timestamp, ThriftRow tr, EntityMetadata m, Object e) throws Exception { List<Column> columns = new ArrayList<Column>(); // Iterate through each column-meta and populate that with field values for (com.impetus.kundera.metadata.model.Column column : m.getColumnsAsList()) { Field field = column.getField(); if (field.getType().isAssignableFrom(Set.class) || field.getType().isAssignableFrom(Collection.class)) { } else { String name = column.getName(); try { byte[] value = PropertyAccessorHelper.get(e, field); if (value != null) { Column col = new Column(); col.setName(PropertyAccessorFactory.STRING.toBytes(name)); col.setValue(value); col.setTimestamp(timestamp); columns.add(col); } else { log.debug("skipping column :" + name + " as value is not provided!"); } } catch (PropertyAccessException exp) { log.warn(exp.getMessage()); } } } tr.setColumns(columns); } /** * Adds the super columns to thrift row. * * @param timestamp * the timestamp * @param client * the client * @param tr * the tr * @param m * the m * @param e * the e * @param id * the id * @throws Exception * the exception */ private void addSuperColumnsToThriftRow(long timestamp, ThriftRow tr, EntityMetadata m, Object e, String id) throws Exception { // Iterate through Super columns for (EmbeddedColumn superColumn : m.getEmbeddedColumnsAsList()) { Field superColumnField = superColumn.getField(); 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 "<Embedded object // field name>#<Unique sequence number> // 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) { continue; } if (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 = superColumn.getName() + Constants.EMBEDDED_COLUMN_NAME_DELIMITER + count; SuperColumn thriftSuperColumn = buildThriftSuperColumn(superColumnName, timestamp, superColumn, obj); 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 = superColumn.getName() + Constants.EMBEDDED_COLUMN_NAME_DELIMITER + (++lastEmbeddedObjectCount); } SuperColumn thriftSuperColumn = buildThriftSuperColumn(superColumnName, timestamp, superColumn, obj); tr.addSuperColumn(thriftSuperColumn); ecCacheHandler.addElementCollectionCacheMapping(id, obj, superColumnName); } // TODO: Why are we not clearing EC Cache as in // HBaseDataHandler // Clear embedded collection cache for GC // ecCacheHandler.clearCache(); } } else { superColumnName = superColumn.getName(); SuperColumn thriftSuperColumn = buildThriftSuperColumn(superColumnName, timestamp, superColumn, superColumnObject); tr.addSuperColumn(thriftSuperColumn); } } } /** * Builds the thrift super column. * * @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 SuperColumn buildThriftSuperColumn(String superColumnName, long timestamp, EmbeddedColumn superColumn, Object superColumnObject) throws PropertyAccessException { List<Column> thriftColumns = new ArrayList<Column>(); for (com.impetus.kundera.metadata.model.Column column : superColumn.getColumns()) { Field field = column.getField(); String name = column.getName(); 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 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); } } SuperColumn thriftSuperColumn = new SuperColumn(); thriftSuperColumn.setName(PropertyAccessorFactory.STRING.toBytes(superColumnName)); thriftSuperColumn.setColumns(thriftColumns); return thriftSuperColumn; } /** * Gets the foreign keys from join table. * * @param <E> * the element type * @param inverseJoinColumnName * the inverse join column name * @param columns * the columns * @return the foreign keys from join table */ <E> List<E> getForeignKeysFromJoinTable(String inverseJoinColumnName, List<Column> columns) { List<E> foreignKeys = new ArrayList<E>(); 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)) { String val = PropertyAccessorFactory.STRING.fromBytes(String.class, thriftColumnValue); foreignKeys.add((E) val); } } catch (PropertyAccessException e) { continue; } } return foreignKeys; } /** * Utility class that represents a row in Cassandra DB. * * @author animesh.kumar */ class ThriftRow { /** Id of the row. */ private String id; /** name of the family. */ private String columnFamilyName; /** list of thrift columns from the row. */ private List<Column> columns; /** list of thrift super columns columns from the row. */ private List<SuperColumn> superColumns; /** list of thrift counter columns from the row. */ private List<CounterColumn> counterColumns; /** list of thrift counter super columns columns from the row. */ private List<CounterSuperColumn> counterSuperColumns; /** * default constructor. */ ThriftRow() { columns = new ArrayList<Column>(); superColumns = new ArrayList<SuperColumn>(); counterColumns = new ArrayList<CounterColumn>(); counterSuperColumns = new ArrayList<CounterSuperColumn>(); } /** * The Constructor. * * @param id * the id * @param columnFamilyName * the column family name * @param columns * the columns * @param superColumns * the super columns */ ThriftRow(String id, String columnFamilyName, List<Column> columns, List<SuperColumn> superColumns, List<CounterColumn> counterColumns, List<CounterSuperColumn> counterSuperColumns) { this.id = id; this.columnFamilyName = columnFamilyName; if (columns != null) { this.columns = columns; } if (superColumns != null) { this.superColumns = superColumns; } if (counterColumns != null) { this.counterColumns = counterColumns; } if (counterSuperColumns != null) { this.counterSuperColumns = counterSuperColumns; } } /** * Gets the id. * * @return the id */ String getId() { return id; } /** * Sets the id. * * @param id * the key to set */ void setId(String id) { this.id = id; } /** * Gets the column family name. * * @return the columnFamilyName */ String getColumnFamilyName() { return columnFamilyName; } /** * Sets the column family name. * * @param columnFamilyName * the columnFamilyName to set */ void setColumnFamilyName(String columnFamilyName) { this.columnFamilyName = columnFamilyName; } /** * Gets the columns. * * @return the columns */ List<Column> getColumns() { return columns; } /** * Sets the columns. * * @param columns * the columns to set */ void setColumns(List<Column> columns) { this.columns = columns; } /** * Adds the column. * * @param column * the column */ void addColumn(Column column) { columns.add(column); } /** * Gets the super columns. * * @return the superColumns */ List<SuperColumn> getSuperColumns() { return superColumns; } /** * Sets the super columns. * * @param superColumns * the superColumns to set */ void setSuperColumns(List<SuperColumn> superColumns) { this.superColumns = superColumns; } /** * Adds the super column. * * @param superColumn * the super column */ void addSuperColumn(SuperColumn superColumn) { this.superColumns.add(superColumn); } /** * @return the counterColumns */ public List<CounterColumn> getCounterColumns() { return counterColumns; } /** * @param counterColumns * the counterColumns to set */ public void setCounterColumns(List<CounterColumn> counterColumns) { this.counterColumns = counterColumns; } /** * Adds the counter column. * * @param counter * column the column */ void addCounterColumn(CounterColumn column) { counterColumns.add(column); } /** * @return the counterSuperColumns */ public List<CounterSuperColumn> getCounterSuperColumns() { return counterSuperColumns; } /** * @param counterSuperColumns * the counterSuperColumns to set */ public void setCounterSuperColumns(List<CounterSuperColumn> counterSuperColumns) { this.counterSuperColumns = counterSuperColumns; } /** * Adds the counter super column. * * @param countersuperColumn * the super column */ void addCounterSuperColumn(CounterSuperColumn superColumn) { this.counterSuperColumns.add(superColumn); } } /** * Gets the timestamp. * * @return the timestamp */ long getTimestamp() { return System.currentTimeMillis(); } }