public void applyPropertiesTo(CFMetaData cfmd) throws RequestValidationException {
    cfmd.defaultValidator(defaultValidator)
        .keyValidator(keyValidator)
        .columnMetadata(getColumns())
        .setDense(isDense);

    cfmd.addColumnMetadataFromAliases(
        keyAliases, keyValidator, ColumnDefinition.Type.PARTITION_KEY);
    cfmd.addColumnMetadataFromAliases(
        columnAliases, comparator, ColumnDefinition.Type.CLUSTERING_KEY);
    if (valueAlias != null)
      cfmd.addColumnMetadataFromAliases(
          Collections.<ByteBuffer>singletonList(valueAlias),
          defaultValidator,
          ColumnDefinition.Type.COMPACT_VALUE);

    properties.applyToCFMetadata(cfmd);
  }
  public RowMutation mutationForKey(
      CFDefinition cfDef,
      ByteBuffer key,
      ColumnNameBuilder builder,
      boolean isRange,
      UpdateParameters params,
      ColumnGroupMap group)
      throws InvalidRequestException {
    QueryProcessor.validateKey(key);
    RowMutation rm = new RowMutation(cfDef.cfm.ksName, key);
    ColumnFamily cf = rm.addOrGet(columnFamily());

    if (columns.isEmpty() && builder.componentCount() == 0) {
      // No columns, delete the row
      cf.delete(new DeletionInfo(params.timestamp, params.localDeletionTime));
    } else {
      if (isRange) {
        ByteBuffer start = builder.copy().build();
        ByteBuffer end = builder.buildAsEndOfRange();
        QueryProcessor.validateColumnName(start); // If start is good, end is too
        cf.addAtom(params.makeRangeTombstone(start, end));
      } else {
        // Delete specific columns
        if (cfDef.isCompact) {
          ByteBuffer columnName = builder.build();
          QueryProcessor.validateColumnName(columnName);
          cf.addColumn(params.makeTombstone(columnName));
        } else {
          Iterator<Pair<CFDefinition.Name, Term>> iter = toRemove.iterator();
          while (iter.hasNext()) {
            Pair<CFDefinition.Name, Term> p = iter.next();
            CFDefinition.Name column = p.left;

            if (column.type.isCollection()) {
              CollectionType validator = (CollectionType) column.type;
              Term keySelected = p.right;

              if (keySelected == null) {
                // Delete the whole collection
                ByteBuffer start = builder.copy().add(column.name.key).build();
                QueryProcessor.validateColumnName(start);
                ColumnNameBuilder b = iter.hasNext() ? builder.copy() : builder;
                ByteBuffer end = b.add(column.name.key).buildAsEndOfRange();
                cf.addAtom(params.makeRangeTombstone(start, end));
              } else {
                builder.add(column.name.key);
                List<Term> args = Collections.singletonList(keySelected);

                Operation op;
                switch (validator.kind) {
                  case LIST:
                    op = ListOperation.DiscardKey(args);
                    break;
                  case SET:
                    op = SetOperation.Discard(args);
                    break;
                  case MAP:
                    op = MapOperation.DiscardKey(keySelected);
                    break;
                  default:
                    throw new InvalidRequestException("Unknown collection type: " + validator.kind);
                }

                op.execute(
                    cf,
                    builder,
                    validator,
                    params,
                    group == null ? null : group.getCollection(column.name.key));
              }
            } else {
              ColumnNameBuilder b = iter.hasNext() ? builder.copy() : builder;
              ByteBuffer columnName = b.add(column.name.key).build();
              QueryProcessor.validateColumnName(columnName);
              cf.addColumn(params.makeTombstone(columnName));
            }
          }
        }
      }
    }

    return rm;
  }