001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.core.model;
007
008import java.util.Collection;
009import java.util.List;
010import java.util.function.Predicate;
011import java.util.stream.Collectors;
012import java.util.stream.Stream;
013
014import dev.metaschema.core.qname.IEnhancedQName;
015import dev.metaschema.core.util.ObjectUtils;
016import edu.umd.cs.findbugs.annotations.NonNull;
017import edu.umd.cs.findbugs.annotations.Nullable;
018
019/**
020 * The API for accessing information about a given Metaschema module.
021 * <p>
022 * A Metaschem module may import another Metaschema module. This import graph
023 * can be accessed using {@link #getImportedModules()}.
024 * <p>
025 * Global scoped Metaschema definitions can be accessed using
026 * {@link #getScopedAssemblyDefinitionByName(Integer)},
027 * {@link #getScopedFieldDefinitionByName(Integer)}, and
028 * {@link #getScopedFlagDefinitionByName(IEnhancedQName)}. These methods take
029 * into consideration the import order to provide the global definitions that
030 * are in scope within the given Metschema module.
031 * <p>
032 * Global scoped definitions exported by this Metaschema module, available for
033 * use by importing Metaschema modules, can be accessed using
034 * {@link #getExportedAssemblyDefinitions()},
035 * {@link #getExportedFieldDefinitions()}, and
036 * {@link #getExportedFlagDefinitions()}.
037 * <p>
038 * Global scoped definitions defined directly within the given Metaschema module
039 * can be accessed using {@link #getAssemblyDefinitions()},
040 * {@link #getFieldDefinitions()}, and {@link #getFlagDefinitions()}, along with
041 * similarly named access methods.
042 *
043 * @param <M>
044 *          the imported module Java type
045 * @param <D>
046 *          the model definition Java type
047 * @param <FL>
048 *          the flag definition Java type
049 * @param <FI>
050 *          the field definition Java type
051 * @param <A>
052 *          the assembly definition Java type
053 */
054public interface IModuleExtended<
055    M extends IModuleExtended<M, D, FL, FI, A>,
056    D extends IModelDefinition,
057    FL extends IFlagDefinition,
058    FI extends IFieldDefinition,
059    A extends IAssemblyDefinition> extends IModule {
060
061  /**
062   * Get a filter that will match all definitions that are not locally defined.
063   *
064   * @param <DEF>
065   *          the type of definition
066   * @return a predicate implementing the filter
067   */
068  static <DEF extends IDefinition> Predicate<DEF> allNonLocalDefinitions() {
069    return definition -> definition.getModuleScope() == IDefinition.ModuleScope.PUBLIC
070        || definition.getModelType() == ModelType.ASSEMBLY
071            && ((IAssemblyDefinition) definition).isRoot();
072  }
073
074  /**
075   * Get a filter that will match all definitions that are root assemblies.
076   *
077   * @param <DEF>
078   *          the type of definition
079   * @return a predicate implementing the filter
080   */
081  static <DEF extends IDefinition> Predicate<DEF> allRootAssemblyDefinitions() {
082    return definition -> definition.getModelType() == ModelType.ASSEMBLY
083        && ((IAssemblyDefinition) definition).isRoot();
084  }
085
086  @Override
087  @NonNull
088  List<? extends M> getImportedModules();
089
090  @Override
091  @Nullable
092  M getImportedModuleByShortName(String name);
093
094  @Override
095  @NonNull
096  Collection<FL> getFlagDefinitions();
097
098  @Override
099  @Nullable
100  FL getFlagDefinitionByName(@NonNull IEnhancedQName name);
101
102  @Override
103  @NonNull
104  Collection<A> getAssemblyDefinitions();
105
106  @Override
107  @Nullable
108  A getAssemblyDefinitionByName(@NonNull Integer name);
109
110  @Override
111  @NonNull
112  Collection<FI> getFieldDefinitions();
113
114  @Override
115  @Nullable
116  FI getFieldDefinitionByName(@NonNull Integer name);
117
118  @Override
119  @SuppressWarnings("unchecked")
120  @NonNull
121  default List<D> getAssemblyAndFieldDefinitions() {
122    return ObjectUtils.notNull(
123        Stream.concat(
124            (Stream<D>) getAssemblyDefinitions().stream(),
125            (Stream<D>) getFieldDefinitions().stream())
126            .collect(Collectors.toList()));
127  }
128
129  @Override
130  @Nullable
131  default A getScopedAssemblyDefinitionByName(@NonNull Integer name) {
132    // first try local/global top-level definitions from current metaschema module
133    A retval = getAssemblyDefinitionByName(name);
134    if (retval == null) {
135      // try global definitions from imported Metaschema modules
136      retval = getExportedAssemblyDefinitionByName(name);
137    }
138    return retval;
139  }
140
141  @Override
142  @Nullable
143  default FI getScopedFieldDefinitionByName(@NonNull Integer name) {
144    // first try local/global top-level definitions from current metaschema module
145    FI retval = getFieldDefinitionByName(name);
146    if (retval == null) {
147      // try global definitions from imported metaschema modules
148      retval = getExportedFieldDefinitionByName(name);
149    }
150    return retval;
151  }
152
153  @Override
154  @Nullable
155  default FL getScopedFlagDefinitionByName(@NonNull IEnhancedQName name) {
156    // first try local/global top-level definitions from current metaschema module
157    FL retval = getFlagDefinitionByName(name);
158    if (retval == null) {
159      // try global definitions from imported metaschema modules
160      retval = getExportedFlagDefinitionByName(name);
161    }
162    return retval;
163  }
164
165  @Override
166  @NonNull
167  default Collection<? extends A> getExportedRootAssemblyDefinitions() {
168    return ObjectUtils.notNull(getExportedAssemblyDefinitions().stream()
169        .filter(allRootAssemblyDefinitions())
170        .collect(Collectors.toList()));
171  }
172
173  @Override
174  @NonNull
175  default Collection<? extends A> getRootAssemblyDefinitions() {
176    return ObjectUtils.notNull(getAssemblyDefinitions().stream()
177        .filter(allRootAssemblyDefinitions())
178        .collect(Collectors.toList()));
179  }
180
181  @Override
182  @NonNull
183  Collection<? extends FL> getExportedFlagDefinitions();
184
185  @Override
186  @Nullable
187  FL getExportedFlagDefinitionByName(IEnhancedQName name);
188
189  @Override
190  @NonNull
191  Collection<? extends FI> getExportedFieldDefinitions();
192
193  @Override
194  @Nullable
195  FI getExportedFieldDefinitionByName(Integer name);
196
197  @Override
198  @NonNull
199  Collection<? extends A> getExportedAssemblyDefinitions();
200
201  @Override
202  @Nullable
203  A getExportedAssemblyDefinitionByName(Integer name);
204}