public CFDefinition(CFMetaData cfm) {
    this.cfm = cfm;

    if (cfm.getKeyValidator() instanceof CompositeType) {
      this.hasCompositeKey = true;
      CompositeType keyComposite = (CompositeType) cfm.getKeyValidator();
      assert keyComposite.types.size() > 1;
      for (int i = 0; i < keyComposite.types.size(); i++) {
        ColumnIdentifier id = getKeyId(cfm, i);
        this.keys.put(
            id,
            new Name(
                cfm.ksName, cfm.cfName, id, Name.Kind.KEY_ALIAS, i, keyComposite.types.get(i)));
      }
    } else {
      this.hasCompositeKey = false;
      ColumnIdentifier id = getKeyId(cfm, 0);
      this.keys.put(
          id, new Name(cfm.ksName, cfm.cfName, id, Name.Kind.KEY_ALIAS, 0, cfm.getKeyValidator()));
    }

    if (cfm.comparator instanceof CompositeType) {
      this.isComposite = true;
      CompositeType composite = (CompositeType) cfm.comparator;
      /*
       * We are a "sparse" composite, i.e. a non-compact one, if either:
       *   - the last type of the composite is a ColumnToCollectionType
       *   - or we have one less alias than of composite types and the last type is UTF8Type.
       *
       * Note that this is not perfect: if someone upgrading from thrift "renames" all but
       * the last column alias, the cf will be considered "sparse" and he will be stuck with
       * that even though that might not be what he wants. But the simple workaround is
       * for that user to rename all the aliases at the same time in the first place.
       */
      int last = composite.types.size() - 1;
      AbstractType<?> lastType = composite.types.get(last);
      if (lastType instanceof ColumnToCollectionType
          || (cfm.getColumnAliases().size() == last && lastType instanceof UTF8Type)) {
        // "sparse" composite
        this.isCompact = false;
        this.value = null;
        assert cfm.getValueAlias() == null;
        // check for collection type
        if (lastType instanceof ColumnToCollectionType) {
          --last;
          this.hasCollections = true;
        } else {
          this.hasCollections = false;
        }

        for (int i = 0; i < last; i++) {
          ColumnIdentifier id = getColumnId(cfm, i);
          this.columns.put(
              id,
              new Name(
                  cfm.ksName, cfm.cfName, id, Name.Kind.COLUMN_ALIAS, i, composite.types.get(i)));
        }

        for (Map.Entry<ByteBuffer, ColumnDefinition> def : cfm.getColumn_metadata().entrySet()) {
          ColumnIdentifier id =
              new ColumnIdentifier(def.getKey(), cfm.getColumnDefinitionComparator(def.getValue()));
          this.metadata.put(
              id,
              new Name(
                  cfm.ksName,
                  cfm.cfName,
                  id,
                  Name.Kind.COLUMN_METADATA,
                  def.getValue().getValidator()));
        }
      } else {
        // "dense" composite
        this.isCompact = true;
        this.hasCollections = false;
        for (int i = 0; i < composite.types.size(); i++) {
          ColumnIdentifier id = getColumnId(cfm, i);
          this.columns.put(
              id,
              new Name(
                  cfm.ksName, cfm.cfName, id, Name.Kind.COLUMN_ALIAS, i, composite.types.get(i)));
        }
        this.value = createValue(cfm);
      }
    } else {
      this.isComposite = false;
      this.hasCollections = false;
      if (!cfm.getColumnAliases().isEmpty() || cfm.getColumn_metadata().isEmpty()) {
        // dynamic CF
        this.isCompact = true;
        ColumnIdentifier id = getColumnId(cfm, 0);
        Name name = new Name(cfm.ksName, cfm.cfName, id, Name.Kind.COLUMN_ALIAS, 0, cfm.comparator);
        this.columns.put(id, name);
        this.value = createValue(cfm);
      } else {
        // static CF
        this.isCompact = false;
        this.value = null;
        assert cfm.getValueAlias() == null;
        assert cfm.getColumnAliases() == null || cfm.getColumnAliases().isEmpty();
        for (Map.Entry<ByteBuffer, ColumnDefinition> def : cfm.getColumn_metadata().entrySet()) {
          ColumnIdentifier id =
              new ColumnIdentifier(def.getKey(), cfm.getColumnDefinitionComparator(def.getValue()));
          this.metadata.put(
              id,
              new Name(
                  cfm.ksName,
                  cfm.cfName,
                  id,
                  Name.Kind.COLUMN_METADATA,
                  def.getValue().getValidator()));
        }
      }
    }
    assert value == null || metadata.isEmpty();
  }
 private static ColumnIdentifier getValueId(CFMetaData cfm) {
   return cfm.getValueAlias() == null
       ? new ColumnIdentifier(DEFAULT_VALUE_ALIAS, false)
       : new ColumnIdentifier(cfm.getValueAlias(), definitionType);
 }