text:
package org.apache.cassandra.config;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cassandra.auth.DataResource;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.SuperColumnCompatibility;
import org.apache.cassandra.cql3.statements.CFStatement;
import org.apache.cassandra.cql3.statements.CreateTableStatement;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.compaction.AbstractCompactionStrategy;
import org.apache.cassandra.db.filter.ColumnFilter;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.utils.*;
import org.github.jamm.Unmetered;

/**
 * This class can be tricky to modify. Please read http://wiki.apache.org/cassandra/ConfigurationNotes for how to do so safely.
 */
@Unmetered
public final class CFMetaData
{
    public enum Flag
    {
        SUPER, COUNTER, DENSE, COMPOUND
    }

    private static final Pattern PATTERN_WORD_CHARS = Pattern.compile("\\w+");

    private static final Logger logger = LoggerFactory.getLogger(CFMetaData.class);

    public static final Serializer serializer = new Serializer();

    //REQUIRED
    public final UUID cfId;                           // internal id, never exposed to user
    public final String ksName;                       // name of keyspace
    public final String cfName;                       // name of this column family
    public final Pair<String, String> ksAndCFName;
    public final byte[] ksAndCFBytes;

    private final boolean isCounter;
    private final boolean isView;
    private final boolean isIndex;

    public volatile ClusteringComparator comparator;  // bytes, long, timeuuid, utf8, etc. This is built directly from clusteringColumns
    public final IPartitioner partitioner;            // partitioner the table uses
    private volatile AbstractType<?> keyValidator;

    private final Serializers serializers;

    // non-final, for now
    private volatile ImmutableSet<Flag> flags;
    private volatile boolean isDense;
    private volatile boolean isCompound;
    private volatile boolean isSuper;

    public volatile TableParams params = TableParams.DEFAULT;

    private volatile Map<ByteBuffer, DroppedColumn> droppedColumns = new HashMap<>();
    private volatile Triggers triggers = Triggers.none();
    private volatile Indexes indexes = Indexes.none();

    /*
     * All CQL3 columns definition are stored in the columnMetadata map.
     * On top of that, we keep separated collection of each kind of definition, to
     * 1) allow easy access to each kind and 2) for the partition key and
     * clustering key ones, those list are ordered by the "component index" of the
     * elements.
     */
    private volatile Map<ByteBuffer, ColumnDefinition> columnMetadata = new HashMap<>();
    private volatile List<ColumnDefinition> partitionKeyColumns;  // Always of size keyValidator.componentsCount, null padded if necessary
    private volatile List<ColumnDefinition> clusteringColumns;    // Of size comparator.componentsCount or comparator.componentsCount -1, null padded if necessary
    private volatile PartitionColumns partitionColumns;           // Always non-PK, non-clustering columns

    // For dense tables, this alias the single non-PK column the table contains (since it can only have one). We keep
    // that as convenience to access that column more easily (but we could replace calls by partitionColumns().iterator().next()
    // for those tables in practice).
    private volatile ColumnDefinition compactValueColumn;

    private volatile Set<ColumnDefinition> hiddenColumns;

    public final DataResource resource;

    //For hot path serialization it's often easier to store this info here
    private volatile ColumnFilter allColumnFilter;

    /**
     * These two columns are "virtual" (e.g. not persisted together with schema).
     *
     * They are stored here to avoid re-creating during SELECT and UPDATE queries, where
     * they are used to allow presenting supercolumn families in the CQL-compatible
     * format. See {@link SuperColumnCompatibility} for more details.
     **/
    private volatile ColumnDefinition superCfKeyColumn;
    private volatile ColumnDefinition superCfValueColumn;

    /** Caches a non-compact version of the metadata for compact tables to be used with the NO_COMPACT protocol option. */
    private volatile CFMetaData nonCompactCopy = null;

    public boolean isSuperColumnKeyColumn(ColumnDefinition cd)
    {
        return cd.name.equals(superCfKeyColumn.name);
    }

    public boolean isSuperColumnValueColumn(ColumnDefinition cd)
    {
        return cd.name.equals(superCfValueColumn.name);
    }

    public ColumnDefinition superColumnValueColumn()
    {
        return superCfValueColumn;
    }

    public ColumnDefinition superColumnKeyColumn() { return superCfKeyColumn; }

    /*
     * All of these methods will go away once CFMetaData becomes completely immutable.
     */
    public CFMetaData params(TableParams params)
    {
        this.params = params;
        return this;
    }

    public CFMetaData bloomFilterFpChance(double prop)
    {
        params = TableParams.builder(params).bloomFilterFpChance(prop).build();
        return this;
    }

    public CFMetaData caching(CachingParams prop)
    {
        params = TableParams.builder(params).caching(prop).build();
        return this;
    }

    public CFMetaData comment(String prop)
    {
        params = TableParams.builder(params).comment(prop).build();
        return this;
    }

    public CFMetaData compaction(CompactionParams prop)
    {
        params = TableParams.builder(params).compaction(prop).build();
        return this;
    }

    public CFMetaData compression(CompressionParams prop)
    {
        params = TableParams.builder(params).compression(prop).build();
        return this;
    }

    public CFMetaData dcLocalReadRepairChance(double prop)
    {
        params = TableParams.builder(params).dcLocalReadRepairChance(prop).build();
        return this;
    }

    public CFMetaData defaultTimeToLive(int prop)
    {
        params = TableParams.builder(params).defaultTimeToLive(prop).build();
        return this;
    }

    public CFMetaData gcGraceSeconds(int prop)
    {
        params = TableParams.builder(params).gcGraceSeconds(prop).build();
        return this;
    }

    public CFMetaData maxIndexInterval(int prop)
    {
        params = TableParams.builder(params).maxIndexInterval(prop).build();
        return this;
    }

    public CFMetaData memtableFlushPeriod(int prop)
    {
        params = TableParams.builder(params).memtableFlushPeriodInMs(prop).build();
        return this;
    }

    public CFMetaData minIndexInterval(int prop)
    {
        params = TableParams.builder(params).minIndexInterval(prop).build();
        return this;
    }

    public CFMetaData readRepairChance(double prop)
    {
        params = TableParams.builder(params).readRepairChance(prop).build();
        return this;
    }

    public CFMetaData crcCheckChance(double prop)
    {
        params = TableParams.builder(params).crcCheckChance(prop).build();
        return this;
    }

    public CFMetaData speculativeRetry(SpeculativeRetryParam prop)
    {
        params = TableParams.builder(params).speculativeRetry(prop).build();
        return this;
    }

    public CFMetaData extensions(Map<String, ByteBuffer> extensions)
    {
        params = TableParams.builder(params).extensions(extensions).build();
        return this;
    }

    public CFMetaData droppedColumns(Map<ByteBuffer, DroppedColumn> cols)
    {
        droppedColumns = cols;
        return this;
    }

    public CFMetaData triggers(Triggers prop)
    {
        triggers = prop;
        return this;
    }

    public CFMetaData indexes(Indexes indexes)
    {
        this.indexes = indexes;
        return this;
    }

    private CFMetaData(String keyspace,
                       String name,
                       UUID cfId,
                       boolean isSuper,
                       boolean isCounter,
                       boolean isDense,
                       boolean isCompound,
                       boolean isView,
                       List<ColumnDefinition> partitionKeyColumns,
                       List<ColumnDefinition> clusteringColumns,
                       PartitionColumns partitionColumns,
                       IPartitioner partitioner,
                       ColumnDefinition superCfKeyColumn,
                       ColumnDefinition superCfValueColumn)
    {
        this.cfId = cfId;
        this.ksName = keyspace;
        this.cfName = name;
        ksAndCFName = Pair.create(keyspace, name);
        byte[] ksBytes = FBUtilities.toWriteUTFBytes(ksName);
        byte[] cfBytes = FBUtilities.toWriteUTFBytes(cfName);
        ksAndCFBytes = Arrays.copyOf(ksBytes, ksBytes.length + cfBytes.length);
        System.arraycopy(cfBytes, 0, ksAndCFBytes, ksBytes.length, cfBytes.length);

        this.isDense = isSuper ? (isDense || SuperColumnCompatibility.recalculateIsDense(partitionColumns.regulars)) : isDense;

        this.isCompound = isCompound;
        this.isSuper = isSuper;
        this.isCounter = isCounter;
        this.isView = isView;

        EnumSet<Flag> flags = EnumSet.noneOf(Flag.class);
        if (isSuper)
            flags.add(Flag.SUPER);
        if (isCounter)
            flags.add(Flag.COUNTER);
        if (isDense)
            flags.add(Flag.DENSE);
        if (isCompound)
            flags.add(Flag.COMPOUND);
        this.flags = Sets.immutableEnumSet(flags);

        isIndex = cfName.contains(".");

        assert partitioner != null : "This assertion failure is probably due to accessing Schema.instance " +
                                     "from client-mode tools - See CASSANDRA-8143.";
        this.partitioner = partitioner;

        // A compact table should always have a clustering
        assert isCQLTable() || !clusteringColumns.isEmpty() : String.format("For table %s.%s, isDense=%b, isCompound=%b, clustering=%s", ksName, cfName, isDense, isCompound, clusteringColumns);

        // All tables should have a partition key
        assert !partitionKeyColumns.isEmpty() : String.format("Have no partition keys for table %s.%s", ksName, cfName);

        this.partitionKeyColumns = partitionKeyColumns;
        this.clusteringColumns = clusteringColumns;
        this.partitionColumns = partitionColumns;

        this.superCfKeyColumn = superCfKeyColumn;
        this.superCfValueColumn = superCfValueColumn;

        //This needs to happen before serializers are set
        //because they use comparator.subtypes()
        rebuild();

        this.serializers = new Serializers(this);
        this.resource = DataResource.table(ksName, cfName);
    }

