001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.core.model;
007
008import java.util.Locale;
009
010import dev.metaschema.core.model.constraint.IFeatureValueConstrained;
011import dev.metaschema.core.qname.IEnhancedQName;
012import edu.umd.cs.findbugs.annotations.NonNull;
013import edu.umd.cs.findbugs.annotations.Nullable;
014
015/**
016 * Represents a definition of a flag, field, or assembly in a Metaschema module.
017 * <p>
018 * Definitions are reusable components that specify the structure and
019 * constraints for data elements. They can be referenced by instances or defined
020 * inline.
021 */
022public interface IDefinition extends INamedModelElement, IAttributable, IFeatureValueConstrained {
023  /**
024   * Describes the visibility of a definition to other modules.
025   */
026  enum ModuleScope {
027    /**
028     * The definition is scoped to only the defining module.
029     */
030    PRIVATE,
031    /**
032     * The definition is scoped to its defining module and any importing module.
033     */
034    PUBLIC;
035  }
036
037  /**
038   * The default module scope for definitions.
039   */
040  @NonNull
041  ModuleScope DEFAULT_MODULE_SCOPE = ModuleScope.PUBLIC;
042
043  /**
044   * Retrieve the definition's scope within the context of its defining module.
045   *
046   * @return the module scope
047   */
048  @NonNull
049  default ModuleScope getModuleScope() {
050    return ModuleScope.PRIVATE;
051  }
052
053  /**
054   * The qualified name for the definition.
055   * <p>
056   * This name is the combination of the definition's namespace, which is the
057   * module's namespace, and the definition's name.
058   *
059   * @return the definition's qualified name
060   */
061  @NonNull
062  IEnhancedQName getDefinitionQName();
063
064  /**
065   * Determine if the definition is defined inline, meaning the definition is
066   * declared where it is used.
067   * <p>
068   * If this method returns {@code false}, then {@link #getInlineInstance()} must
069   * return {@code null}.
070   *
071   * @return {@code true} if the definition is declared inline or {@code false} if
072   *         the definition is able to be globally referenced
073   * @see #getInlineInstance()
074   */
075  default boolean isInline() {
076    return getInlineInstance() != null;
077  }
078
079  /**
080   * If {@link #isInline()} is {@code true}, return the instance the definition is
081   * inlined for.
082   * <p>
083   * If this method returns {@code null}, then {@link #getInlineInstance()} must
084   * return {@code false}.
085   *
086   * @return the instance or {@code null} otherwise
087   * @see #isInline()
088   */
089  INamedInstance getInlineInstance();
090
091  /**
092   * Generates a coordinate string for the provided information element
093   * definition.
094   *
095   * A coordinate consists of the element's:
096   * <ul>
097   * <li>containing Metaschema's short name
098   * <li>model type
099   * <li>name
100   * <li>hash code
101   * </ul>
102   *
103   * @return the coordinate
104   */
105  @SuppressWarnings("null")
106  @Override
107  default String toCoordinates() {
108    return String.format("%s:%s-definition:%s(%d)",
109        getContainingModule().getShortName(),
110        getModelType().toString().toUpperCase(Locale.ROOT),
111        getName(),
112        hashCode());
113  }
114
115  /**
116   * Get the resource location information for the provided item, if known.
117   *
118   * @param itemValue
119   *          the item to get the location information for
120   *
121   * @return the resource location information, or {@code null} if not known
122   */
123  @Nullable
124  default IResourceLocation getLocation(@NonNull Object itemValue) {
125    return itemValue instanceof IBoundObject ? ((IBoundObject) itemValue).getMetaschemaData() : null;
126  }
127}