001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.databind.io;
007
008import dev.metaschema.core.configuration.AbstractConfigurationFeature;
009import dev.metaschema.core.model.IAssemblyDefinition;
010import edu.umd.cs.findbugs.annotations.NonNull;
011
012/**
013 * Configuration features that control the deserialization behavior of
014 * Metaschema-bound object readers.
015 * <p>
016 * Each feature has a default value that can be overridden when configuring a
017 * deserializer.
018 *
019 * @param <V>
020 *          the value type of the configuration feature
021 */
022@SuppressWarnings("PMD.DataClass") // not a data class
023public final class DeserializationFeature<V>
024    extends AbstractConfigurationFeature<V> {
025  /**
026   * The default maximum number of codepoints that can be read from a YAML
027   * document.
028   */
029  public static final int YAML_CODEPOINT_LIMIT_DEFAULT = Integer.MAX_VALUE - 1; // 2 GB
030  /**
031   * The default number of bytes used for format detection lookahead.
032   */
033  public static final int FORMAT_DETECTION_LOOKAHEAD = 32_768; // 32 KB
034
035  /**
036   * If enabled, perform constraint validation on the deserialized bound objects.
037   */
038  @NonNull
039  public static final DeserializationFeature<Boolean> DESERIALIZE_VALIDATE_CONSTRAINTS
040      = new DeserializationFeature<>("validate", Boolean.class, false);
041
042  /**
043   * If enabled, allow inline XML entities to be automatically replaced.
044   */
045  @NonNull
046  public static final DeserializationFeature<Boolean> DESERIALIZE_XML_ALLOW_ENTITY_RESOLUTION
047      = new DeserializationFeature<>("allow-entity-resolution", Boolean.class, false);
048
049  /**
050   * If enabled, process the next JSON node as a field, whose name must match the
051   * {@link IAssemblyDefinition#getRootJsonName()}. If not enabled, the next JSON
052   * node is expected to be an object containing the data of the
053   * {@link IAssemblyDefinition}.
054   */
055  @NonNull
056  public static final DeserializationFeature<Boolean> DESERIALIZE_JSON_ROOT_PROPERTY
057      = new DeserializationFeature<>("deserialize-root-property", Boolean.class, true);
058
059  /**
060   * Determines the max YAML codepoints that can be read.
061   */
062  @NonNull
063  public static final DeserializationFeature<Integer> YAML_CODEPOINT_LIMIT
064      = new DeserializationFeature<>("yaml-codepoint-limit", Integer.class, YAML_CODEPOINT_LIMIT_DEFAULT);
065
066  /**
067   * Determines how many bytes can be looked at to identify the format of a
068   * document.
069   */
070  @NonNull
071  public static final DeserializationFeature<Integer> FORMAT_DETECTION_LOOKAHEAD_LIMIT
072      = new DeserializationFeature<>("format-detection-lookahead-limit", Integer.class, FORMAT_DETECTION_LOOKAHEAD);
073
074  /**
075   * If enabled, validate that required fields are present during deserialization.
076   * When a required field is missing and has no default value, an error will be
077   * thrown with a descriptive message.
078   * <p>
079   * Choice groups are handled correctly: if an instance belongs to a choice and
080   * at least one sibling in that choice was provided, the instance is not
081   * considered missing.
082   * <p>
083   * When using schema validation via CLI commands, this feature is automatically
084   * disabled since the schema already validates required fields.
085   */
086  @NonNull
087  public static final DeserializationFeature<Boolean> DESERIALIZE_VALIDATE_REQUIRED_FIELDS
088      = new DeserializationFeature<>("validate-required-fields", Boolean.class, true);
089
090  /**
091   * Construct a new deserialization feature.
092   *
093   * @param name
094   *          the feature name used for identification
095   * @param valueClass
096   *          the class of the feature value type
097   * @param defaultValue
098   *          the default value for this feature
099   */
100  private DeserializationFeature(
101      @NonNull String name,
102      @NonNull Class<V> valueClass,
103      @NonNull V defaultValue) {
104    super(name, valueClass, defaultValue);
105  }
106}