    // This rebuild informations that are intrinsically duplicate of the table definition but
    // are kept because they are often useful in a different format.
    private void rebuild()
    {
        // A non-compact copy will be created lazily
        this.nonCompactCopy = null;

        if (isCompactTable())
        {
            this.compactValueColumn = isSuper() ?
                                      SuperColumnCompatibility.getCompactValueColumn(partitionColumns) :
                                      CompactTables.getCompactValueColumn(partitionColumns);
        }

        Map<ByteBuffer, ColumnDefinition> newColumnMetadata = Maps.newHashMapWithExpectedSize(partitionKeyColumns.size() + clusteringColumns.size() + partitionColumns.size());

        if (isSuper() && isDense())
        {
            CompactTables.DefaultNames defaultNames = SuperColumnCompatibility.columnNameGenerator(partitionKeyColumns, clusteringColumns, partitionColumns);
            if (superCfKeyColumn == null)
                superCfKeyColumn = SuperColumnCompatibility.getSuperCfKeyColumn(this, clusteringColumns, defaultNames);
            if (superCfValueColumn == null)
                superCfValueColumn = SuperColumnCompatibility.getSuperCfValueColumn(this, partitionColumns, superCfKeyColumn, defaultNames);

            for (ColumnDefinition def : partitionKeyColumns)
                newColumnMetadata.put(def.name.bytes, def);
            newColumnMetadata.put(clusteringColumns.get(0).name.bytes, clusteringColumns.get(0));
            newColumnMetadata.put(superCfKeyColumn.name.bytes, SuperColumnCompatibility.getSuperCfSschemaRepresentation(superCfKeyColumn));
            newColumnMetadata.put(superCfValueColumn.name.bytes, superCfValueColumn);
            newColumnMetadata.put(compactValueColumn.name.bytes, compactValueColumn);
            clusteringColumns = Arrays.asList(clusteringColumns().get(0));
            partitionColumns = PartitionColumns.of(compactValueColumn);
        }
        else
        {
            for (ColumnDefinition def : partitionKeyColumns)
                newColumnMetadata.put(def.name.bytes, def);
            for (ColumnDefinition def : clusteringColumns)
                newColumnMetadata.put(def.name.bytes, def);
            for (ColumnDefinition def : partitionColumns)
                newColumnMetadata.put(def.name.bytes, def);
        }
        this.columnMetadata = newColumnMetadata;

        List<AbstractType<?>> keyTypes = extractTypes(partitionKeyColumns);
        this.keyValidator = keyTypes.size() == 1 ? keyTypes.get(0) : CompositeType.getInstance(keyTypes);

        if (isSuper())
            this.comparator = new ClusteringComparator(clusteringColumns.get(0).type);
        else
            this.comparator = new ClusteringComparator(extractTypes(clusteringColumns));

        Set<ColumnDefinition> hiddenColumns;
        if (isCompactTable() && isDense && CompactTables.hasEmptyCompactValue(this))
        {
            hiddenColumns = Collections.singleton(compactValueColumn);
        }
        else if (isCompactTable() && !isDense && !isSuper)
        {
            hiddenColumns = Sets.newHashSetWithExpectedSize(clusteringColumns.size() + 1);
            hiddenColumns.add(compactValueColumn);
            hiddenColumns.addAll(clusteringColumns);

        }
        else
        {
            hiddenColumns = Collections.emptySet();
        }
        this.hiddenColumns = hiddenColumns;

        this.allColumnFilter = ColumnFilter.all(this);
    }

    public Indexes getIndexes()
    {
        return indexes;
    }

    public ColumnFilter getAllColumnFilter()
    {
        return allColumnFilter;
    }

    public static CFMetaData create(String ksName,
                                    String name,
                                    UUID cfId,
                                    boolean isDense,
                                    boolean isCompound,
                                    boolean isSuper,
                                    boolean isCounter,
                                    boolean isView,
                                    List<ColumnDefinition> columns,
                                    IPartitioner partitioner)
    {
        List<ColumnDefinition> partitions = new ArrayList<>();
        List<ColumnDefinition> clusterings = new ArrayList<>();
        PartitionColumns.Builder builder = PartitionColumns.builder();

        for (ColumnDefinition column : columns)
        {
            switch (column.kind)
            {
                case PARTITION_KEY:
                    partitions.add(column);
                    break;
                case CLUSTERING:
                    clusterings.add(column);
                    break;
                default:
                    builder.add(column);
                    break;
            }
        }

        Collections.sort(partitions);
        Collections.sort(clusterings);

        return new CFMetaData(ksName,
                              name,
                              cfId,
                              isSuper,
                              isCounter,
                              isDense,
                              isCompound,
                              isView,
                              partitions,
                              clusterings,
                              builder.build(),
                              partitioner,
                              null,
                              null);
    }

    public static List<AbstractType<?>> extractTypes(Iterable<ColumnDefinition> clusteringColumns)
    {
        List<AbstractType<?>> types = new ArrayList<>();
        for (ColumnDefinition def : clusteringColumns)
            types.add(def.type);
        return types;
    }

    public Set<Flag> flags()
    {
        return flags;
    }

    /**
     * There is a couple of places in the code where we need a CFMetaData object and don't have one readily available
     * and know that only the keyspace and name matter. This creates such "fake" metadata. Use only if you know what
     * you're doing.
     */
    public static CFMetaData createFake(String keyspace, String name)
    {
        return CFMetaData.Builder.create(keyspace, name).addPartitionKey("key", BytesType.instance).build();
    }

    public Triggers getTriggers()
    {
        return triggers;
    }

    // compilation should validate statement against a provided keyspace metadata
    public static CFMetaData compile(String cql, String keyspace)
    {
    	return compile(cql, KeyspaceMetadata.create(keyspace, KeyspaceParams.local()));
    }

    // Compiles a system metadata
    public static CFMetaData compile(String cql, KeyspaceMetadata ksm)
    {
        CFStatement parsed = (CFStatement)QueryProcessor.parseStatement(cql);
        parsed.prepareKeyspace(ksm.name);
        CreateTableStatement statement = (CreateTableStatement) ((CreateTableStatement.RawStatement) parsed).prepare(ksm, ksm.types).statement;

        return statement.metadataBuilder()
                        .withId(generateLegacyCfId(ksm.name, statement.columnFamily()))
                        .build()
                        .params(statement.params())
                        .readRepairChance(0.0)
                        .dcLocalReadRepairChance(0.0)
                        .gcGraceSeconds(0)
                        .memtableFlushPeriod((int) TimeUnit.HOURS.toMillis(1));
    }

    /**
     * Generates deterministic UUID from keyspace/columnfamily name pair.
     * This is used to generate the same UUID for {@code C* version < 2.1}
     *
     * Since 2.1, this is only used for system columnfamilies and tests.
     */
    public static UUID generateLegacyCfId(String ksName, String cfName)
    {
        return UUID.nameUUIDFromBytes(ArrayUtils.addAll(ksName.getBytes(), cfName.getBytes()));
    }

    public CFMetaData reloadIndexMetadataProperties(CFMetaData parent)
    {
        TableParams.Builder indexParams = TableParams.builder(parent.params);

        // Depends on parent's cache setting, turn on its index CF's cache.
        // Row caching is never enabled; see CASSANDRA-5732
        if (parent.params.caching.cacheKeys())
            indexParams.caching(CachingParams.CACHE_KEYS);
        else
            indexParams.caching(CachingParams.CACHE_NOTHING);

        indexParams.readRepairChance(0.0)
                   .dcLocalReadRepairChance(0.0)
                   .gcGraceSeconds(0);

        return params(indexParams.build());
    }

    /**
     * Returns a cached non-compact version of this table. Cached version has to be invalidated
     * every time the table is rebuilt.
     */
    public CFMetaData asNonCompact()
    {
        assert isCompactTable() : "Can't get non-compact version of a CQL table";

        // Note that this is racy, but re-computing the non-compact copy a few times on first uses isn't a big deal so
        // we don't bother.
        if (nonCompactCopy == null)
        {
            nonCompactCopy = copyOpts(new CFMetaData(ksName,
                                                     cfName,
                                                     cfId,
                                                     false,
                                                     isCounter,
                                                     false,
                                                     true,
                                                     isView,
                                                     copy(partitionKeyColumns),
                                                     copy(clusteringColumns),
                                                     copy(partitionColumns),
                                                     partitioner,
                                                     superCfKeyColumn,
                                                     superCfValueColumn),
                                      this);
        }

        return nonCompactCopy;
    }

    public CFMetaData copy()
    {
        return copy(cfId);
    }

    /**
     * Clones the CFMetaData, but sets a different cfId
     *
     * @param newCfId the cfId for the cloned CFMetaData
     * @return the cloned CFMetaData instance with the new cfId
     */
    public CFMetaData copy(UUID newCfId)
    {
        return copyOpts(new CFMetaData(ksName,
                                       cfName,
                                       newCfId,
                                       isSuper(),
                                       isCounter(),
                                       isDense(),
                                       isCompound(),
                                       isView(),
                                       copy(partitionKeyColumns),
                                       copy(clusteringColumns),
                                       copy(partitionColumns),
                                       partitioner,
                                       superCfKeyColumn,
                                       superCfValueColumn),
                        this);
    }

    public CFMetaData copy(IPartitioner partitioner)
    {
        return copyOpts(new CFMetaData(ksName,
                                       cfName,
                                       cfId,
                                       isSuper,
                                       isCounter,
                                       isDense,
                                       isCompound,
                                       isView,
                                       copy(partitionKeyColumns),
                                       copy(clusteringColumns),
                                       copy(partitionColumns),
                                       partitioner,
                                       superCfKeyColumn,
                                       superCfValueColumn),
                        this);
    }

    public CFMetaData copyWithNewCompactValueType(AbstractType<?> type)
    {
        assert isDense && compactValueColumn.type instanceof EmptyType && partitionColumns.size() == 1;
        return copyOpts(new CFMetaData(ksName,
                                       cfName,
                                       cfId,
                                       isSuper,
                                       isCounter,
                                       isDense,
                                       isCompound,
                                       isView,
                                       copy(partitionKeyColumns),
                                       copy(clusteringColumns),
                                       PartitionColumns.of(compactValueColumn.withNewType(type)),
                                       partitioner,
                                       superCfKeyColumn,
                                       superCfValueColumn),
                        this);
    }

    private static List<ColumnDefinition> copy(List<ColumnDefinition> l)
    {
        List<ColumnDefinition> copied = new ArrayList<>(l.size());
        for (ColumnDefinition cd : l)
            copied.add(cd.copy());
        return copied;
    }

    private static PartitionColumns copy(PartitionColumns columns)
    {
        PartitionColumns.Builder newColumns = PartitionColumns.builder();
        for (ColumnDefinition cd : columns)
            newColumns.add(cd.copy());
        return newColumns.build();
    }

