1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.model;
7   
8   import java.util.Locale;
9   
10  import dev.metaschema.core.model.constraint.IFeatureValueConstrained;
11  import dev.metaschema.core.qname.IEnhancedQName;
12  import edu.umd.cs.findbugs.annotations.NonNull;
13  import edu.umd.cs.findbugs.annotations.Nullable;
14  
15  /**
16   * Represents a definition of a flag, field, or assembly in a Metaschema module.
17   * <p>
18   * Definitions are reusable components that specify the structure and
19   * constraints for data elements. They can be referenced by instances or defined
20   * inline.
21   */
22  public interface IDefinition extends INamedModelElement, IAttributable, IFeatureValueConstrained {
23    /**
24     * Describes the visibility of a definition to other modules.
25     */
26    enum ModuleScope {
27      /**
28       * The definition is scoped to only the defining module.
29       */
30      PRIVATE,
31      /**
32       * The definition is scoped to its defining module and any importing module.
33       */
34      PUBLIC;
35    }
36  
37    /**
38     * The default module scope for definitions.
39     */
40    @NonNull
41    ModuleScope DEFAULT_MODULE_SCOPE = ModuleScope.PUBLIC;
42  
43    /**
44     * Retrieve the definition's scope within the context of its defining module.
45     *
46     * @return the module scope
47     */
48    @NonNull
49    default ModuleScope getModuleScope() {
50      return ModuleScope.PRIVATE;
51    }
52  
53    /**
54     * The qualified name for the definition.
55     * <p>
56     * This name is the combination of the definition's namespace, which is the
57     * module's namespace, and the definition's name.
58     *
59     * @return the definition's qualified name
60     */
61    @NonNull
62    IEnhancedQName getDefinitionQName();
63  
64    /**
65     * Determine if the definition is defined inline, meaning the definition is
66     * declared where it is used.
67     * <p>
68     * If this method returns {@code false}, then {@link #getInlineInstance()} must
69     * return {@code null}.
70     *
71     * @return {@code true} if the definition is declared inline or {@code false} if
72     *         the definition is able to be globally referenced
73     * @see #getInlineInstance()
74     */
75    default boolean isInline() {
76      return getInlineInstance() != null;
77    }
78  
79    /**
80     * If {@link #isInline()} is {@code true}, return the instance the definition is
81     * inlined for.
82     * <p>
83     * If this method returns {@code null}, then {@link #getInlineInstance()} must
84     * return {@code false}.
85     *
86     * @return the instance or {@code null} otherwise
87     * @see #isInline()
88     */
89    INamedInstance getInlineInstance();
90  
91    /**
92     * Generates a coordinate string for the provided information element
93     * definition.
94     *
95     * A coordinate consists of the element's:
96     * <ul>
97     * <li>containing Metaschema's short name
98     * <li>model type
99     * <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 }