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; 015import gov.nist.secauto.metaschema.databind.model.metaschema.binding.MetaschemaModelModule; 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) { 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 private void processModule(@NonNull IModule module) { 084 postProcessedModulesLock.lock(); 085 try { 086 if (!postProcessedModules.contains(module)) { 087 // do not post-process the built-in Metaschema module, since it has already been 088 // pre-processed 089 if (!(module instanceof MetaschemaModelModule)) { 090 for (IModuleLoader.IModulePostProcessor postProcessor : getModulePostProcessors()) { 091 postProcessor.processModule(module); 092 } 093 } 094 postProcessedModules.add(module); 095 } 096 } finally { 097 postProcessedModulesLock.unlock(); 098 } 099 } 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 // resolvedModulesLock.lock(); 113 // try { 114 // if (!resolvedModules.contains(module)) { 115 // // add first, to avoid loops 116 // resolvedModules.add(module); 117 // for (IModuleLoader.IModulePostProcessor postProcessor : 118 // getModulePostProcessors()) { 119 // postProcessor.processModule(module); 120 // } 121 // } 122 // } finally { 123 // resolvedModulesLock.unlock(); 124 // } 125 return delegate.getBoundDefinitionForClass(clazz, bindingContext); 126 } 127}