    @VisibleForTesting
    public static CFMetaData copyOpts(CFMetaData newCFMD, CFMetaData oldCFMD)
    {
        return newCFMD.params(oldCFMD.params)
                      .droppedColumns(new HashMap<>(oldCFMD.droppedColumns))
                      .triggers(oldCFMD.triggers)
                      .indexes(oldCFMD.indexes);
    }

    /**
     * generate a column family name for an index corresponding to the given column.
     * This is NOT the same as the index's name! This is only used in sstable filenames and is not exposed to users.
     *
     * @param info A definition of the column with index
     *
     * @return name of the index ColumnFamily
     */
    public String indexColumnFamilyName(IndexMetadata info)
    {
        // TODO simplify this when info.index_name is guaranteed to be set
        return cfName + Directories.SECONDARY_INDEX_NAME_SEPARATOR + info.name;
    }

    /**
     * true if this CFS contains secondary index data.
     */
    public boolean isIndex()
    {
        return isIndex;
    }

    public DecoratedKey decorateKey(ByteBuffer key)
    {
        return partitioner.decorateKey(key);
    }

    public Map<ByteBuffer, ColumnDefinition> getColumnMetadata()
    {
        return columnMetadata;
    }

    /**
     *
     * @return The name of the parent cf if this is a seconday index
     */
    public String getParentColumnFamilyName()
    {
        return isIndex ? cfName.substring(0, cfName.indexOf('.')) : null;
    }

    public ReadRepairDecision newReadRepairDecision()
    {
        double chance = ThreadLocalRandom.current().nextDouble();
        if (params.readRepairChance > chance)
            return ReadRepairDecision.GLOBAL;

        if (params.dcLocalReadRepairChance > chance)
            return ReadRepairDecision.DC_LOCAL;

        return ReadRepairDecision.NONE;
    }

    public AbstractType<?> getColumnDefinitionNameComparator(ColumnDefinition.Kind kind)
    {
        return (isSuper() && kind == ColumnDefinition.Kind.REGULAR) || (isStaticCompactTable() && kind == ColumnDefinition.Kind.STATIC)
             ? thriftColumnNameType()
             : UTF8Type.instance;
    }

    public AbstractType<?> getKeyValidator()
    {
        return keyValidator;
    }

    public Collection<ColumnDefinition> allColumns()
    {
        return columnMetadata.values();
    }

    private Iterator<ColumnDefinition> nonPkColumnIterator()
    {
        final boolean noNonPkColumns = isCompactTable() && CompactTables.hasEmptyCompactValue(this) && !isSuper();
        if (noNonPkColumns)
        {
            return Collections.<ColumnDefinition>emptyIterator();
        }
        else if (isStaticCompactTable())
        {
            return partitionColumns.statics.selectOrderIterator();
        }
        else if (isSuper())
        {
            if (isDense)
                return Iterators.forArray(superCfKeyColumn, superCfValueColumn);
            else
                return Iterators.filter(partitionColumns.iterator(), (c) -> !c.type.isCollection());
        }
        else
            return partitionColumns().selectOrderIterator();
    }

    // An iterator over all column definitions but that respect the order of a SELECT *.
    // This also hides the clustering/regular columns for a non-CQL3 non-dense table for backward compatibility
    // sake (those are accessible through thrift but not through CQL currently) and exposes the key and value
    // columns for supercolumn family.
    public Iterator<ColumnDefinition> allColumnsInSelectOrder()
    {
        return new AbstractIterator<ColumnDefinition>()
        {
            private final Iterator<ColumnDefinition> partitionKeyIter = partitionKeyColumns.iterator();
            private final Iterator<ColumnDefinition> clusteringIter = isStaticCompactTable() ? Collections.<ColumnDefinition>emptyIterator() : clusteringColumns.iterator();
            private final Iterator<ColumnDefinition> otherColumns = nonPkColumnIterator();

            protected ColumnDefinition computeNext()
            {
                if (partitionKeyIter.hasNext())
                    return partitionKeyIter.next();

                if (clusteringIter.hasNext())
                    return clusteringIter.next();

                return otherColumns.hasNext() ? otherColumns.next() : endOfData();
            }
        };
    }

    public Iterable<ColumnDefinition> primaryKeyColumns()
    {
        return Iterables.concat(partitionKeyColumns, clusteringColumns);
    }

    public List<ColumnDefinition> partitionKeyColumns()
    {
        return partitionKeyColumns;
    }

    public List<ColumnDefinition> clusteringColumns()
    {
        return clusteringColumns;
    }

    public PartitionColumns partitionColumns()
    {
        return partitionColumns;
    }

    public ColumnDefinition compactValueColumn()
    {
        return compactValueColumn;
    }

    public ClusteringComparator getKeyValidatorAsClusteringComparator()
    {
        boolean isCompound = keyValidator instanceof CompositeType;
        List<AbstractType<?>> types = isCompound
                                    ? ((CompositeType) keyValidator).types
                                    : Collections.<AbstractType<?>>singletonList(keyValidator);
        return new ClusteringComparator(types);
    }

    public static ByteBuffer serializePartitionKey(ClusteringPrefix keyAsClustering)
    {
        // TODO: we should stop using Clustering for partition keys. Maybe we can add
        // a few methods to DecoratedKey so we don't have to (note that while using a Clustering
        // allows to use buildBound(), it's actually used for partition keys only when every restriction
        // is an equal, so we could easily create a specific method for keys for that.
        if (keyAsClustering.size() == 1)
            return keyAsClustering.get(0);

        ByteBuffer[] values = new ByteBuffer[keyAsClustering.size()];
        for (int i = 0; i < keyAsClustering.size(); i++)
            values[i] = keyAsClustering.get(i);
        return CompositeType.build(values);
    }

    public Map<ByteBuffer, DroppedColumn> getDroppedColumns()
    {
        return droppedColumns;
    }

    public ColumnDefinition getDroppedColumnDefinition(ByteBuffer name)
    {
        return getDroppedColumnDefinition(name, false);
    }

    /**
     * Returns a "fake" ColumnDefinition corresponding to the dropped column {@code name}
     * of {@code null} if there is no such dropped column.
     *
     * @param name - the column name
     * @param isStatic - whether the column was a static column, if known
     */
    public ColumnDefinition getDroppedColumnDefinition(ByteBuffer name, boolean isStatic)
    {
        DroppedColumn dropped = droppedColumns.get(name);
        if (dropped == null)
            return null;

        // We need the type for deserialization purpose. If we don't have the type however,
        // it means that it's a dropped column from before 3.0, and in that case using
        // BytesType is fine for what we'll be using it for, even if that's a hack.
        AbstractType<?> type = dropped.type == null ? BytesType.instance : dropped.type;
        return isStatic
               ? ColumnDefinition.staticDef(this, name, type)
               : ColumnDefinition.regularDef(this, name, type);
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true;

        if (!(o instanceof CFMetaData))
            return false;

        CFMetaData other = (CFMetaData) o;

        return Objects.equal(cfId, other.cfId)
            && Objects.equal(flags, other.flags)
            && Objects.equal(ksName, other.ksName)
            && Objects.equal(cfName, other.cfName)
            && Objects.equal(params, other.params)
            && Objects.equal(comparator, other.comparator)
            && Objects.equal(keyValidator, other.keyValidator)
            && Objects.equal(columnMetadata, other.columnMetadata)
            && Objects.equal(droppedColumns, other.droppedColumns)
            && Objects.equal(triggers, other.triggers)
            && Objects.equal(indexes, other.indexes);
    }

    @Override
    public int hashCode()
    {
        return new HashCodeBuilder(29, 1597)
            .append(cfId)
            .append(ksName)
            .append(cfName)
            .append(flags)
            .append(comparator)
            .append(params)
            .append(keyValidator)
            .append(columnMetadata)
            .append(droppedColumns)
            .append(triggers)
            .append(indexes)
            .toHashCode();
    }

    /**
     * Updates CFMetaData in-place to match cfm
     *
     * @return true if any change was made which impacts queries/updates on the table,
     *         e.g. any columns or indexes were added, removed, or altered; otherwise, false is returned.
     *         Used to determine whether prepared statements against this table need to be re-prepared.
     * @throws ConfigurationException if ks/cf names or cf ids didn't match
     */
    @VisibleForTesting
    public boolean apply(CFMetaData cfm) throws ConfigurationException
    {
        logger.debug("applying {} to {}", cfm, this);

        validateCompatibility(cfm);

        partitionKeyColumns = cfm.partitionKeyColumns;
        clusteringColumns = cfm.clusteringColumns;

        boolean changeAffectsStatements = !partitionColumns.equals(cfm.partitionColumns);
        partitionColumns = cfm.partitionColumns;
        superCfKeyColumn = cfm.superCfKeyColumn;
        superCfValueColumn = cfm.superCfValueColumn;

        isDense = cfm.isDense;
        isCompound = cfm.isCompound;
        isSuper = cfm.isSuper;

        flags = cfm.flags;

        rebuild();

        // compaction thresholds are checked by ThriftValidation. We shouldn't be doing
        // validation on the apply path; it's too late for that.

        params = cfm.params;

        if (!cfm.droppedColumns.isEmpty())
            droppedColumns = cfm.droppedColumns;

        triggers = cfm.triggers;

        changeAffectsStatements |= !indexes.equals(cfm.indexes);
        indexes = cfm.indexes;

        logger.debug("application result is {}", this);

        return changeAffectsStatements;
    }

    public void validateCompatibility(CFMetaData cfm) throws ConfigurationException
    {
        // validate
        if (!cfm.ksName.equals(ksName))
            throw new ConfigurationException(String.format("Keyspace mismatch (found %s; expected %s)",
                                                           cfm.ksName, ksName));
        if (!cfm.cfName.equals(cfName))
            throw new ConfigurationException(String.format("Column family mismatch (found %s; expected %s)",
                                                           cfm.cfName, cfName));
        if (!cfm.cfId.equals(cfId))
            throw new ConfigurationException(String.format("Column family ID mismatch (found %s; expected %s)",
                                                           cfm.cfId, cfId));
    }

