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.HashSet;
010import java.util.Set;
011import java.util.function.Function;
012
013import dev.metaschema.core.util.CollectionUtil;
014import edu.umd.cs.findbugs.annotations.NonNull;
015
016/**
017 * This model walker can be used to gather metaschema definitions that are
018 * defined globally.
019 */
020public class UsedDefinitionModelWalker
021    extends DefinitionCollectingModelWalker {
022  private static final Function<IDefinition, Boolean> FILTER = (def) -> {
023    return true;
024    // return def.isGlobal();
025    // return def.isGlobal() || (def instanceof AssemblyDefinition &&
026    // ((AssemblyDefinition)def).getRootName() != null);
027  };
028
029  /**
030   * Get the collection of all definitions used directly and transitively by the
031   * provided definitions.
032   *
033   * @param definitions
034   *          a collection of definitions to generate used definitions from
035   * @return the collection of used definitions
036   */
037  @NonNull
038  public static Collection<? extends IDefinition>
039      collectUsedDefinitions(Collection<? extends IAssemblyDefinition> definitions) {
040    UsedDefinitionModelWalker walker = new UsedDefinitionModelWalker();
041    for (IAssemblyDefinition definition : definitions) {
042      assert definition != null;
043      walker.walk(definition);
044    }
045    return walker.getDefinitions();
046  }
047
048  /**
049   * Collect the globally defined Metaschema definitions from the provided
050   * Metaschema modules, and any Metaschema modules imported directly or
051   * indirectly by these modules.
052   *
053   * @param modules
054   *          the Metaschema modules to analyze
055   * @return a collection of matching definitions
056   */
057  @NonNull
058  public static Collection<? extends IDefinition> collectUsedDefinitionsFromModule(
059      @NonNull Collection<? extends IModule> modules) {
060    Set<IAssemblyDefinition> definitions = new HashSet<>();
061    for (IModule module : modules) {
062      // get local roots in case they are scope=local
063      for (IAssemblyDefinition rootDef : module.getRootAssemblyDefinitions()) {
064        definitions.add(rootDef);
065      }
066
067      // get roots from exported
068      for (IAssemblyDefinition assembly : module.getExportedAssemblyDefinitions()) {
069        assert assembly != null;
070        if (assembly.isRoot()) {
071          definitions.add(assembly);
072        }
073      }
074    }
075    return collectUsedDefinitions(definitions);
076  }
077
078  /**
079   * Collect the globally defined Metaschema definitions from the provided
080   * Metaschema module, and any Metaschema modules imported directly or indirectly
081   * by this module.
082   *
083   * @param module
084   *          the metaschema module to analyze
085   * @return a collection of matching definitions
086   */
087  @NonNull
088  public static Collection<? extends IDefinition> collectUsedDefinitionsFromModule(
089      @NonNull IModule module) {
090    return collectUsedDefinitionsFromModule(CollectionUtil.singleton(module));
091  }
092
093  /**
094   * Construct a new walker.
095   */
096  protected UsedDefinitionModelWalker() {
097    super(FILTER);
098  }
099}