PostProcessingModuleLoaderStrategy.java
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/
package gov.nist.secauto.metaschema.databind;
import gov.nist.secauto.metaschema.core.model.IBoundObject;
import gov.nist.secauto.metaschema.core.model.IModule;
import gov.nist.secauto.metaschema.core.model.IModuleLoader;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.databind.IBindingContext.IBindingMatcher;
import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
import gov.nist.secauto.metaschema.databind.model.IBoundModule;
import gov.nist.secauto.metaschema.databind.model.metaschema.binding.MetaschemaModelModule;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import edu.umd.cs.findbugs.annotations.NonNull;
public class PostProcessingModuleLoaderStrategy
implements IBindingContext.IModuleLoaderStrategy {
@NonNull
private final List<IModuleLoader.IModulePostProcessor> modulePostProcessors;
// private final Set<IModule> resolvedModules = new HashSet<>();
// private final Lock resolvedModulesLock = new ReentrantLock();
private final IBindingContext.IModuleLoaderStrategy delegate;
private final Set<IModule> postProcessedModules = new HashSet<>();
private final Lock postProcessedModulesLock = new ReentrantLock();
public PostProcessingModuleLoaderStrategy(
@NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors) {
this(modulePostProcessors, new SimpleModuleLoaderStrategy());
}
public PostProcessingModuleLoaderStrategy(
@NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors,
@NonNull IBindingContext.IModuleLoaderStrategy delegate) {
this.modulePostProcessors = CollectionUtil.unmodifiableList(new ArrayList<>(modulePostProcessors));
this.delegate = delegate;
}
@NonNull
protected List<IModuleLoader.IModulePostProcessor> getModulePostProcessors() {
return modulePostProcessors;
}
@Override
public IBoundModule loadModule(Class<? extends IBoundModule> clazz, IBindingContext bindingContext) {
return delegate.loadModule(clazz, bindingContext);
}
@Override
public void postProcessModule(IModule module, IBindingContext bindingContext) {
processModule(module);
delegate.postProcessModule(module, bindingContext);
}
@Override
public IBoundModule registerModule(IModule module, IBindingContext bindingContext) {
IBoundModule boundModule;
postProcessedModulesLock.lock();
try {
// process before registering
processModule(module);
boundModule = delegate.registerModule(module, bindingContext);
// ensure the resulting bound module is not processed again
postProcessedModules.add(boundModule);
} finally {
postProcessedModulesLock.unlock();
}
return boundModule;
}
private void processModule(@NonNull IModule module) {
postProcessedModulesLock.lock();
try {
if (!postProcessedModules.contains(module)) {
// do not post-process the built-in Metaschema module, since it has already been
// pre-processed
if (!(module instanceof MetaschemaModelModule)) {
for (IModuleLoader.IModulePostProcessor postProcessor : getModulePostProcessors()) {
postProcessor.processModule(module);
}
}
postProcessedModules.add(module);
}
} finally {
postProcessedModulesLock.unlock();
}
}
@Override
public Collection<IBindingMatcher> getBindingMatchers() {
return delegate.getBindingMatchers();
}
@Override
public IBoundDefinitionModelComplex getBoundDefinitionForClass(
Class<? extends IBoundObject> clazz,
IBindingContext bindingContext) {
//
// resolvedModulesLock.lock();
// try {
// if (!resolvedModules.contains(module)) {
// // add first, to avoid loops
// resolvedModules.add(module);
// for (IModuleLoader.IModulePostProcessor postProcessor :
// getModulePostProcessors()) {
// postProcessor.processModule(module);
// }
// }
// } finally {
// resolvedModulesLock.unlock();
// }
return delegate.getBoundDefinitionForClass(clazz, bindingContext);
}
}