package me.prettyprint.cassandra.service.template; import java.nio.ByteBuffer; import java.util.List; import me.prettyprint.cassandra.model.HColumnImpl; import me.prettyprint.cassandra.model.HSlicePredicate; import me.prettyprint.hector.api.Keyspace; import me.prettyprint.hector.api.Serializer; import me.prettyprint.hector.api.beans.HColumn; import me.prettyprint.hector.api.factory.HFactory; import me.prettyprint.hector.api.mutation.Mutator; import me.prettyprint.hector.api.query.SubCountQuery; import me.prettyprint.hector.api.query.SuperCountQuery; public abstract class SuperCfTemplate<K, SN, N> extends AbstractColumnFamilyTemplate<K, SN> { protected Serializer<N> subSerializer; public SuperCfTemplate(Keyspace keyspace, String columnFamily, Serializer<K> keySerializer, Serializer<SN> topSerializer, Serializer<N> subSerializer) { super(keyspace, columnFamily, keySerializer, topSerializer); this.subSerializer = subSerializer; } public Serializer<N> getSubSerializer() { return subSerializer; } /** * Checks if there are any columns at a row specified by key in a super column * family * * @param key * @return true if columns exist */ public boolean isColumnsExist(K key) { return countColumns(key) > 0; } /** * Checks if there are any columns at a row specified by key in a specific * super column * * @param key * @param superColumnName * the column name serializer of the child columns * @return true if columns exist */ public boolean isSubColumnsExist(K key, SN superColumnName) { return countSubColumns(key, superColumnName) > 0; } /** * @param key * @return the number of columns in a super column family at the specified row * key */ @SuppressWarnings("unchecked") public int countColumns(K key) { return countColumns(key, (SN) ALL_COLUMNS_START, (SN) ALL_COLUMNS_END, ALL_COLUMNS_COUNT); } /** * * @param key * @param superColumnName * @return the number of child columns in a specified super column */ @SuppressWarnings("unchecked") public int countSubColumns(K key, SN superColumnName) { return countSubColumns(key, superColumnName, (N) ALL_COLUMNS_START, (N) ALL_COLUMNS_END, ALL_COLUMNS_COUNT); } /** * Counts columns in the specified range of a super column family * * @param key * @param start * @param end * @param max * @return */ public int countColumns(K key, SN start, SN end, int max) { SuperCountQuery<K, SN> query = HFactory.createSuperCountQuery(keyspace, keySerializer, topSerializer); query.setKey(key); query.setColumnFamily(columnFamily); query.setRange(start, end, max); return query.execute().get(); } /** * Counts child columns in the specified range of a children in a specified * super column * * @param key * @param superColumnName * @param start * @param end * @param max * @return */ public int countSubColumns(K key, SN superColumnName, N start, N end, int max) { SubCountQuery<K, SN, N> query = HFactory.createSubCountQuery( keyspace, keySerializer, topSerializer, subSerializer); query.setKey(key); query.setColumnFamily(columnFamily); query.setSuperColumn(superColumnName); query.setRange(start, end, max); return query.execute().get(); } public <V> HColumn<N, V> querySingleSubColumn(K key, SN columnName, N subColumnName, Serializer<V> valueSerializer) { SuperCfResult<K,SN,N> result = doExecuteSlice(key, columnName, activeSlicePredicate); if (result == null) { return null; } HColumn<N,ByteBuffer> origCol = result.getColumn(subColumnName); // TODO make this far less hacky if ( columnName == null || origCol == null ) { return null; } return new HColumnImpl<N, V>(subColumnName, valueSerializer.fromByteBuffer(origCol.getValue()), origCol.getClock(), subSerializer, valueSerializer); } /** * Query super columns using the provided predicate instead of the internal one * @param key * @param predicate * @return */ public SuperCfResult<K, SN, N> querySuperColumns(K key, HSlicePredicate<SN> predicate) { return doExecuteSlice(key,null,predicate); } public SuperCfResult<K, SN, N> querySuperColumns(K key, List<SN> sColumnNames) { HSlicePredicate<SN> workingSlicePredicate = new HSlicePredicate<SN>(topSerializer); workingSlicePredicate.setColumnNames(sColumnNames); return doExecuteSlice(key, null, workingSlicePredicate); } public SuperCfResult<K, SN, N> querySuperColumns(List<K> keys, List<SN> sColumnNames) { HSlicePredicate<SN> workingSlicePredicate = new HSlicePredicate<SN>(topSerializer); workingSlicePredicate.setColumnNames(sColumnNames); return doExecuteMultigetSlice(keys, workingSlicePredicate); } public SuperCfResult<K, SN, N> querySuperColumns(List<K> keys) { return doExecuteMultigetSlice(keys, activeSlicePredicate); } public <T> T querySuperColumns(K key, List<SN> sColumnNames, SuperCfRowMapper<K, SN, N, T> mapper) { HSlicePredicate<SN> workingSlicePredicate = new HSlicePredicate<SN>(topSerializer); workingSlicePredicate.setColumnNames(sColumnNames); return mapper.mapRow(doExecuteSlice(key, null, workingSlicePredicate)); } public SuperCfResult<K, SN, N> querySuperColumns(K key) { return doExecuteSlice(key, null, activeSlicePredicate); } public SuperCfResult<K, SN, N> querySuperColumn(K key, SN sColumnName) { HSlicePredicate<SN> workingSlicePredicate = new HSlicePredicate<SN>(topSerializer); workingSlicePredicate.addColumnName(sColumnName); return doExecuteSlice(key, sColumnName, workingSlicePredicate); } public SuperCfUpdater<K, SN, N> createUpdater(K key, SN sColumnName) { return createUpdater(key).addSuperColumn(sColumnName); } public SuperCfUpdater<K, SN, N> createUpdater(K key) { SuperCfUpdater<K, SN, N> updater = new SuperCfUpdater<K, SN, N>(this, columnFactory); updater.addKey(key); return updater; } /** * Calls {@link SuperCfUpdater#updateInternal()} and {@link SuperCfUpdater#update()} * in that order before invoking {@link #executeIfNotBatched(Mutator)} on the underlying * upater's {@link Mutator} * @param updater */ public void update(SuperCfUpdater<K, SN, N> updater) { updater.updateInternal(); updater.update(); executeIfNotBatched(updater.getCurrentMutator()); } /** * Immediately delete the key and superColumn combination */ @Override public void deleteColumn(K key, SN sColumnName) { createMutator().superDelete(key, getColumnFamily(), sColumnName, topSerializer); } /** * Immediately delete the row */ @Override public void deleteRow(K key) { createMutator().delete(key, getColumnFamily(), null, null); } protected abstract SuperCfResult<K,SN,N> doExecuteSlice(K key, SN sColumnName, HSlicePredicate<SN> predicate); protected abstract SuperCfResult<K,SN,N> doExecuteMultigetSlice(List<K> keys, HSlicePredicate<SN> predicate); }