    public static Class<? extends AbstractCompactionStrategy> createCompactionStrategy(String className) throws ConfigurationException
    {
        className = className.contains(".") ? className : "org.apache.cassandra.db.compaction." + className;
        Class<AbstractCompactionStrategy> strategyClass = FBUtilities.classForName(className, "compaction strategy");
        if (!AbstractCompactionStrategy.class.isAssignableFrom(strategyClass))
            throw new ConfigurationException(String.format("Specified compaction strategy class (%s) is not derived from AbstractCompactionStrategy", className));

        return strategyClass;
    }

    public static AbstractCompactionStrategy createCompactionStrategyInstance(ColumnFamilyStore cfs,
                                                                              CompactionParams compactionParams)
    {
        try
        {
            Constructor<? extends AbstractCompactionStrategy> constructor =
                compactionParams.klass().getConstructor(ColumnFamilyStore.class, Map.class);
            return constructor.newInstance(cfs, compactionParams.options());
        }
        catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the ColumnDefinition for {@code name}.
     */
    public ColumnDefinition getColumnDefinition(ColumnIdentifier name)
    {
        return getColumnDefinition(name.bytes);
    }

    // In general it is preferable to work with ColumnIdentifier to make it
    // clear that we are talking about a CQL column, not a cell name, but there
    // is a few cases where all we have is a ByteBuffer (when dealing with IndexExpression
    // for instance) so...
    public ColumnDefinition getColumnDefinition(ByteBuffer name)
    {
        return columnMetadata.get(name);
    }

    // Returns only columns that are supposed to be visible through CQL layer
    public ColumnDefinition getColumnDefinitionForCQL(ColumnIdentifier name)
    {
        return getColumnDefinitionForCQL(name.bytes);
    }

    public ColumnDefinition getColumnDefinitionForCQL(ByteBuffer name)
    {
        ColumnDefinition cd = getColumnDefinition(name);
        return hiddenColumns.contains(cd) ? null : cd;
    }

    public static boolean isNameValid(String name)
    {
        return name != null && !name.isEmpty()
               && name.length() <= SchemaConstants.NAME_LENGTH && PATTERN_WORD_CHARS.matcher(name).matches();
    }

    public CFMetaData validate() throws ConfigurationException
    {
    	return validate(Schema.instance.getKSMetaData(ksName));
    }

    public CFMetaData validate(KeyspaceMetadata ksm) throws ConfigurationException
    {
        rebuild();

        if (!isNameValid(ksName))
            throw new ConfigurationException(String.format("Keyspace name must not be empty, more than %s characters long, or contain non-alphanumeric-underscore characters (got \"%s\")", SchemaConstants.NAME_LENGTH, ksName));
        if (!isNameValid(cfName))
            throw new ConfigurationException(String.format("ColumnFamily name must not be empty, more than %s characters long, or contain non-alphanumeric-underscore characters (got \"%s\")", SchemaConstants.NAME_LENGTH, cfName));

        params.validate();

        for (int i = 0; i < comparator.size(); i++)
        {
            if (comparator.subtype(i) instanceof CounterColumnType)
                throw new ConfigurationException("CounterColumnType is not a valid comparator");
        }
        if (keyValidator instanceof CounterColumnType)
            throw new ConfigurationException("CounterColumnType is not a valid key validator");

        // Mixing counter with non counter columns is not supported (#2614)
        if (isCounter())
        {
            for (ColumnDefinition def : partitionColumns())
                if (!(def.type instanceof CounterColumnType) && (!isSuper() || isSuperColumnValueColumn(def)))
                    throw new ConfigurationException("Cannot add a non counter column (" + def + ") in a counter column family");
        }
        else
        {
            for (ColumnDefinition def : allColumns())
                if (def.type instanceof CounterColumnType)
                    throw new ConfigurationException("Cannot add a counter column (" + def.name + ") in a non counter column family");
        }

        if (!indexes.isEmpty() && isSuper())
            throw new ConfigurationException("Secondary indexes are not supported on super column families");

        Set<String> indexNames = ksm == null ? new HashSet<>() : ksm.existingIndexNames(cfName);
        for (IndexMetadata index : indexes)
        {
            // check index names against this CF _and_ globally
            if (indexNames.contains(index.name))
                throw new ConfigurationException("Duplicate index name " + index.name);
            indexNames.add(index.name);

            index.validate(this);
        }

        return this;
    }

    // The comparator to validate the definition name with thrift.
    public AbstractType<?> thriftColumnNameType()
    {
        if (isSuper())
        {
            ColumnDefinition def = compactValueColumn();
            assert def != null && def.type instanceof MapType;
            return ((MapType)def.type).nameComparator();
        }

        assert isStaticCompactTable();
        return clusteringColumns.get(0).type;
    }

    public CFMetaData addColumnDefinition(ColumnDefinition def) throws ConfigurationException
    {
        if (columnMetadata.containsKey(def.name.bytes))
            throw new ConfigurationException(String.format("Cannot add column %s, a column with the same name already exists", def.name));

        return addOrReplaceColumnDefinition(def);
    }

    // This method doesn't check if a def of the same name already exist and should only be used when we
    // know this cannot happen.
    public CFMetaData addOrReplaceColumnDefinition(ColumnDefinition def)
    {
        // Adds the definition and rebuild what is necessary. We could call rebuild() but it's not too hard to
        // only rebuild the necessary bits.
        switch (def.kind)
        {
            case PARTITION_KEY:
                partitionKeyColumns.set(def.position(), def);
                break;
            case CLUSTERING:
                clusteringColumns.set(def.position(), def);
                break;
            case REGULAR:
            case STATIC:
                PartitionColumns.Builder builder = PartitionColumns.builder();
                for (ColumnDefinition column : partitionColumns)
                    if (!column.name.equals(def.name))
                        builder.add(column);
                builder.add(def);
                partitionColumns = builder.build();
                // If dense, we must have modified the compact value since that's the only one we can have.
                if (isDense())
                    this.compactValueColumn = def;
                break;
        }
        this.columnMetadata.put(def.name.bytes, def);
        return this;
    }

    public boolean removeColumnDefinition(ColumnDefinition def)
    {
        assert !def.isPartitionKey();
        boolean removed = columnMetadata.remove(def.name.bytes) != null;
        if (removed)
            partitionColumns = partitionColumns.without(def);
        return removed;
    }

    /**
     * Adds the column definition as a dropped column, recording the drop with the provided timestamp.
     */
    public void recordColumnDrop(ColumnDefinition def, long timeMicros)
    {
        recordColumnDrop(def, timeMicros, true);
    }

    @VisibleForTesting
    public void recordColumnDrop(ColumnDefinition def, long timeMicros, boolean preserveKind)
    {
        droppedColumns.put(def.name.bytes, new DroppedColumn(def.name.toString(), preserveKind ? def.kind : null, def.type, timeMicros));
    }

    public void renameColumn(ColumnIdentifier from, ColumnIdentifier to) throws InvalidRequestException
    {
        ColumnDefinition def = getColumnDefinitionForCQL(from);

        if (def == null)
            throw new InvalidRequestException(String.format("Cannot rename unknown column %s in keyspace %s", from, cfName));

        if (getColumnDefinition(to) != null)
            throw new InvalidRequestException(String.format("Cannot rename column %s to %s in keyspace %s; another column of that name already exist", from, to, cfName));

        if (def.isPartOfCellName(isCQLTable(), isSuper()) && !isDense())
        {
            throw new InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", from));
        }

        if (!getIndexes().isEmpty())
        {
            ColumnFamilyStore store = Keyspace.openAndGetStore(this);
            Set<IndexMetadata> dependentIndexes = store.indexManager.getDependentIndexes(def);
            if (!dependentIndexes.isEmpty())
                throw new InvalidRequestException(String.format("Cannot rename column %s because it has " +
                                                                "dependent secondary indexes (%s)",
                                                                from,
                                                                dependentIndexes.stream()
                                                                                .map(i -> i.name)
                                                                                .collect(Collectors.joining(","))));
        }

        if (isSuper() && isDense())
        {
            if (isSuperColumnKeyColumn(def))
            {
                columnMetadata.remove(superCfKeyColumn.name.bytes);
                superCfKeyColumn = superCfKeyColumn.withNewName(to);
                columnMetadata.put(superCfKeyColumn.name.bytes, SuperColumnCompatibility.getSuperCfSschemaRepresentation(superCfKeyColumn));
            }
            else if (isSuperColumnValueColumn(def))
            {
                columnMetadata.remove(superCfValueColumn.name.bytes);
                superCfValueColumn = superCfValueColumn.withNewName(to);
                columnMetadata.put(superCfValueColumn.name.bytes, superCfValueColumn);
            }
            else
                addOrReplaceColumnDefinition(def.withNewName(to));
        }
        else
        {
            addOrReplaceColumnDefinition(def.withNewName(to));
        }

        // removeColumnDefinition doesn't work for partition key (expectedly) but renaming one is fine so we still
        // want to update columnMetadata.
        if (def.isPartitionKey())
            columnMetadata.remove(def.name.bytes);
        else
            removeColumnDefinition(def);
    }

    public boolean isCQLTable()
    {
        return !isSuper() && !isDense() && isCompound();
    }

    public boolean isCompactTable()
    {
        return !isCQLTable();
    }

    public boolean isStaticCompactTable()
    {
        return !isSuper() && !isDense() && !isCompound();
    }

    /**
     * Returns whether this CFMetaData can be returned to thrift.
     */
    public boolean isThriftCompatible()
    {
        return isCompactTable();
    }

    public boolean hasStaticColumns()
    {
        return !partitionColumns.statics.isEmpty();
    }

    public boolean hasCollectionColumns()
    {
        for (ColumnDefinition def : partitionColumns())
            if (def.type instanceof CollectionType && def.type.isMultiCell())
                return true;
        return false;
    }

    public boolean hasComplexColumns()
    {
        for (ColumnDefinition def : partitionColumns())
            if (def.isComplex())
                return true;
        return false;
    }

    public boolean hasDroppedCollectionColumns()
    {
        for (DroppedColumn def : getDroppedColumns().values())
            if (def.type instanceof CollectionType && def.type.isMultiCell())
                return true;
        return false;
    }

    public boolean isSuper()
    {
        return isSuper;
    }

    public boolean isCounter()
    {
        return isCounter;
    }

    // We call dense a CF for which each component of the comparator is a clustering column, i.e. no
    // component is used to store a regular column names. In other words, non-composite static "thrift"
    // and CQL3 CF are *not* dense.
    public boolean isDense()
    {
        return isDense;
    }

    public boolean isCompound()
    {
        return isCompound;
    }

    public boolean isView()
    {
        return isView;
    }

    /**
     * A table with strict liveness filters/ignores rows without PK liveness info,
     * effectively tying the row liveness to its primary key liveness.
     *
     * Currently this is only used by views with normal base column as PK column
     * so updates to other columns do not make the row live when the base column
     * is not live. See CASSANDRA-11500.
     */
    public boolean enforceStrictLiveness()
    {
        return isView && Keyspace.open(ksName).viewManager.getByName(cfName).enforceStrictLiveness();
    }

    public Serializers serializers()
    {
        return serializers;
    }

    public AbstractType<?> makeLegacyDefaultValidator()
    {
        if (isCounter())
            return CounterColumnType.instance;
        else if (isCompactTable())
            return isSuper() ? ((MapType)compactValueColumn().type).valueComparator() : compactValueColumn().type;
        else
            return BytesType.instance;
    }

    public static Set<Flag> flagsFromStrings(Set<String> strings)
    {
        return strings.stream()
                      .map(String::toUpperCase)
                      .map(Flag::valueOf)
                      .collect(Collectors.toSet());
    }

    public static Set<String> flagsToStrings(Set<Flag> flags)
    {
        return flags.stream()
                    .map(Flag::toString)
                    .map(String::toLowerCase)
                    .collect(Collectors.toSet());
    }

    @Override
    public String toString()
    {
        return new ToStringBuilder(this)
            .append("cfId", cfId)
            .append("ksName", ksName)
            .append("cfName", cfName)
            .append("flags", flags)
            .append("params", params)
            .append("comparator", comparator)
            .append("partitionColumns", partitionColumns)
            .append("partitionKeyColumns", partitionKeyColumns)
            .append("clusteringColumns", clusteringColumns)
            .append("keyValidator", keyValidator)
            .append("columnMetadata", columnMetadata.values())
            .append("droppedColumns", droppedColumns)
            .append("triggers", triggers)
            .append("indexes", indexes)
            .toString();
    }

    public static class Builder
    {
        private final String keyspace;
        private final String table;
        private final boolean isDense;
        private final boolean isCompound;
        private final boolean isSuper;
        private final boolean isCounter;
        private final boolean isView;
        private Optional<IPartitioner> partitioner;

        private UUID tableId;

        private final List<Pair<ColumnIdentifier, AbstractType>> partitionKeys = new ArrayList<>();
        private final List<Pair<ColumnIdentifier, AbstractType>> clusteringColumns = new ArrayList<>();
        private final List<Pair<ColumnIdentifier, AbstractType>> staticColumns = new ArrayList<>();
        private final List<Pair<ColumnIdentifier, AbstractType>> regularColumns = new ArrayList<>();

        private Builder(String keyspace, String table, boolean isDense, boolean isCompound, boolean isSuper, boolean isCounter, boolean isView)
        {
            this.keyspace = keyspace;
            this.table = table;
            this.isDense = isDense;
            this.isCompound = isCompound;
            this.isSuper = isSuper;
            this.isCounter = isCounter;
            this.isView = isView;
            this.partitioner = Optional.empty();
        }

        public static Builder create(String keyspace, String table)
        {
            return create(keyspace, table, false, true, false);
        }

        public static Builder create(String keyspace, String table, boolean isDense, boolean isCompound, boolean isCounter)
        {
            return create(keyspace, table, isDense, isCompound, false, isCounter);
        }

        public static Builder create(String keyspace, String table, boolean isDense, boolean isCompound, boolean isSuper, boolean isCounter)
        {
            return new Builder(keyspace, table, isDense, isCompound, isSuper, isCounter, false);
        }

        public static Builder createView(String keyspace, String table)
        {
            return new Builder(keyspace, table, false, true, false, false, true);
        }

        public static Builder createDense(String keyspace, String table, boolean isCompound, boolean isCounter)
        {
            return create(keyspace, table, true, isCompound, isCounter);
        }

        public static Builder createSuper(String keyspace, String table, boolean isCounter)
        {
            return create(keyspace, table, true, true, true, isCounter);
        }

        public Builder withPartitioner(IPartitioner partitioner)
        {
            this.partitioner = Optional.ofNullable(partitioner);
            return this;
        }

        public Builder withId(UUID tableId)
        {
            this.tableId = tableId;
            return this;
        }

        public Builder addPartitionKey(String name, AbstractType type)
        {
            return addPartitionKey(ColumnIdentifier.getInterned(name, false), type);
        }

        public Builder addPartitionKey(ColumnIdentifier name, AbstractType type)
        {
            this.partitionKeys.add(Pair.create(name, type));
            return this;
        }

        public Builder addClusteringColumn(String name, AbstractType type)
        {
            return addClusteringColumn(ColumnIdentifier.getInterned(name, false), type);
        }

        public Builder addClusteringColumn(ColumnIdentifier name, AbstractType type)
        {
            this.clusteringColumns.add(Pair.create(name, type));
            return this;
        }

        public Builder addRegularColumn(String name, AbstractType type)
        {
            return addRegularColumn(ColumnIdentifier.getInterned(name, false), type);
        }

        public Builder addRegularColumn(ColumnIdentifier name, AbstractType type)
        {
            this.regularColumns.add(Pair.create(name, type));
            return this;
        }

        public boolean hasRegulars()
        {
            return !this.regularColumns.isEmpty();
        }

        public Builder addStaticColumn(String name, AbstractType type)
        {
            return addStaticColumn(ColumnIdentifier.getInterned(name, false), type);
        }

        public Builder addStaticColumn(ColumnIdentifier name, AbstractType type)
        {
            this.staticColumns.add(Pair.create(name, type));
            return this;
        }

        public Set<String> usedColumnNames()
        {
            Set<String> usedNames = Sets.newHashSetWithExpectedSize(partitionKeys.size() + clusteringColumns.size() + staticColumns.size() + regularColumns.size());
            for (Pair<ColumnIdentifier, AbstractType> p : partitionKeys)
                usedNames.add(p.left.toString());
            for (Pair<ColumnIdentifier, AbstractType> p : clusteringColumns)
                usedNames.add(p.left.toString());
            for (Pair<ColumnIdentifier, AbstractType> p : staticColumns)
                usedNames.add(p.left.toString());
            for (Pair<ColumnIdentifier, AbstractType> p : regularColumns)
                usedNames.add(p.left.toString());
            return usedNames;
        }

        public CFMetaData build()
        {
            if (tableId == null)
                tableId = UUIDGen.getTimeUUID();

            List<ColumnDefinition> partitions = new ArrayList<>(partitionKeys.size());
            List<ColumnDefinition> clusterings = new ArrayList<>(clusteringColumns.size());
            PartitionColumns.Builder builder = PartitionColumns.builder();

            for (int i = 0; i < partitionKeys.size(); i++)
            {
                Pair<ColumnIdentifier, AbstractType> p = partitionKeys.get(i);
                partitions.add(new ColumnDefinition(keyspace, table, p.left, p.right, i, ColumnDefinition.Kind.PARTITION_KEY));
            }

            for (int i = 0; i < clusteringColumns.size(); i++)
            {
                Pair<ColumnIdentifier, AbstractType> p = clusteringColumns.get(i);
                clusterings.add(new ColumnDefinition(keyspace, table, p.left, p.right, i, ColumnDefinition.Kind.CLUSTERING));
            }

            for (Pair<ColumnIdentifier, AbstractType> p : regularColumns)
                builder.add(new ColumnDefinition(keyspace, table, p.left, p.right, ColumnDefinition.NO_POSITION, ColumnDefinition.Kind.REGULAR));

            for (Pair<ColumnIdentifier, AbstractType> p : staticColumns)
                builder.add(new ColumnDefinition(keyspace, table, p.left, p.right, ColumnDefinition.NO_POSITION, ColumnDefinition.Kind.STATIC));

            return new CFMetaData(keyspace,
                                  table,
                                  tableId,
                                  isSuper,
                                  isCounter,
                                  isDense,
                                  isCompound,
                                  isView,
                                  partitions,
                                  clusterings,
                                  builder.build(),
                                  partitioner.orElseGet(DatabaseDescriptor::getPartitioner),
                                  null,
                                  null);
        }
    }

    public static class Serializer
    {
        public void serialize(CFMetaData metadata, DataOutputPlus out, int version) throws IOException
        {
            UUIDSerializer.serializer.serialize(metadata.cfId, out, version);
        }

        public CFMetaData deserialize(DataInputPlus in, int version) throws IOException
        {
            UUID cfId = UUIDSerializer.serializer.deserialize(in, version);
            CFMetaData metadata = Schema.instance.getCFMetaData(cfId);
            if (metadata == null)
            {
                String message = String.format("Couldn't find table for cfId %s. If a table was just " +
                        "created, this is likely due to the schema not being fully propagated.  Please wait for schema " +
                        "agreement on table creation.", cfId);
                throw new UnknownColumnFamilyException(message, cfId);
            }

            return metadata;
        }

        public long serializedSize(CFMetaData metadata, int version)
        {
            return UUIDSerializer.serializer.serializedSize(metadata.cfId, version);
        }
    }

    public static class DroppedColumn
    {
        // we only allow dropping REGULAR columns, from CQL-native tables, so the names are always of UTF8Type
        public final String name;
        public final AbstractType<?> type;

        // drop timestamp, in microseconds, yet with millisecond granularity
        public final long droppedTime;

        @Nullable
        public final ColumnDefinition.Kind kind;

        public DroppedColumn(String name, ColumnDefinition.Kind kind, AbstractType<?> type, long droppedTime)
        {
            this.name = name;
            this.kind = kind;
            this.type = type;
            this.droppedTime = droppedTime;
        }

        @Override
        public boolean equals(Object o)
        {
            if (this == o)
                return true;

            if (!(o instanceof DroppedColumn))
                return false;

            DroppedColumn dc = (DroppedColumn) o;

            return name.equals(dc.name)
                && kind == dc.kind
                && type.equals(dc.type)
                && droppedTime == dc.droppedTime;
        }

        @Override
        public int hashCode()
        {
            return Objects.hashCode(name, kind, type, droppedTime);
        }

        @Override
        public String toString()
        {
            return MoreObjects.toStringHelper(this)
                              .add("name", name)
                              .add("kind", kind)
                              .add("type", type)
                              .add("droppedTime", droppedTime)
                              .toString();
        }
    }
}


text:
'use strict';

var _ = require('lodash');
var assert = require('assert');
var Inherits = require('util').inherits;
var Path = require('path');
var URI = require('urijs');
var Promise = require('bluebird');
var Xml2Js = require('xml2js');

var BaseFormat = require('../base_format.js');
var Util = require('../util.js');

var WADL = module.exports = function() {
  WADL.super_.apply(this, arguments);
  this.format = 'wadl';

  this.converters.swagger_2 =
    Promise.method(wadl => convertToSwagger(wadl.spec));

  this.converters.openapi_3 =
    Promise.method(swagger1 => this.convertTransitive(['swagger_2', 'openapi_3']));
}

Inherits(WADL, BaseFormat);

WADL.prototype.formatName = 'wadl';
WADL.prototype.supportedVersions = ['1.0'];
WADL.prototype.getFormatVersion = function () {
  return '1.0';
}

WADL.prototype.parsers = {
  'XML': data => Promise.promisify(Xml2Js.parseString)(data, {
    //HACK: we just strip namespace. Yes I know, it's ugly.
    //But handling XML namespaces is even uglier.
    tagNameProcessors: [Xml2Js.processors.stripPrefix],
    attrNameProcessors: [Xml2Js.processors.stripPrefix]
  })
};

WADL.prototype.checkFormat = function (spec) {
  return true;
}

function convertToSwagger(wadl) {
  var convertStyle = function(style) {
    switch (style) {
      case 'query':
      case 'header':
        return style;
      case 'template':
        return 'path';
      default:
        assert(false);
    }
  }
  var convertType = function(wadlType) {
    if (_.isUndefined(wadlType))
      return {};

    //HACK: we just strip namespace. Yes I know, it's ugly.
    //But handling XML namespaces is even uglier.
    var match = wadlType.match(/^(?:[^:]+:)?(.+)$/);
    assert(match, wadlType);
    var type = match[1];
    switch (type.toLowerCase()) {
      case 'boolean':
      case 'string':
      case 'integer':
        return {type: type};
      case 'double':
      case 'decimal':
        return {type: 'number'};
      case 'int':
        return {type: 'integer', format: 'int32'};
      case 'long':
        return {type: 'integer', format: 'int64'};
      case 'positiveInteger':
        return {type: 'integer', minimum: 1};
      case 'anyURI':
      case 'date':
      case 'time':
      case 'date-time':
        //TODO: add 'format' where possible
        return {type: 'string'};
      default:
        //HACK: convert unknown types into 'string' these works for everything,
        //except body and responces but we don't support them yet.
        return {type: 'string'};
        //TODO: add warning
        //assert(false, 'Unsupported type: ' + wadlType);
    }
  }

  var convertDoc = function (doc) {
    if (_.isUndefined(doc))
      return {};

    assert(_.isArray(doc));
    var result = {};
    _.each(doc, function (docElement) {
      if (_.isPlainObject(docElement)) {
        //Handle Apigee extension
        var externalUrl = docElement.$['url'];
        if (externalUrl)
          result.externalDocs = {url: externalUrl};
        docElement = docElement._;
        if (!_.isString(docElement))
          return;
      }

      assert(_.isString(docElement));
      docElement = docElement.trim();
      if (result.description)
        result.description += '\n' + docElement;
      else
        result.description = docElement;
    });
    return result;
  }

  var convertDefault = function (wadlDefault, type) {
    if (type === 'string')
      return wadlDefault;
    return JSON.parse(wadlDefault);
  }

  var convertParameter = function(wadlParam) {
    var loc = convertStyle(wadlParam.$.style);
    var ret = {
      name: wadlParam.$.name,
      required: loc === 'path' ? true : JSON.parse(wadlParam.$.required || 'false'),
      in: loc,
      type: 'string', //default type
    };
    _.assign(ret, convertType(wadlParam.$.type));

    var wadlDefault = wadlParam.$.default;
    if (!_.isUndefined(wadlDefault))
      ret.default = convertDefault(wadlDefault, ret.type);

    var doc = convertDoc(wadlParam.doc);
    //FIXME:
    delete doc.externalDocs;
    _.extend(ret,doc);

    if (wadlParam.option) {
      ret.enum = wadlParam.option.map(function(opt) {
        return opt.$.value;
      })
    }
    return ret;
  }

  function unwrapArray(array) {
    if (_.isUndefined(array))
      return;

    assert(_.isArray(array));
    assert(_.size(array) === 1);
    return array[0];
  }

  function convertMethod(wadlMethod) {
    var method = {
      operationId: wadlMethod.$.id,
      responses: {
        //FIXME: take responces from WADL file
        200: {
          description: 'Successful Response'
        }
      }
    };

    var wadlRequest = unwrapArray(wadlMethod.request);
    if (wadlRequest)
      method.parameters = _.uniqBy(_.map(wadlRequest.param, convertParameter),function(e){
      return e.name + e.in });

    _.extend(method, convertDoc(wadlMethod.doc));

    return method;
  }

  // Jersey use very strange extension to WADL. See:
  // https://docs.oracle.com/cd/E19776-01/820-4867/6nga7f5nc/index.html
  // They add {<name>: <regex>} template parameters which should be converted
  // to {<name>}. Tricky part is find end of regexp.
  function convertPath(path) {
    function indexOf(ch, startPosition) {
      var pos = path.indexOf(ch, startPosition);
      if (pos === -1)
        return pos;

      var slashNumber = 0;
      while (path.charAt(pos - 1 - slashNumber) === '\\')
        ++slashNumber;

      if (slashNumber % 2 === 0)
        return pos;

      //Skip escaped symbols
      return indexOf(ch, pos + 1);
    }

    var match;

    //RegEx should be inside loop to reset iteration
    while (match = /{([^}:]+):/g.exec(path)) {
      var deleteBegin = match.index + match[0].length - 1;
      var deleteEnd = deleteBegin;

      var unmatched = 1;
      while (unmatched !== 0) {

        var open = indexOf('{', deleteEnd + 1);
        var close = indexOf('}', deleteEnd + 1);

        if (close === -1)
          throw Error('Unmatched curly brackets in path: ' + path);

        if (open !==  -1 && open < close) {
          ++unmatched;
          deleteEnd = open;
        }
        else {
          --unmatched;
          deleteEnd = close;
        }
      }

      //For future use: regex itself is
      //path.substring(deleteBegin + 1, deleteEnd)

      path = path.slice(0, deleteBegin) + path.slice(deleteEnd);
    }

    return path;
  }

  function convertResource(wadlResource) {
    var resourcePath = Util.joinPath('/', convertPath(wadlResource.$.path));
    var paths = {};

    //Not supported
    assert(!_.has(wadlResource, 'resource_type'));
    assert(!_.has(wadlResource, 'resource_type'));

    var resource = {};
    var commonParameters = _.uniqBy(_.map(wadlResource.param, convertParameter),function(e){
    return e.name + e.in });

    _.each(wadlResource.method, function(wadlMethod) {
      var httpMethod = wadlMethod.$.name.toLowerCase();
      resource[httpMethod] = convertMethod(wadlMethod);
    });

    if (!_.isEmpty(resource)) {
      resource.parameters = commonParameters;
      paths[resourcePath] = resource;
    }

    _.each(wadlResource.resource, function (wadlSubResource) {
      var subPaths = convertResource(wadlSubResource);
      subPaths = _.mapKeys(subPaths, function (subPath, path) {
        subPath.parameters = _.uniqBy(commonParameters.concat(subPath.parameters),function(e){
        return e.name + e.id });
        return Util.joinPath(resourcePath, convertPath(path));
      });
      mergePaths(paths, subPaths);
    });

    return paths;
  }

  function mergePaths(paths, pathsToAdd) {
    _.each(pathsToAdd, function (resource, path) {
      var existingResource = paths[path];
      if (!_.isUndefined(existingResource)) {
        assert(_.isEqual(existingResource.parameters, resource.parameters));
        _.extend(existingResource, resource);
      }
      else
        paths[path] = resource;
    });
  }

  var root = unwrapArray(wadl.application.resources);
  var title = wadl.application.doc && wadl.application.doc[1] && wadl.application.doc[1].$ ?
    wadl.application.doc[1].$.title : "";

  var baseUrl = URI(root.$.base);
  var swagger = {
    swagger: '2.0',
    info: {
      title: title,
      version: ""
    },
    host:  baseUrl.host() || undefined,
    basePath: baseUrl.pathname() || undefined,
    schemes: baseUrl.protocol() ? [baseUrl.protocol()] : undefined,
    paths: {}
  };

  _.each(root.resource, function(wadlResource) {
    mergePaths(swagger.paths, convertResource(wadlResource));
  });

  return swagger;
}

redpajama_set_name: RedPajamaGithub


text:
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayKlass.inline.hpp"
#include "oops/objArrayKlassKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/copy.hpp"
#ifndef SERIALGC
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif

int objArrayKlass::oop_size(oop obj) const {
  assert(obj->is_objArray(), "must be object array");
  return objArrayOop(obj)->object_size();
}

objArrayOop objArrayKlass::allocate(int length, TRAPS) {
  if (length >= 0) {
    if (length <= arrayOopDesc::max_array_length(T_OBJECT)) {
      int size = objArrayOopDesc::object_size(length);
      KlassHandle h_k(THREAD, as_klassOop());
      objArrayOop a = (objArrayOop)CollectedHeap::array_allocate(h_k, size, length, CHECK_NULL);
      assert(a->is_parsable(), "Can't publish unless parsable");
      return a;
    } else {
      report_java_out_of_memory("Requested array size exceeds VM limit");
      JvmtiExport::post_array_size_exhausted();
      THROW_OOP_0(Universe::out_of_memory_error_array_size());
    }
  } else {
    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
  }
}

static int multi_alloc_counter = 0;

oop objArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
  int length = *sizes;
  // Call to lower_dimension uses this pointer, so most be called before a
  // possible GC
  KlassHandle h_lower_dimension(THREAD, lower_dimension());
  // If length < 0 allocate will throw an exception.
  objArrayOop array = allocate(length, CHECK_NULL);
  assert(array->is_parsable(), "Don't handlize unless parsable");
  objArrayHandle h_array (THREAD, array);
  if (rank > 1) {
    if (length != 0) {
      for (int index = 0; index < length; index++) {
        arrayKlass* ak = arrayKlass::cast(h_lower_dimension());
        oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
        assert(sub_array->is_parsable(), "Don't publish until parsable");
        h_array->obj_at_put(index, sub_array);
      }
    } else {
      // Since this array dimension has zero length, nothing will be
      // allocated, however the lower dimension values must be checked
      // for illegal values.
      for (int i = 0; i < rank - 1; ++i) {
        sizes += 1;
        if (*sizes < 0) {
          THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
        }
      }
    }
  }
  return h_array();
}

