1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind;
7   
8   import gov.nist.secauto.metaschema.core.model.IBoundObject;
9   import gov.nist.secauto.metaschema.core.model.IModule;
10  import gov.nist.secauto.metaschema.core.model.IModuleLoader;
11  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
12  import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
13  
14  import java.util.ArrayList;
15  import java.util.HashSet;
16  import java.util.List;
17  import java.util.Set;
18  
19  import edu.umd.cs.findbugs.annotations.NonNull;
20  
21  class PostProcessingModuleLoaderStrategy
22      extends SimpleModuleLoaderStrategy {
23    @NonNull
24    private final List<IModuleLoader.IModulePostProcessor> modulePostProcessors;
25    private final Set<IModule> resolvedModules = new HashSet<>();
26  
27    protected PostProcessingModuleLoaderStrategy(
28        @NonNull IBindingContext bindingContext,
29        @NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors) {
30      super(bindingContext);
31      this.modulePostProcessors = CollectionUtil.unmodifiableList(new ArrayList<>(modulePostProcessors));
32    }
33  
34    @NonNull
35    protected List<IModuleLoader.IModulePostProcessor> getModulePostProcessors() {
36      return modulePostProcessors;
37    }
38  
39    @Override
40    public IBoundDefinitionModelComplex getBoundDefinitionForClass(@NonNull Class<? extends IBoundObject> clazz) {
41      IBoundDefinitionModelComplex retval = super.getBoundDefinitionForClass(clazz);
42      if (retval != null) {
43        // force loading of metaschema information to apply constraints
44        IModule module = retval.getContainingModule();
45        synchronized (resolvedModules) {
46          if (!resolvedModules.contains(module)) {
47            // add first, to avoid loops
48            resolvedModules.add(module);
49            handleModule(module);
50          }
51        }
52      }
53      return retval;
54    }
55  
56    private void handleModule(@NonNull IModule module) {
57      for (IModuleLoader.IModulePostProcessor postProcessor : getModulePostProcessors()) {
58        postProcessor.processModule(module);
59      }
60    }
61  }