1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind;
7   
8   import gov.nist.secauto.metaschema.core.model.IBoundObject;
9   import gov.nist.secauto.metaschema.core.util.ObjectUtils;
10  import gov.nist.secauto.metaschema.databind.model.AbstractBoundModule;
11  import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
12  import gov.nist.secauto.metaschema.databind.model.IBoundModule;
13  import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
14  import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaField;
15  import gov.nist.secauto.metaschema.databind.model.impl.DefinitionAssembly;
16  import gov.nist.secauto.metaschema.databind.model.impl.DefinitionField;
17  
18  import java.util.Map;
19  import java.util.concurrent.ConcurrentHashMap;
20  
21  import edu.umd.cs.findbugs.annotations.NonNull;
22  import edu.umd.cs.findbugs.annotations.Nullable;
23  
24  public class SimpleModuleLoaderStrategy implements IBindingContext.IModuleLoaderStrategy {
25    @NonNull
26    private final IBindingContext bindingContext;
27    @NonNull
28    private final Map<Class<?>, IBoundModule> modulesByClass = new ConcurrentHashMap<>();
29    @NonNull
30    private final Map<Class<?>, IBoundDefinitionModelComplex> definitionsByClass = new ConcurrentHashMap<>();
31  
32    protected SimpleModuleLoaderStrategy(@NonNull IBindingContext bindingContext) {
33      this.bindingContext = bindingContext;
34    }
35  
36    @NonNull
37    private IBindingContext getBindingContext() {
38      return bindingContext;
39    }
40  
41    @Override
42    public IBoundModule loadModule(@NonNull Class<? extends IBoundModule> clazz) {
43      IBoundModule retval;
44      synchronized (this) {
45        retval = modulesByClass.get(clazz);
46        if (retval == null) {
47          retval = AbstractBoundModule.createInstance(clazz, getBindingContext());
48          modulesByClass.put(clazz, retval);
49        }
50      }
51      return ObjectUtils.notNull(retval);
52    }
53  
54    @Override
55    public IBoundDefinitionModelComplex getBoundDefinitionForClass(@NonNull Class<? extends IBoundObject> clazz) {
56      IBoundDefinitionModelComplex retval;
57      synchronized (this) {
58        retval = definitionsByClass.get(clazz);
59        if (retval == null) {
60          retval = newBoundDefinition(clazz);
61          if (retval != null) {
62            definitionsByClass.put(clazz, retval);
63          }
64        }
65      }
66      return retval;
67    }
68  
69    @Nullable
70    private IBoundDefinitionModelComplex newBoundDefinition(@NonNull Class<? extends IBoundObject> clazz) {
71      IBoundDefinitionModelComplex retval = null;
72      if (clazz.isAnnotationPresent(MetaschemaAssembly.class)) {
73        retval = DefinitionAssembly.newInstance(clazz, getBindingContext());
74      } else if (clazz.isAnnotationPresent(MetaschemaField.class)) {
75        retval = DefinitionField.newInstance(clazz, getBindingContext());
76      }
77      return retval;
78    }
79  }