001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.core.model;
007
008import dev.metaschema.core.datatype.markup.MarkupLine;
009import edu.umd.cs.findbugs.annotations.NonNull;
010import edu.umd.cs.findbugs.annotations.Nullable;
011
012/**
013 * Represents an instance that references a definition.
014 * <p>
015 * This interface provides common functionality for instances that reference
016 * definitions rather than defining their own inline structure. It handles
017 * effective value resolution by delegating to the referenced definition when
018 * the instance does not override a value.
019 *
020 * @param <DEFINITION>
021 *          the Java type of the referenced definition
022 * @param <INSTANCE>
023 *          the Java type of the inline instance (when definition is inline)
024 */
025public interface IFeatureDefinitionReferenceInstance<
026    DEFINITION extends IDefinition,
027    INSTANCE extends INamedInstance>
028    extends INamedInstance {
029
030  @Override
031  DEFINITION getDefinition();
032
033  @Override
034  default boolean isInlineDefinition() {
035    return false;
036  }
037
038  /**
039   * Get the instance this definition is combined with.
040   *
041   * @return the instance or {@code null} if the definition is not inline
042   */
043  @Nullable
044  default INSTANCE getInlineInstance() {
045    return null;
046  }
047
048  @Override
049  default String getEffectiveFormalName() {
050    String result = getFormalName();
051    return result == null ? getDefinition().getEffectiveFormalName() : result;
052  }
053
054  @Override
055  default MarkupLine getEffectiveDescription() {
056    MarkupLine result = getDescription();
057    return result == null ? getDefinition().getEffectiveDescription() : result;
058  }
059
060  @Override
061  @NonNull
062  default String getEffectiveName() {
063    String result = getUseName();
064    if (result == null) {
065      // fall back to the definition
066      IDefinition def = getDefinition();
067      result = def.getEffectiveName();
068    }
069    return result;
070  }
071
072  @Override
073  @Nullable
074  default Integer getEffectiveIndex() {
075    Integer result = getUseIndex();
076    if (result == null) {
077      // fall back to the definition
078      IDefinition def = getDefinition();
079      result = def.getEffectiveIndex();
080    }
081    return result;
082  }
083
084  /**
085   * The resolved default value, which allows an instance to override a
086   * definition's default value.
087   *
088   * @return the default value or {@code null} if not defined on either the
089   *         instance or definition
090   */
091  @Override
092  @Nullable
093  default Object getEffectiveDefaultValue() {
094    Object retval = getDefaultValue();
095    if (retval == null) {
096      retval = getDefinition().getDefaultValue();
097    }
098    return retval;
099  }
100}