content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.cassandra.db.filter;
  
  import java.io.IOException;
  
  import org.apache.cassandra.db.*;
  import org.apache.cassandra.db.partitions.CachedPartition;
  import org.apache.cassandra.db.partitions.Partition;
  import org.apache.cassandra.db.rows.*;
  import org.apache.cassandra.io.util.DataInputPlus;
  import org.apache.cassandra.io.util.DataOutputPlus;
  import org.apache.cassandra.schema.TableMetadata;
  
  /**
   * A filter that selects a subset of the rows of a given partition by using the "clustering index".
   * <p>
   * In CQL terms, this correspond to the clustering columns selection and correspond to what
   * the storage engine can do without filtering (and without 2ndary indexes). This does not include
   * the restrictions on non-PK columns which can be found in {@link RowFilter}.
   */
  public interface ClusteringIndexFilter
  {
      public static final Serializer serializer = AbstractClusteringIndexFilter.serializer;
  
      public enum Kind
      {
          SLICE (ClusteringIndexSliceFilter.deserializer),
          NAMES (ClusteringIndexNamesFilter.deserializer);
  
          protected final InternalDeserializer deserializer;
  
          private Kind(InternalDeserializer deserializer)
          {
              this.deserializer = deserializer;
          }
      }
  
      static interface InternalDeserializer
      {
          public ClusteringIndexFilter deserialize(DataInputPlus in, int version, TableMetadata metadata, boolean reversed) throws IOException;
      }
  
      /**
       * Whether the filter query rows in reversed clustering order or not.
       *
       * @return whether the filter query rows in reversed clustering order or not.
       */
      public boolean isReversed();
  
      public boolean isEmpty(ClusteringComparator comparator);
  
      /**
       * Returns a filter for continuing the paging of this filter given the last returned clustering prefix.
       *
       * @param comparator the comparator for the table this is a filter for.
       * @param lastReturned the last clustering that was returned for the query we are paging for. The
       * resulting filter will be such that results coming after {@code lastReturned} are returned
       * (where coming after means "greater than" if the filter is not reversed, "lesser than" otherwise;
       * futher, whether the comparison is strict or not depends on {@code inclusive}).
       * @param inclusive whether or not we want to include the {@code lastReturned} in the newly returned
       * page of results.
       *
       * @return a new filter that selects results coming after {@code lastReturned}.
       */
      public ClusteringIndexFilter forPaging(ClusteringComparator comparator, Clustering<?> lastReturned, boolean inclusive);
  
      /**
       * Returns whether we can guarantee that a given cached partition contains all the data selected by this filter.
       *
       * @param partition the cached partition. This method assumed that the rows of this partition contains all the table columns.
       *
       * @return whether we can guarantee that all data selected by this filter are in {@code partition}.
       */
      public boolean isFullyCoveredBy(CachedPartition partition);
  
      /**
       * Whether this filter selects the head of a partition (i.e. it isn't reversed and selects all rows up to a certain point).
       *
       * @return whether this filter selects the head of a partition.
       */
      public boolean isHeadFilter();
  
      /**
       * Whether this filter selects all the row of a partition (it's an "identity" filter).
       *
       * @return whether this filter selects all the row of a partition (it's an "identity" filter).
       */
      public boolean selectsAllPartition();
  
      /**
       * Whether a given row is selected by this filter.
       *
       * @param clustering the clustering of the row to test the selection of.
       *
       * @return whether the row with clustering {@code clustering} is selected by this filter.
       */
      public boolean selects(Clustering<?> clustering);
  
      /**
       * Returns an iterator that only returns the rows of the provided iterator that this filter selects.
       * <p>
       * This method is the "dumb" counterpart to {@link #getSlices(TableMetadata)} in that it has no way to quickly get
       * to what is actually selected, so it simply iterate over it all and filters out what shouldn't be returned. This should
       * be avoided in general.
       * Another difference with {@link #getSlices(TableMetadata)} is that this method also filter the queried
       * columns in the returned result, while the former assumes that the provided iterator has already done it.
       *
       * @param columnFilter the columns to include in the rows of the result iterator.
       * @param iterator the iterator for which we should filter rows.
       *
       * @return an iterator that only returns the rows (or rather Unfilted) from {@code iterator} that are selected by this filter.
       */
      public UnfilteredRowIterator filterNotIndexed(ColumnFilter columnFilter, UnfilteredRowIterator iterator);
  
      public Slices getSlices(TableMetadata metadata);
  
      /**
       * Given a partition, returns a row iterator for the rows of this partition that are selected by this filter.
       *
       * @param columnFilter the columns to include in the rows of the result iterator.
       * @param partition the partition containing the rows to filter.
       *
       * @return a unfiltered row iterator returning those rows (or rather Unfiltered) from {@code partition} that are selected by this filter.
       */
      public UnfilteredRowIterator getUnfilteredRowIterator(ColumnFilter columnFilter, Partition partition);
  
      /**
       * Whether the data selected by this filter intersects with the provided slice.
       *
       * @param comparator the comparator of the table this if a filter on.
       * @param slice the slice to check intersection with,
       *
       * @return whether the data selected by this filter intersects with {@code slice}.
       */
      public boolean intersects(ClusteringComparator comparator, Slice slice);
  
      public Kind kind();
  
      public String toString(TableMetadata metadata);
      public String toCQLString(TableMetadata metadata, RowFilter rowFilter);
  
      public interface Serializer
      {
          public void serialize(ClusteringIndexFilter filter, DataOutputPlus out, int version) throws IOException;
          public ClusteringIndexFilter deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException;
          public long serializedSize(ClusteringIndexFilter filter, int version);
      }
  }