content: package org.allaymc.api.pdc;
  
  import org.allaymc.api.utils.identifier.Identifier;
  import org.cloudburstmc.nbt.NbtMap;
  
  import java.util.Set;
  
  /**
   * Represents a read-only view of a {@link PersistentDataContainer}.
   * No methods in this interface modify the container.
   *
   * @author IWareQ | Bukkit
   * @see PersistentDataContainer
   */
  public interface PersistentDataContainerView {
      /**
       * Checks if the container has a value stored under the given key
       * and if it matches the specified primitive data type.
       *
       * <p>
       * This method returns {@code true} only if the stored value has the same
       * primitive type as the provided {@link PersistentDataType}.
       * </p>
       *
       * <p>
       * Since custom {@link PersistentDataType} implementations store only primitive
       * representations, complex types aren't checked.
       * For example, storing a UUID as a byte array will match {@link PersistentDataType#BYTE_ARRAY},
       * and vice versa, even if the byte array doesn't contain a valid UUID.
       * </p>
       *
       * <p>
       * This method applies only to custom object keys.
       * Overwriting standard tags, such as display names, will not work as those are stored using a namespace.
       * </p>
       *
       * @param key  the key under which the value is stored
       * @param type the expected primitive data type
       * @param <P>  the primitive type stored in the container
       * @param <C>  the complex type returned by the {@link PersistentDataType}
       *
       * @return {@code true} if a value with the given key and type exists; otherwise, {@code false}
       *
       * @throws IllegalArgumentException if {@code key} or {@code type} is {@code null}
       */
      <P, C> boolean has(Identifier key, PersistentDataType<P, C> type);
  
      /**
       * Checks if the container has a value stored under the given key,
       * regardless of its type.
       *
       * <p>
       * This method applies only to custom object keys.
       * Overwriting standard tags, such as display names, will not work as those are stored using a namespace.
       * </p>
       *
       * @param key the key under which the value is stored
       *
       * @return {@code true} if a value with the given key exists; otherwise, {@code false}
       *
       * @throws IllegalArgumentException if {@code key} is {@code null}
       */
      boolean has(Identifier key);
  
      /**
       * Retrieves the value stored under the given key.
       *
       * @param key  the key under which the value is stored
       * @param type the expected data type
       * @param <P>  the primitive type stored in the container
       * @param <C>  the complex type returned by the {@link PersistentDataType}
       *
       * @return the stored value or {@code null} if no matching value exists
       *
       * @throws IllegalArgumentException if {@code key} or {@code type} is {@code null}
       * @throws IllegalArgumentException if a value exists but can't be accessed with the given type
       * @throws IllegalArgumentException if no suitable adapter is found for {@link PersistentDataType#getPrimitiveType()}
       */
      <P, C> C get(Identifier key, PersistentDataType<P, C> type);
  
      /**
       * Retrieves the value stored under the given key, or returns a default value
       * if no such value exists.
       *
       * @param key          the key under which the value is stored
       * @param type         the expected data type
       * @param defaultValue the value to return if no stored value exists
       * @param <P>          the primitive type stored in the container
       * @param <C>          the complex type returned by the {@link PersistentDataType}
       *
       * @return the stored value or {@code defaultValue} if no matching value exists
       *
       * @throws IllegalArgumentException if {@code key} or {@code type} is {@code null}
       * @throws IllegalArgumentException if a value exists but can't be accessed with the given type
       * @throws IllegalArgumentException if no suitable adapter is found for {@link PersistentDataType#getPrimitiveType()}
       */
      <P, C> C getOrDefault(Identifier key, PersistentDataType<P, C> type, C defaultValue);
  
      /**
       * Returns the set of all keys present in this container.
       * <p>
       * Modifications to the returned set don't affect the underlying container.
       * </p>
       *
       * @return a set of keys stored in this container
       */
      Set<Identifier> getKeys();
  
      /**
       * Checks whether the container is empty.
       *
       * @return {@code true} if the container has no stored entries; otherwise, {@code false}
       */
      boolean isEmpty();
  
      /**
       * Returns the adapter context associated with this container.
       *
       * @return the {@link PersistentDataAdapterContext} used by this container
       */
      PersistentDataAdapterContext getAdapterContext();
  
      /**
       * Converts the data container to a {@link NbtMap}.
       *
       * @return a nbt representing the container
       */
      NbtMap toNbt();
  }
  