001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.metaschema.databind; 007 008import gov.nist.secauto.metaschema.core.model.IBoundObject; 009import gov.nist.secauto.metaschema.core.model.IModule; 010import gov.nist.secauto.metaschema.core.model.IModuleLoader; 011import gov.nist.secauto.metaschema.core.util.CollectionUtil; 012import gov.nist.secauto.metaschema.databind.IBindingContext.IBindingMatcher; 013import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex; 014import gov.nist.secauto.metaschema.databind.model.IBoundModule; 015 016import java.util.ArrayList; 017import java.util.Collection; 018import java.util.HashSet; 019import java.util.List; 020import java.util.Set; 021import java.util.concurrent.locks.Lock; 022import java.util.concurrent.locks.ReentrantLock; 023 024import edu.umd.cs.findbugs.annotations.NonNull; 025 026public class PostProcessingModuleLoaderStrategy 027 implements IBindingContext.IModuleLoaderStrategy { 028 @NonNull 029 private final List<IModuleLoader.IModulePostProcessor> modulePostProcessors; 030 // private final Set<IModule> resolvedModules = new HashSet<>(); 031 // private final Lock resolvedModulesLock = new ReentrantLock(); 032 private final IBindingContext.IModuleLoaderStrategy delegate; 033 private final Set<IModule> postProcessedModules = new HashSet<>(); 034 private final Lock postProcessedModulesLock = new ReentrantLock(); 035 036 public PostProcessingModuleLoaderStrategy( 037 @NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors) { 038 this(modulePostProcessors, new SimpleModuleLoaderStrategy()); 039 } 040 041 public PostProcessingModuleLoaderStrategy( 042 @NonNull List<IModuleLoader.IModulePostProcessor> modulePostProcessors, 043 @NonNull IBindingContext.IModuleLoaderStrategy delegate) { 044 this.modulePostProcessors = CollectionUtil.unmodifiableList(new ArrayList<>(modulePostProcessors)); 045 this.delegate = delegate; 046 } 047 048 @NonNull 049 protected List<IModuleLoader.IModulePostProcessor> getModulePostProcessors() { 050 return modulePostProcessors; 051 } 052 053 @Override 054 public IBoundModule loadModule(Class<? extends IBoundModule> clazz, IBindingContext bindingContext) { 055 return delegate.loadModule(clazz, bindingContext); 056 } 057 058 @Override 059 public void postProcessModule(IModule module, IBindingContext bindingContext) { 060 processModule(module); 061 delegate.postProcessModule(module, bindingContext); 062 } 063 064 @Override 065 public IBoundModule registerModule(IModule module, IBindingContext bindingContext) { 066 IBoundModule boundModule; 067 postProcessedModulesLock.lock(); 068 try { 069 // process before registering 070 processModule(module); 071 072 boundModule = delegate.registerModule(module, bindingContext); 073 074 // ensure the resulting bound module is not processed again 075 postProcessedModules.add(boundModule); 076 } finally { 077 postProcessedModulesLock.unlock(); 078 } 079 return boundModule; 080 } 081 082 /** 083 * Perform post-processing on the provided module. 084 * 085 * @param module 086 * the module to post process 087 */ 088 protected void processModule(@NonNull IModule module) { 089 postProcessedModulesLock.lock(); 090 try { 091 if (!postProcessedModules.contains(module)) { 092 for (IModuleLoader.IModulePostProcessor postProcessor : getModulePostProcessors()) { 093 postProcessor.processModule(module); 094 } 095 postProcessedModules.add(module); 096 } 097 } finally { 098 postProcessedModulesLock.unlock(); 099 } 100 } 101 102 @Override 103 public Collection<IBindingMatcher> getBindingMatchers() { 104 return delegate.getBindingMatchers(); 105 } 106 107 @Override 108 public IBoundDefinitionModelComplex getBoundDefinitionForClass( 109 Class<? extends IBoundObject> clazz, 110 IBindingContext bindingContext) { 111 112 // 113 // resolvedModulesLock.lock(); 114 // try { 115 // if (!resolvedModules.contains(module)) { 116 // // add first, to avoid loops 117 // resolvedModules.add(module); 118 // for (IModuleLoader.IModulePostProcessor postProcessor : 119 // getModulePostProcessors()) { 120 // postProcessor.processModule(module); 121 // } 122 // } 123 // } finally { 124 // resolvedModulesLock.unlock(); 125 // } 126 return delegate.getBoundDefinitionForClass(clazz, bindingContext); 127 } 128}