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