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.util.ObjectUtils;
010import gov.nist.secauto.metaschema.databind.model.AbstractBoundModule;
011import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
012import gov.nist.secauto.metaschema.databind.model.IBoundModule;
013import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
014import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaField;
015import gov.nist.secauto.metaschema.databind.model.impl.DefinitionAssembly;
016import gov.nist.secauto.metaschema.databind.model.impl.DefinitionField;
017
018import java.util.Map;
019import java.util.concurrent.ConcurrentHashMap;
020
021import edu.umd.cs.findbugs.annotations.NonNull;
022import edu.umd.cs.findbugs.annotations.Nullable;
023
024public class SimpleModuleLoaderStrategy implements IBindingContext.IModuleLoaderStrategy {
025  @NonNull
026  private final IBindingContext bindingContext;
027  @NonNull
028  private final Map<Class<?>, IBoundModule> modulesByClass = new ConcurrentHashMap<>();
029  @NonNull
030  private final Map<Class<?>, IBoundDefinitionModelComplex> definitionsByClass = new ConcurrentHashMap<>();
031
032  protected SimpleModuleLoaderStrategy(@NonNull IBindingContext bindingContext) {
033    this.bindingContext = bindingContext;
034  }
035
036  @NonNull
037  private IBindingContext getBindingContext() {
038    return bindingContext;
039  }
040
041  @Override
042  public IBoundModule loadModule(@NonNull Class<? extends IBoundModule> clazz) {
043    IBoundModule retval;
044    synchronized (this) {
045      retval = modulesByClass.get(clazz);
046      if (retval == null) {
047        retval = AbstractBoundModule.createInstance(clazz, getBindingContext());
048        modulesByClass.put(clazz, retval);
049      }
050    }
051    return ObjectUtils.notNull(retval);
052  }
053
054  @Override
055  public IBoundDefinitionModelComplex getBoundDefinitionForClass(@NonNull Class<? extends IBoundObject> clazz) {
056    IBoundDefinitionModelComplex retval;
057    synchronized (this) {
058      retval = definitionsByClass.get(clazz);
059      if (retval == null) {
060        retval = newBoundDefinition(clazz);
061        if (retval != null) {
062          definitionsByClass.put(clazz, retval);
063        }
064      }
065    }
066    return retval;
067  }
068
069  @Nullable
070  private IBoundDefinitionModelComplex newBoundDefinition(@NonNull Class<? extends IBoundObject> clazz) {
071    IBoundDefinitionModelComplex retval = null;
072    if (clazz.isAnnotationPresent(MetaschemaAssembly.class)) {
073      retval = DefinitionAssembly.newInstance(clazz, getBindingContext());
074    } else if (clazz.isAnnotationPresent(MetaschemaField.class)) {
075      retval = DefinitionField.newInstance(clazz, getBindingContext());
076    }
077    return retval;
078  }
079}