// Either oop or narrowOop depending on UseCompressedOops.
template <class T> void objArrayKlass::do_copy(arrayOop s, T* src,
                               arrayOop d, T* dst, int length, TRAPS) {

  BarrierSet* bs = Universe::heap()->barrier_set();
  // For performance reasons, we assume we are that the write barrier we
  // are using has optimized modes for arrays of references.  At least one
  // of the asserts below will fail if this is not the case.
  assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
  assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");

  if (s == d) {
    // since source and destination are equal we do not need conversion checks.
    assert(length > 0, "sanity check");
    bs->write_ref_array_pre(dst, length);
    Copy::conjoint_oops_atomic(src, dst, length);
  } else {
    // We have to make sure all elements conform to the destination array
    klassOop bound = objArrayKlass::cast(d->klass())->element_klass();
    klassOop stype = objArrayKlass::cast(s->klass())->element_klass();
    if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
      // elements are guaranteed to be subtypes, so no check necessary
      bs->write_ref_array_pre(dst, length);
      Copy::conjoint_oops_atomic(src, dst, length);
    } else {
      // slow case: need individual subtype checks
      // note: don't use obj_at_put below because it includes a redundant store check
      T* from = src;
      T* end = from + length;
      for (T* p = dst; from < end; from++, p++) {
        // XXX this is going to be slow.
        T element = *from;
        // even slower now
        bool element_is_null = oopDesc::is_null(element);
        oop new_val = element_is_null ? oop(NULL)
                                      : oopDesc::decode_heap_oop_not_null(element);
        if (element_is_null ||
            Klass::cast((new_val->klass()))->is_subtype_of(bound)) {
          bs->write_ref_field_pre(p, new_val);
          *p = *from;
        } else {
          // We must do a barrier to cover the partial copy.
          const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);
          // pointer delta is scaled to number of elements (length field in
          // objArrayOop) which we assume is 32 bit.
          assert(pd == (size_t)(int)pd, "length field overflow");
          bs->write_ref_array((HeapWord*)dst, pd);
          THROW(vmSymbols::java_lang_ArrayStoreException());
          return;
        }
      }
    }
  }
  bs->write_ref_array((HeapWord*)dst, length);
}

