001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.core.model;
007
008import java.util.function.Predicate;
009
010import edu.umd.cs.findbugs.annotations.NonNull;
011import edu.umd.cs.findbugs.annotations.Nullable;
012
013/**
014 * Represents a named instance of a field or assembly within a model.
015 * <p>
016 * Provides access to the instance's definition and JSON key configuration for
017 * serialization purposes.
018 */
019public interface INamedModelInstance extends IModelInstance, INamedInstance {
020
021  /**
022   * Tests if the provided instance represents complex data. The data is complex
023   * if one of the following is true:
024   * <ul>
025   * <li>The instance is a {@link IAssemblyInstance}.
026   * <li>The instance is a {@link IFieldInstance} that has flags.
027   * </ul>
028   *
029   * This method can be used as a {@link Predicate}.
030   *
031   * @param instance
032   *          the instance to test
033   * @return {@code true} if the data is complex, or {@code false} otherwise
034   */
035  static boolean complexObjectFilter(INamedModelInstance instance) {
036    boolean retval = true;
037    if (instance instanceof IFieldInstance) {
038      IFieldInstance field = (IFieldInstance) instance;
039      retval = !field.getDefinition().getFlagInstances().isEmpty();
040    }
041    return retval;
042  }
043
044  @Override
045  @NonNull
046  IModelDefinition getDefinition();
047
048  /**
049   * Indicates if a flag's value can be used as a property name in the containing
050   * object in JSON whose value will be the object containing the flag. In such
051   * cases, the flag will not appear in the object. This is only allowed if the
052   * flag is required, as determined by a {@code true} result from
053   * {@link IFlagInstance#isRequired()}. The {@link IFlagInstance} can be
054   * retrieved using {@link #getEffectiveJsonKey()}.
055   *
056   * @return {@code true} if the flag's value can be used as a property name, or
057   *         {@code false} otherwise
058   * @see #getEffectiveJsonKey()
059   */
060  // TODO: remove once moved to the instance side
061  default boolean hasJsonKey() {
062    return getEffectiveJsonKey() != null;
063  }
064
065  /**
066   * Get the JSON key flag instance for this model instance, if one is configured.
067   *
068   * @return the JSON key flag instance or {@code null} if no JSON key is
069   *         configured
070   */
071  @Nullable
072  IFlagInstance getEffectiveJsonKey();
073
074  /**
075   * Get the JSON key associated with this instance.
076   *
077   * @return the configured JSON key or {@code null} if no JSON key is configured
078   */
079  @Nullable
080  IFlagInstance getJsonKey();
081}