1
2
3
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.IBindingContext.IBindingMatcher;
13 import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
14 import gov.nist.secauto.metaschema.databind.model.IBoundModule;
15 import gov.nist.secauto.metaschema.databind.model.metaschema.binding.MetaschemaModelModule;
16
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Set;
22 import java.util.concurrent.locks.Lock;
23 import java.util.concurrent.locks.ReentrantLock;
24
25 import edu.umd.cs.findbugs.annotations.NonNull;
26
27 public class PostProcessingModuleLoaderStrategy
28 implements IBindingContext.IModuleLoaderStrategy {
29 @NonNull
30 private final List<IModuleLoader.IModulePostProcessor> modulePostProcessors;
31
32
33 private final IBindingContext.IModuleLoaderStrategy delegate;
34 private final Set<IModule> postProcessedModules = new HashSet<>();
35 private final Lock postProcessedModulesLock = new ReentrantLock();
36
37 public PostProcessingModuleLoaderStrategy(
38 @NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors) {
39 this(modulePostProcessors, new SimpleModuleLoaderStrategy());
40 }
41
42 public PostProcessingModuleLoaderStrategy(
43 @NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors,
44 @NonNull IBindingContext.IModuleLoaderStrategy delegate) {
45 this.modulePostProcessors = CollectionUtil.unmodifiableList(new ArrayList<>(modulePostProcessors));
46 this.delegate = delegate;
47 }
48
49 @NonNull
50 protected List<IModuleLoader.IModulePostProcessor> getModulePostProcessors() {
51 return modulePostProcessors;
52 }
53
54 @Override
55 public IBoundModule loadModule(Class<? extends IBoundModule> clazz, IBindingContext bindingContext) {
56 return delegate.loadModule(clazz, bindingContext);
57 }
58
59 @Override
60 public void postProcessModule(IModule module, IBindingContext bindingContext) {
61 processModule(module);
62 delegate.postProcessModule(module, bindingContext);
63 }
64
65 @Override
66 public IBoundModule registerModule(IModule module, IBindingContext bindingContext) {
67 IBoundModule boundModule;
68 postProcessedModulesLock.lock();
69 try {
70
71 processModule(module);
72
73 boundModule = delegate.registerModule(module, bindingContext);
74
75
76 postProcessedModules.add(boundModule);
77 } finally {
78 postProcessedModulesLock.unlock();
79 }
80 return boundModule;
81 }
82
83 private void processModule(@NonNull IModule module) {
84 postProcessedModulesLock.lock();
85 try {
86 if (!postProcessedModules.contains(module)) {
87
88
89 if (!(module instanceof MetaschemaModelModule)) {
90 for (IModuleLoader.IModulePostProcessor postProcessor : getModulePostProcessors()) {
91 postProcessor.processModule(module);
92 }
93 }
94 postProcessedModules.add(module);
95 }
96 } finally {
97 postProcessedModulesLock.unlock();
98 }
99 }
100
101 @Override
102 public Collection<IBindingMatcher> getBindingMatchers() {
103 return delegate.getBindingMatchers();
104 }
105
106 @Override
107 public IBoundDefinitionModelComplex getBoundDefinitionForClass(
108 Class<? extends IBoundObject> clazz,
109 IBindingContext bindingContext) {
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 return delegate.getBoundDefinitionForClass(clazz, bindingContext);
126 }
127 }