void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
                               int dst_pos, int length, TRAPS) {
  assert(s->is_objArray(), "must be obj array");

  if (!d->is_objArray()) {
    THROW(vmSymbols::java_lang_ArrayStoreException());
  }

  // Check is all offsets and lengths are non negative
  if (src_pos < 0 || dst_pos < 0 || length < 0) {
    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
  }
  // Check if the ranges are valid
  if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
     || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
  }

  // Special case. Boundary cases must be checked first
  // This allows the following call: copy_array(s, s.length(), d.length(), 0).
  // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
  // points to the right of the last element.
  if (length==0) {
    return;
  }
  if (UseCompressedOops) {
    narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);
    narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);
    do_copy<narrowOop>(s, src, d, dst, length, CHECK);
  } else {
    oop* const src = objArrayOop(s)->obj_at_addr<oop>(src_pos);
    oop* const dst = objArrayOop(d)->obj_at_addr<oop>(dst_pos);
    do_copy<oop> (s, src, d, dst, length, CHECK);
  }
}

klassOop objArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
  objArrayKlassHandle h_this(THREAD, as_klassOop());
  return array_klass_impl(h_this, or_null, n, CHECK_NULL);
}

klassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_null, int n, TRAPS) {

  assert(this_oop->dimension() <= n, "check order of chain");
  int dimension = this_oop->dimension();
  if (dimension == n)
    return this_oop();

  objArrayKlassHandle ak (THREAD, this_oop->higher_dimension());
  if (ak.is_null()) {
    if (or_null)  return NULL;

    ResourceMark rm;
    JavaThread *jt = (JavaThread *)THREAD;
    {
      MutexLocker mc(Compile_lock, THREAD);   // for vtables
      // Ensure atomic creation of higher dimensions
      MutexLocker mu(MultiArray_lock, THREAD);

      // Check if another thread beat us
      ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
      if( ak.is_null() ) {

        // Create multi-dim klass object and link them together
        klassOop new_klass =
          objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
          allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
        ak = objArrayKlassHandle(THREAD, new_klass);
        ak->set_lower_dimension(this_oop());
        OrderAccess::storestore();
        this_oop->set_higher_dimension(ak());
        assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
      }
    }
  } else {
    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
  }

  if (or_null) {
    return ak->array_klass_or_null(n);
  }
  return ak->array_klass(n, CHECK_NULL);
}

