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.kafka.streams.state;
  
  import org.apache.kafka.common.serialization.Serializer;
  import org.apache.kafka.streams.errors.InvalidStateStoreException;
  
  /**
   * A key-value store that only supports read operations.
   * Implementations should be thread-safe as concurrent reads and writes are expected.
   * <p>
   * Please note that this contract defines the thread-safe read functionality only; it does not
   * guarantee anything about whether the actual instance is writable by another thread, or
   * whether it uses some locking mechanism under the hood. For this reason, making dependencies
   * between the read and write operations on different StateStore instances can cause concurrency
   * problems like deadlock.
   *
   * @param <K> the key type
   * @param <V> the value type
   */
  public interface ReadOnlyKeyValueStore<K, V> {
  
      /**
       * Get the value corresponding to this key.
       *
       * @param key The key to fetch
       * @return The value or null if no value is found.
       * @throws NullPointerException       If null is used for key.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      V get(K key);
  
      /**
       * Get an iterator over a given range of keys. This iterator must be closed after use.
       * The returned iterator must be safe from {@link java.util.ConcurrentModificationException}s
       * and must not return null values.
       * Order is based on the serialized byte[] of the keys, not the 'logical' key order.
       *
       * @param from The first key that could be in the range, where iteration starts from.
       *             A null value indicates that the range starts with the first element in the store.
       * @param to   The last key that could be in the range, where iteration ends.
       *             A null value indicates that the range ends with the last element in the store.
       * @return The iterator for this range, from key with the smallest bytes to the key with the largest bytes of keys.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      KeyValueIterator<K, V> range(K from, K to);
  
      /**
       * Get a reverse iterator over a given range of keys. This iterator must be closed after use.
       * The returned iterator must be safe from {@link java.util.ConcurrentModificationException}s
       * and must not return null values.
       * Order is based on the serialized byte[] of the keys, not the 'logical' key order.
       *
       * @param from The first key that could be in the range, where iteration ends.
       *             A null value indicates that the range starts with the first element in the store.
       * @param to   The last key that could be in the range, where iteration starts from.
       *             A null value indicates that the range ends with the last element in the store.
       * @return The iterator for this range, from key with the smallest bytes to the key with the largest bytes of keys.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      default KeyValueIterator<K, V> reverseRange(K from, K to) {
          throw new UnsupportedOperationException();
      }
  
      /**
       * Return an iterator over all keys in this store. This iterator must be closed after use.
       * The returned iterator must be safe from {@link java.util.ConcurrentModificationException}s
       * and must not return null values.
       * Order is not guaranteed as bytes lexicographical ordering might not represent key order.
       *
       * @return An iterator of all key/value pairs in the store, from smallest to largest bytes.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      KeyValueIterator<K, V> all();
  
      /**
       * Return a reverse iterator over all keys in this store. This iterator must be closed after use.
       * The returned iterator must be safe from {@link java.util.ConcurrentModificationException}s
       * and must not return null values.
       * Order is not guaranteed as bytes lexicographical ordering might not represent key order.
       *
       * @return A reverse iterator of all key/value pairs in the store, from largest to smallest key bytes.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      default KeyValueIterator<K, V> reverseAll() {
          throw new UnsupportedOperationException();
      }
  
      /**
       * Return an iterator over all keys with the specified prefix.
       * Since the type of the prefix can be different from that of the key, a serializer to convert the
       * prefix into the format in which the keys are stored in the stores needs to be passed to this method.
       * The returned iterator must be safe from {@link java.util.ConcurrentModificationException}s
       * and must not return null values.
       * Since {@code prefixScan()} relies on byte lexicographical ordering and not on the ordering of the key type, results for some types might be unexpected.
       * For example, if the key type is {@code Integer}, and the store contains keys [1, 2, 11, 13],
       * then running {@code store.prefixScan(1, new IntegerSerializer())} will return [1] and not [1,11,13]. 
       * In contrast, if the key type is {@code String} the keys will be sorted [1, 11, 13, 2] in the store and {@code store.prefixScan(1, new StringSerializer())} will return [1,11,13]. 
       * In both cases {@code prefixScan()} starts the scan at 1 and stops at 2.
       *
       * @param prefix The prefix.
       * @param prefixKeySerializer Serializer for the Prefix key type
       * @param <PS> Prefix Serializer type
       * @param <P> Prefix Type.
       * @return The iterator for keys having the specified prefix.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      default <PS extends Serializer<P>, P> KeyValueIterator<K, V> prefixScan(P prefix, PS prefixKeySerializer) {
          throw new UnsupportedOperationException();
      }
  
      /**
       * Return an approximate count of key-value mappings in this store.
       * <p>
       * The count is not guaranteed to be exact in order to accommodate stores
       * where an exact count is expensive to calculate.
       *
       * @return an approximate count of key-value mappings in the store.
       * @throws InvalidStateStoreException if the store is not initialized
       */
      long approximateNumEntries();
  }
  