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