klassOop objArrayKlass::array_klass_impl(bool or_null, TRAPS) {
  return array_klass_impl(or_null, dimension() +  1, CHECK_NULL);
}

bool objArrayKlass::can_be_primary_super_slow() const {
  if (!bottom_klass()->klass_part()->can_be_primary_super())
    // array of interfaces
    return false;
  else
    return Klass::can_be_primary_super_slow();
}

objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
  // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... };
  objArrayOop es = Klass::cast(element_klass())->secondary_supers();
  objArrayHandle elem_supers (THREAD, es);
  int num_elem_supers = elem_supers.is_null() ? 0 : elem_supers->length();
  int num_secondaries = num_extra_slots + 2 + num_elem_supers;
  if (num_secondaries == 2) {
    // Must share this for correct bootstrapping!
    return Universe::the_array_interfaces_array();
  } else {
    objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
    objArrayHandle secondaries(THREAD, sec_oop);
    secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::Cloneable_klass());
    secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::Serializable_klass());
    for (int i = 0; i < num_elem_supers; i++) {
      klassOop elem_super = (klassOop) elem_supers->obj_at(i);
      klassOop array_super = elem_super->klass_part()->array_klass_or_null();
      assert(array_super != NULL, "must already have been created");
      secondaries->obj_at_put(num_extra_slots+2+i, array_super);
    }
    return secondaries();
  }
}

bool objArrayKlass::compute_is_subtype_of(klassOop k) {
  if (!k->klass_part()->oop_is_objArray())
    return arrayKlass::compute_is_subtype_of(k);

  objArrayKlass* oak = objArrayKlass::cast(k);
  return element_klass()->klass_part()->is_subtype_of(oak->element_klass());
}

void objArrayKlass::initialize(TRAPS) {
  Klass::cast(bottom_klass())->initialize(THREAD);  // dispatches to either instanceKlass or typeArrayKlass
}

#define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \
{                                   \
  T* p         = (T*)(a)->base();   \
  T* const end = p + (a)->length(); \
  while (p < end) {                 \
    do_oop;                         \
    p++;                            \
  }                                 \
}

#define ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(T, a, p, low, high, do_oop) \
{                                   \
  T* const l = (T*)(low);           \
  T* const h = (T*)(high);          \
  T* p       = (T*)(a)->base();     \
  T* end     = p + (a)->length();   \
  if (p < l) p = l;                 \
  if (end > h) end = h;             \
  while (p < end) {                 \
    do_oop;                         \
    ++p;                            \
  }                                 \
}

#define ObjArrayKlass_OOP_ITERATE(a, p, do_oop)      \
  if (UseCompressedOops) {                           \
    ObjArrayKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
      a, p, do_oop)                                  \
  } else {                                           \
    ObjArrayKlass_SPECIALIZED_OOP_ITERATE(oop,       \
      a, p, do_oop)                                  \
  }

#define ObjArrayKlass_BOUNDED_OOP_ITERATE(a, p, low, high, do_oop) \
  if (UseCompressedOops) {                                   \
    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
      a, p, low, high, do_oop)                               \
  } else {                                                   \
    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,       \
      a, p, low, high, do_oop)                               \
  }

void objArrayKlass::oop_follow_contents(oop obj) {
  assert (obj->is_array(), "obj must be array");
  objArrayOop(obj)->follow_header();
  if (UseCompressedOops) {
    objarray_follow_contents<narrowOop>(obj, 0);
  } else {
    objarray_follow_contents<oop>(obj, 0);
  }
}

#ifndef SERIALGC
void objArrayKlass::oop_follow_contents(ParCompactionManager* cm,
                                        oop obj) {
  assert(obj->is_array(), "obj must be array");
  objArrayOop(obj)->follow_header(cm);
  if (UseCompressedOops) {
    objarray_follow_contents<narrowOop>(cm, obj, 0);
  } else {
    objarray_follow_contents<oop>(cm, obj, 0);
  }
}
#endif // SERIALGC

#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)           \
                                                                                \
int objArrayKlass::oop_oop_iterate##nv_suffix(oop obj,                          \
                                              OopClosureType* closure) {        \
  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
  assert (obj->is_array(), "obj must be array");                                \
  objArrayOop a = objArrayOop(obj);                                             \
  /* Get size before changing pointers. */                                      \
  /* Don't call size() or oop_size() since that is a virtual call. */           \
  int size = a->object_size();                                                  \
  if (closure->do_header()) {                                                   \
    a->oop_iterate_header(closure);                                             \
  }                                                                             \
  ObjArrayKlass_OOP_ITERATE(a, p, (closure)->do_oop##nv_suffix(p))              \
  return size;                                                                  \
}

#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)         \
                                                                                \
int objArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj,                      \
                                                  OopClosureType* closure,      \
                                                  MemRegion mr) {               \
  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
  assert(obj->is_array(), "obj must be array");                                 \
  objArrayOop a  = objArrayOop(obj);                                            \
  /* Get size before changing pointers. */                                      \
  /* Don't call size() or oop_size() since that is a virtual call */            \
  int size = a->object_size();                                                  \
  if (closure->do_header()) {                                                   \
    a->oop_iterate_header(closure, mr);                                         \
  }                                                                             \
  ObjArrayKlass_BOUNDED_OOP_ITERATE(                                            \
    a, p, mr.start(), mr.end(), (closure)->do_oop##nv_suffix(p))                \
  return size;                                                                  \
}

// Like oop_oop_iterate but only iterates over a specified range and only used
// for objArrayOops.
#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r(OopClosureType, nv_suffix)         \
                                                                                \
int objArrayKlass::oop_oop_iterate_range##nv_suffix(oop obj,                    \
                                                  OopClosureType* closure,      \
                                                  int start, int end) {         \
  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
  assert(obj->is_array(), "obj must be array");                                 \
  objArrayOop a  = objArrayOop(obj);                                            \
  /* Get size before changing pointers. */                                      \
  /* Don't call size() or oop_size() since that is a virtual call */            \
  int size = a->object_size();                                                  \
  if (UseCompressedOops) {                                                      \
    HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<narrowOop>(start);\
    /* this might be wierd if end needs to be aligned on HeapWord boundary */   \
    HeapWord* high = (HeapWord*)((narrowOop*)a->base() + end);                  \
    MemRegion mr(low, high);                                                    \
    if (closure->do_header()) {                                                 \
      a->oop_iterate_header(closure, mr);                                       \
    }                                                                           \
    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop,                    \
      a, p, low, high, (closure)->do_oop##nv_suffix(p))                         \
  } else {                                                                      \
    HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<oop>(start);  \
    HeapWord* high = (HeapWord*)((oop*)a->base() + end);                        \
    MemRegion mr(low, high);                                                    \
    if (closure->do_header()) {                                                 \
      a->oop_iterate_header(closure, mr);                                       \
    }                                                                           \
    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,                          \
      a, p, low, high, (closure)->do_oop##nv_suffix(p))                         \
  }                                                                             \
  return size;                                                                  \
}

ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)

int objArrayKlass::oop_adjust_pointers(oop obj) {
  assert(obj->is_objArray(), "obj must be obj array");
  objArrayOop a = objArrayOop(obj);
  // Get size before changing pointers.
  // Don't call size() or oop_size() since that is a virtual call.
  int size = a->object_size();
  a->adjust_header();
  ObjArrayKlass_OOP_ITERATE(a, p, MarkSweep::adjust_pointer(p))
  return size;
}

#ifndef SERIALGC
void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
  assert(obj->is_objArray(), "obj must be obj array");
  ObjArrayKlass_OOP_ITERATE( \
    objArrayOop(obj), p, \
    if (PSScavenge::should_scavenge(p)) { \
      pm->claim_or_forward_depth(p); \
    })
}

int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
  assert (obj->is_objArray(), "obj must be obj array");
  objArrayOop a = objArrayOop(obj);
  ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p))
  return a->object_size();
}
#endif // SERIALGC

// JVM support

jint objArrayKlass::compute_modifier_flags(TRAPS) const {
  // The modifier for an objectArray is the same as its element
  if (element_klass() == NULL) {
    assert(Universe::is_bootstrapping(), "partial objArray only at startup");
    return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
  }
  // Return the flags of the bottom element type.
  jint element_flags = Klass::cast(bottom_klass())->compute_modifier_flags(CHECK_0);

  return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
                        | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
}

#ifndef PRODUCT
// Printing

void objArrayKlass::oop_print_on(oop obj, outputStream* st) {
  arrayKlass::oop_print_on(obj, st);
  assert(obj->is_objArray(), "must be objArray");
  objArrayOop oa = objArrayOop(obj);
  int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
  for(int index = 0; index < print_len; index++) {
    st->print(" - %3d : ", index);
    oa->obj_at(index)->print_value_on(st);
    st->cr();
  }
  int remaining = oa->length() - print_len;
  if (remaining > 0) {
    st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
  }
}

#endif //PRODUCT

static int max_objArray_print_length = 4;

void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
  assert(obj->is_objArray(), "must be objArray");
  st->print("a ");
  element_klass()->print_value_on(st);
  int len = objArrayOop(obj)->length();
  st->print("[%d] ", len);
  obj->print_address_on(st);
  if (NOT_PRODUCT(PrintOopAddress ||) PrintMiscellaneous && (WizardMode || Verbose)) {
    st->print("{");
    for (int i = 0; i < len; i++) {
      if (i > max_objArray_print_length) {
        st->print("..."); break;
      }
      st->print(" "INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i));
    }
    st->print(" }");
  }
}

const char* objArrayKlass::internal_name() const {
  return external_name();
}

// Verification

void objArrayKlass::oop_verify_on(oop obj, outputStream* st) {
  arrayKlass::oop_verify_on(obj, st);
  guarantee(obj->is_objArray(), "must be objArray");
  objArrayOop oa = objArrayOop(obj);
  for(int index = 0; index < oa->length(); index++) {
    guarantee(oa->obj_at(index)->is_oop_or_null(), "should be oop");
  }
}


text:
package ar.com.javacuriosities.nio;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;

/*
 * Una falencia del API del paquete java.io, era que no había forma de manejar metadata de directorios y archivos
 *
 * 	- File Owners
 * 	- Permissions
 * 	- Time stamps
 * 	- DOS attributes
 * 	- Extended attributes
 *
 * La forma de manejarlos es por medio de vistas donde engloban estos atributos
 */
public class Lesson06FileAttributes {
	public static void main(String[] args) {
		try {
			Path path = Paths.get("metadata.txt");

			Files.deleteIfExists(path);

			Files.createFile(path);

			BasicFileAttributeView basicView = Files.getFileAttributeView(path, BasicFileAttributeView.class);

			BasicFileAttributes basicAttributes = basicView.readAttributes();
			boolean isDirectory = basicAttributes.isDirectory();
			FileTime lastModifiedTime = basicAttributes.lastModifiedTime();

			System.out.println(isDirectory);
			System.out.println(lastModifiedTime);

			PosixFileAttributeView posixView = Files.getFileAttributeView(path, PosixFileAttributeView.class);
			PosixFileAttributes posixAttributes = posixView.readAttributes();

			GroupPrincipal group = posixAttributes.group();

			Set<PosixFilePermission> permissions = posixAttributes.permissions();
			permissions.add(PosixFilePermission.OWNER_EXECUTE);
			posixView.setPermissions(permissions);

			System.out.println(group);

		} catch (IOException e) {
			// Log and Handle exception
			e.printStackTrace();
		}
	}
}


text:
package it.revevol.simulation.domain;

import java.util.Map;

/**
 * Represents the result of the simulation
 * @author Angelo
 *
 */
public class SimulationResult {

	//How many different numbers have been generated
	private int differentNums;

	//A number and its occurrence in the simulation (expressed in %)
	private Map<Integer,Double> occurrencePercent;

	//A number and its occurrence in the simulation
	private Map<Integer,Integer> occurrence;

	//The most frequent number generated
	private int mostFrequent;

	//The simulation execution time
	private long executionTime;

	public SimulationResult(int differentNums, Map<Integer, Integer> occurrence, Map<Integer, Double> occurrencePercent,
			int mostFrequent, long executionTime) {
		this.differentNums = differentNums;
		this.occurrence = occurrence;
		this.occurrencePercent = occurrencePercent;
		this.mostFrequent = mostFrequent;
		this.executionTime = executionTime;
	}

	public SimulationResult(){

	}
	public Map<Integer, Double> getOccurencePercent() {
		return occurrencePercent;
	}
	public void setOccurencePercent(Map<Integer, Double> occurencePercent) {
		this.occurrencePercent = occurencePercent;
	}
	public Map<Integer, Integer> getOccurence() {
		return occurrence;
	}

	public void setOccurence(Map<Integer, Integer> occurence) {
		this.occurrence = occurence;
	}
	public int getDifferentNums() {
		return differentNums;
	}
	public void setDifferentNums(int differentNums) {
		this.differentNums = differentNums;
	}
	public int getMostFrequent() {
		return mostFrequent;
	}
	public void setMostFrequent(int mostFrequent) {
		this.mostFrequent = mostFrequent;
	}
	public long getExecutionTime() {
		return executionTime;
	}
	public void setExecutionTime(long executionTime) {
		this.executionTime = executionTime;
	}

}


text:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky - Edit Post{% endblock %}

{% block page_content %}

    {% if post.author == current_user %}

Edit Your Post

    {% else %}

Edit {{post.author.username}}'s Post

    {% endif %}

    {{ wtf.quick_form(form) }}

{% endblock %}


text:
import sys
import traceback

_log_level = 1

# 0 - only error messages will be reported
# 1 - only error and warning messages will be reported
# 2 - only error, warning and informational messages will be reported
# 3 - all messages will be reported

def     LogLevel( level = None ):
    global _log_level

    previous_level = _log_level

    if level is not None:
        _log_level = int(level)

    return previous_level

#//-------------------------------------------------------//

class   ErrorException( StandardError ):
    pass

def     Error( exception ):
    raise ErrorException( exception )

def     Msg( msg ):
        print 'AQL: ***', msg

def     Warning( msg ):
    if _log_level > 0:
        print 'AQL: Warning: ***', msg

def     Info( msg ):
    if _log_level > 1:
        print 'AQL: Info: ***', msg

def     DebugMsg( exception, traceback_limit = 50, backtfrom = 2 ):
    if __debug__:
        if _log_level > 2:
            try:
                raise ZeroDivisionError
            except ZeroDivisionError:
                frame = sys.exc_info()[ backtfrom ].tb_frame.f_back

            print 'AQL DBG: ***', exception
            traceback.print_stack( frame, traceback_limit )


text:
<?php

namespace Magento\Framework\DB\Ddl;

class TriggerFactory
{
    /**
     * @var \Magento\Framework\ObjectManagerInterface
     */
    protected $objectManager;

    /**
     * @var string
     */
    const INSTANCE_NAME = 'Magento\Framework\DB\Ddl\Trigger';

    /**
     * @param \Magento\Framework\ObjectManagerInterface $objectManager
     */
    public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
    {
        $this->_objectManager = $objectManager;
    }

    /**
     * Create class instance with specified parameters
     *
     * @param array $data
     * @return \Magento\Framework\DB\Ddl\Trigger
     */
    public function create(array $data = [])
    {
        return $this->_objectManager->create(self::INSTANCE_NAME, $data);
    }
}