From 52786ccc9906944dae96f76680be910cd78b4b1e Mon Sep 17 00:00:00 2001 From: David Waltermire Date: Tue, 19 Nov 2024 09:07:30 -0500 Subject: [PATCH] Refactored the implementations supporting model container generation, by reducing the number of implementations and implementing a builder pattern to store container information while the container is being built. Also removed a bunch of unneccsary interfaces and unwound some significant spaghetti code. --- .../core/datatype/DataTypeService.java | 8 + .../core/metapath/StaticContext.java | 32 ++- ...ava => AbstractContainerModelSupport.java} | 108 ++++---- .../model/DefaultAssemblyModelBuilder.java | 112 +++++++++ .../model/DefaultChoiceGroupModelBuilder.java | 117 +++++++++ .../core/model/DefaultChoiceModelBuilder.java | 81 ++++++ .../model/IContainerModelAssemblySupport.java | 3 +- .../core/model/IContainerModelSupport.java | 6 +- .../core/model/IFeatureContainerModel.java | 77 ------ .../model/IFeatureContainerModelAbsolute.java | 14 +- .../model/IFeatureContainerModelGrouped.java | 9 +- .../secauto/metaschema/core/model/INamed.java | 1 - .../DefaultContainerModelAssemblySupport.java | 56 +---- ...faultContainerModelChoiceGroupSupport.java | 61 +++++ .../impl/DefaultContainerModelSupport.java | 109 ++++++++ .../impl/DefaultContainerModelSupport.java | 182 -------------- .../core/model/xml/impl/ModelFactory.java | 1 - .../XmlAssemblyModelContainerSupport.java | 95 +++---- .../xml/impl/XmlChoiceGroupInstance.java | 208 ++++++++-------- .../model/xml/impl/XmlChoiceInstance.java | 212 ++++++++-------- .../metaschema/core/qname/EQNameFactory.java | 193 ++++++++++++++ ...eUtilsTest.java => StaticContextTest.java} | 7 +- .../model/IBoundContainerModelAssembly.java | 55 ---- .../IBoundContainerModelChoiceGroup.java | 44 ---- .../model/IBoundDefinitionModelAssembly.java | 26 +- .../model/IBoundInstanceModelChoiceGroup.java | 7 +- ...pport.java => AssemblyModelGenerator.java} | 104 ++------ .../model/impl/DefinitionAssembly.java | 28 ++- .../IFeatureBoundContainerModelAssembly.java | 91 ------- ...FeatureBoundContainerModelChoiceGroup.java | 71 ------ .../impl/IFeatureInstanceModelGroupAs.java | 1 - .../model/impl/InstanceModelChoiceGroup.java | 123 +++------ .../impl/AbstractAbsoluteModelGenerator.java | 226 +++++++++++++++++ .../AbstractBindingModelContainerSupport.java | 119 --------- .../impl/AssemblyModelContainerSupport.java | 234 ----------------- .../impl/AssemblyModelGenerator.java | 158 ++++++++++++ .../ChoiceGroupModelContainerSupport.java | 235 ------------------ .../impl/ChoiceGroupModelGenerator.java | 216 ++++++++++++++++ .../impl/ChoiceModelContainerSupport.java | 178 ------------- .../metaschema/impl/ChoiceModelGenerator.java | 122 +++++++++ .../impl/DefinitionAssemblyGlobal.java | 4 +- .../impl/IFeatureBindingContainerModel.java | 72 ------ ...IFeatureBindingContainerModelAssembly.java | 95 ------- .../impl/InstanceModelAssemblyInline.java | 4 +- .../impl/InstanceModelAssemblyReference.java | 2 +- .../metaschema/impl/InstanceModelChoice.java | 6 +- .../impl/InstanceModelChoiceGroup.java | 2 +- .../impl/InstanceModelFieldReference.java | 15 ++ .../InstanceModelGroupedAssemblyInline.java | 5 +- 49 files changed, 1888 insertions(+), 2047 deletions(-) rename core/src/main/java/gov/nist/secauto/metaschema/core/model/{xml/impl/DefaultGroupedModelContainerSupport.java => AbstractContainerModelSupport.java} (67%) create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultAssemblyModelBuilder.java create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceGroupModelBuilder.java create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceModelBuilder.java delete mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModel.java rename core/src/main/java/gov/nist/secauto/metaschema/core/model/{xml => }/impl/DefaultContainerModelAssemblySupport.java (65%) create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelChoiceGroupSupport.java create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelSupport.java delete mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelSupport.java create mode 100644 core/src/main/java/gov/nist/secauto/metaschema/core/qname/EQNameFactory.java rename core/src/test/java/gov/nist/secauto/metaschema/core/metapath/{cst/EQNameUtilsTest.java => StaticContextTest.java} (94%) delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelAssembly.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelChoiceGroup.java rename databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/{AssemblyModelContainerSupport.java => AssemblyModelGenerator.java} (53%) delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelAssembly.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelChoiceGroup.java create mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractAbsoluteModelGenerator.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractBindingModelContainerSupport.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelContainerSupport.java create mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelGenerator.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelContainerSupport.java create mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelGenerator.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelContainerSupport.java create mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelGenerator.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModel.java delete mode 100644 databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModelAssembly.java diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/DataTypeService.java b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/DataTypeService.java index 74fe70432..2f0dd2a18 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/DataTypeService.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/DataTypeService.java @@ -149,6 +149,14 @@ public > TYPE getJavaTypeAdapterByClass(@NonNul return (TYPE) typeByAdapterClass.get(clazz); } + /** + * Lookup a specific {@link IDataTypeAdapter} instance by its item class. + * + * @param clazz + * the adapter class to get the instance for + * @return the instance or {@code null} if the instance is unknown to the type + * system + */ @Nullable public IDataTypeAdapter getJavaTypeAdapterByItemClass(Class clazz) { return typeByItemClass.get(clazz); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java index 67b730cf2..148a9b937 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java @@ -135,10 +135,6 @@ private StaticContext(Builder builder) { this.useWildcardWhenNamespaceNotDefaulted = builder.useWildcardWhenNamespaceNotDefaulted; } - private EQNameFactory getEqNameFactory() { - return EQNameFactory.instance(); - } - /** * Get the static base URI to use in resolving URIs handled by the Metapath * processor. This URI, if provided, will be used when a document base URI is @@ -223,14 +219,14 @@ private String resolveBasicPrefix(@NonNull String prefix) { @NonNull private IEnhancedQName parseDataTypeName(@NonNull String name) { - return getEqNameFactory().parseName( + return EQNameFactory.instance().parseName( name, this::resolveBasicPrefix); } @NonNull private IEnhancedQName parseFunctionName(@NonNull String name) { - return getEqNameFactory().parseName( + return EQNameFactory.instance().parseName( name, this::resolveFunctionPrefix); } @@ -262,11 +258,13 @@ private String resolveFunctionPrefix(@NonNull String prefix) { *
  • Use {@link XMLConstants#NULL_NS_URI}.
  • * * + * @param name + * the name * @return the parsed qualified name */ @NonNull public IEnhancedQName parseFlagName(@NonNull String name) { - return getEqNameFactory().parseName( + return EQNameFactory.instance().parseName( name, this::resolveBasicPrefix); } @@ -287,11 +285,13 @@ public IEnhancedQName parseFlagName(@NonNull String name) { * {@link Builder#defaultModelNamespace(String)}). * * + * @param name + * the name * @return the parsed qualified name */ @NonNull public IEnhancedQName parseModelName(@NonNull String name) { - return getEqNameFactory().parseName( + return EQNameFactory.instance().parseName( name, this::resolveModelReferencePrefix); } @@ -324,11 +324,13 @@ private String resolveModelReferencePrefix(@NonNull String prefix) { *
  • Use {@link XMLConstants#NULL_NS_URI}.
  • * * + * @param name + * the name * @return the parsed qualified name */ @NonNull public IEnhancedQName parseVariableName(@NonNull String name) { - return getEqNameFactory().parseName( + return EQNameFactory.instance().parseName( name, this::resolveBasicPrefix); } @@ -350,9 +352,9 @@ public Builder buildFrom() { } /** - * Indicates if a name match should use a wildcard for the namespace is the - * namespace does not have a value and the {@link #getDefaultModelNamespace()} - * is {@code null}. + * Indicates if a name match should use a wildcard for the namespace if the + * namespace does not have a value and the default model namespace is + * {@code null}. * * @return {@code true} if a wildcard match on the name space should be used or * {@code false} otherwise @@ -422,7 +424,6 @@ public Builder baseUri(@NonNull URI uri) { * the namespace URI * @return this builder * @see StaticContext#lookupNamespaceForPrefix(String) - * @see StaticContext#lookupNamespaceURIForPrefix(String) * @see StaticContext#getWellKnownNamespacesMap() */ @NonNull @@ -443,7 +444,6 @@ public Builder namespace(@NonNull String prefix, @NonNull URI uri) { * @throws IllegalArgumentException * if the provided URI is invalid * @see StaticContext#lookupNamespaceForPrefix(String) - * @see StaticContext#lookupNamespaceURIForPrefix(String) * @see StaticContext#getWellKnownNamespacesMap() */ @NonNull @@ -458,7 +458,6 @@ public Builder namespace(@NonNull String prefix, @NonNull String uri) { * @param uri * the namespace URI * @return this builder - * @see StaticContext#getDefaultModelNamespace() */ @NonNull public Builder defaultModelNamespace(@NonNull URI uri) { @@ -475,7 +474,6 @@ public Builder defaultModelNamespace(@NonNull URI uri) { * @return this builder * @throws IllegalArgumentException * if the provided URI is invalid - * @see StaticContext#getDefaultModelNamespace() */ @NonNull public Builder defaultModelNamespace(@NonNull String uri) { @@ -489,7 +487,6 @@ public Builder defaultModelNamespace(@NonNull String uri) { * @param uri * the namespace URI * @return this builder - * @see StaticContext#getDefaultFunctionNamespace() */ @NonNull public Builder defaultFunctionNamespace(@NonNull URI uri) { @@ -506,7 +503,6 @@ public Builder defaultFunctionNamespace(@NonNull URI uri) { * @return this builder * @throws IllegalArgumentException * if the provided URI is invalid - * @see StaticContext#getDefaultFunctionNamespace() */ @NonNull public Builder defaultFunctionNamespace(@NonNull String uri) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultGroupedModelContainerSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractContainerModelSupport.java similarity index 67% rename from core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultGroupedModelContainerSupport.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractContainerModelSupport.java index 83b3a9f17..9b8ad411b 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultGroupedModelContainerSupport.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractContainerModelSupport.java @@ -3,32 +3,25 @@ * SPDX-License-Identifier: CC0-1.0 */ -package gov.nist.secauto.metaschema.core.model.xml.impl; +package gov.nist.secauto.metaschema.core.model; -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceGrouped; -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceGrouped; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceGrouped; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; +import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** - * Supports grouped model instance operations on assembly model instances. + * Supports model instance operations on assembly model instances. *

    * This implementation uses underlying {@link LinkedHashMap} instances to * preserve ordering. - *

    - * Since a choice group only contains named model instances (i.e., fields, - * assemblies), model instance operations are supported by the map returned by - * {@link #getNamedModelInstanceMap()}. * + * @param + * the model instance Java type * @param * the named model instance Java type * @param @@ -36,11 +29,12 @@ * @param * the assembly instance Java type */ -public class DefaultGroupedModelContainerSupport< - NMI extends INamedModelInstanceGrouped, - FI extends IFieldInstanceGrouped, - AI extends IAssemblyInstanceGrouped> - implements IContainerModelSupport { +public abstract class AbstractContainerModelSupport< + MI extends IModelInstance, + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance> + implements IContainerModelSupport { @NonNull private final Map namedModelInstances; @@ -53,7 +47,7 @@ public class DefaultGroupedModelContainerSupport< * Construct an empty, mutable container. */ @SuppressWarnings("PMD.UseConcurrentHashMap") - public DefaultGroupedModelContainerSupport() { + public AbstractContainerModelSupport() { this( new LinkedHashMap<>(), new LinkedHashMap<>(), @@ -61,21 +55,50 @@ public DefaultGroupedModelContainerSupport() { } /** - * Construct an immutable container from a collection of named model instances. + * Construct an new container using the provided collections. + * + * @param namedModelInstances + * a collection of named model instances + * @param fieldInstances + * a collection of field instances + * @param assemblyInstances + * a collection of assembly instances + */ + protected AbstractContainerModelSupport( + @NonNull Map namedModelInstances, + @NonNull Map fieldInstances, + @NonNull Map assemblyInstances) { + this.namedModelInstances = namedModelInstances; + this.fieldInstances = fieldInstances; + this.assemblyInstances = assemblyInstances; + } + + /** + * Construct an immutable container from a collection of model instances. * * @param instances - * the collection of named model instances to add to the new container. + * the collection of model instances to add to the new container. + * @param namedModelClass + * the Java type for named model instances * @param fieldClass * the Java type for field instances * @param assemblyClass * the Java type for assembly instances */ - @SuppressWarnings({ "PMD.UseConcurrentHashMap" }) - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - private DefaultGroupedModelContainerSupport( - @NonNull Collection instances, + @SuppressWarnings("PMD.UseConcurrentHashMap") + protected AbstractContainerModelSupport( + @NonNull Stream instances, + @NonNull Class namedModelClass, @NonNull Class fieldClass, @NonNull Class assemblyClass) { + assert namedModelClass.isAssignableFrom(fieldClass) : String.format( + "The field class '%s' is not assignment compatible to class '%s'.", + fieldClass.getName(), + namedModelClass.getName()); + assert namedModelClass.isAssignableFrom(assemblyClass) : String.format( + "The assembly class '%s' is not assignment compatible to class '%s'.", + assemblyClass.getName(), + namedModelClass.getName()); assert !fieldClass.isAssignableFrom(assemblyClass) : String.format( "The field class '%s' must not be assignment compatible to the assembly class '%s'.", fieldClass.getName(), @@ -84,7 +107,8 @@ private DefaultGroupedModelContainerSupport( Map namedModelInstances = new LinkedHashMap<>(); Map fieldInstances = new LinkedHashMap<>(); Map assemblyInstances = new LinkedHashMap<>(); - for (NMI instance : instances) { + + instances.forEachOrdered(instance -> { IEnhancedQName key = instance.getQName(); namedModelInstances.put(key, instance); @@ -93,7 +117,7 @@ private DefaultGroupedModelContainerSupport( } else if (assemblyClass.isInstance(instance)) { assemblyInstances.put(key, assemblyClass.cast(instance)); } - } + }); this.namedModelInstances = namedModelInstances.isEmpty() ? CollectionUtil.emptyMap() @@ -106,31 +130,6 @@ private DefaultGroupedModelContainerSupport( : CollectionUtil.unmodifiableMap(assemblyInstances); } - /** - * Construct an new container using the provided collections. - * - * @param namedModelInstances - * a collection of named model instances - * @param fieldInstances - * a collection of field instances - * @param assemblyInstances - * a collection of assembly instances - */ - protected DefaultGroupedModelContainerSupport( - @NonNull Map namedModelInstances, - @NonNull Map fieldInstances, - @NonNull Map assemblyInstances) { - this.namedModelInstances = namedModelInstances; - this.fieldInstances = fieldInstances; - this.assemblyInstances = assemblyInstances; - } - - @SuppressWarnings("null") - @Override - public Collection getModelInstances() { - return namedModelInstances.values(); - } - @Override public Map getNamedModelInstanceMap() { return namedModelInstances; @@ -145,4 +144,11 @@ public Map getFieldInstanceMap() { public Map getAssemblyInstanceMap() { return assemblyInstances; } + + @SuppressWarnings({ "PMD.EmptyFinalizer", "checkstyle:NoFinalizer" }) + @Override + protected final void finalize() { + // Address SEI CERT Rule OBJ-11: + // https://wiki.sei.cmu.edu/confluence/display/java/OBJ11-J.+Be+wary+of+letting+constructors+throw+exceptions + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultAssemblyModelBuilder.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultAssemblyModelBuilder.java new file mode 100644 index 000000000..c0f07188b --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultAssemblyModelBuilder.java @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.model; + +import gov.nist.secauto.metaschema.core.model.impl.DefaultContainerModelAssemblySupport; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * An assembly model builder. + * + * @param + * the model instance Java type + * @param + * the named model instance Java type + * @param + * the field instance Java type + * @param + * the assembly instance Java type + * @param + * the choice instance Java type + * @param + * the choice group instance Java type + * @see DefaultChoiceGroupModelBuilder for a choice group model builder + * @see DefaultChoiceModelBuilder for a choice model builder + */ +@SuppressWarnings("PMD.UseConcurrentHashMap") +public class DefaultAssemblyModelBuilder< + MI extends IModelInstance, + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance, + CI extends IChoiceInstance, + CGI extends IChoiceGroupInstance> + extends DefaultChoiceModelBuilder { + // collections to store model instances + @NonNull + private final List choiceInstances = new LinkedList<>(); + @NonNull + private final Map choiceGroupInstances = new LinkedHashMap<>(); + + /** + * Append the instance. + * + * @param instance + * the instance to append + */ + @SuppressWarnings("unchecked") + public void append(@NonNull CI instance) { + getModelInstances().add((MI) instance); + choiceInstances.add(instance); + } + + /** + * Append the instance. + * + * @param instance + * the instance to append + */ + @SuppressWarnings("unchecked") + public void append(@NonNull CGI instance) { + getModelInstances().add((MI) instance); + choiceGroupInstances.put(instance.getGroupAsName(), instance); + } + + /** + * Get the appended choice instances. + * + * @return the instances or an empty list if no instances were appended + */ + @NonNull + protected List getChoiceInstances() { + return choiceInstances; + } + + /** + * Get the appended choice group instances. + * + * @return the instances or an empty map if no instances were appended + */ + @NonNull + protected Map getChoiceGroupInstances() { + return choiceGroupInstances; + } + + /** + * Build an immutable assembly model container based on the appended instances. + * + * @return the container + */ + @NonNull + public IContainerModelAssemblySupport buildAssembly() { + return getModelInstances().isEmpty() + ? IContainerModelAssemblySupport.empty() + : new DefaultContainerModelAssemblySupport<>( + CollectionUtil.unmodifiableList(getModelInstances()), + CollectionUtil.unmodifiableMap(getNamedModelInstances()), + CollectionUtil.unmodifiableMap(getFieldInstances()), + CollectionUtil.unmodifiableMap(getAssemblyInstances()), + CollectionUtil.unmodifiableList(getChoiceInstances()), + CollectionUtil.unmodifiableMap(getChoiceGroupInstances())); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceGroupModelBuilder.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceGroupModelBuilder.java new file mode 100644 index 000000000..bb9e06fa0 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceGroupModelBuilder.java @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.model; + +import gov.nist.secauto.metaschema.core.model.impl.DefaultContainerModelChoiceGroupSupport; +import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; + +import java.util.LinkedHashMap; +import java.util.Map; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * A choice group model builder. + *

    + * Is extended to support other model builders (i.e. choice and assembly model + * builders). + * + * @param + * the named model instance Java type + * @param + * the field instance Java type + * @param + * the assembly instance Java type + * @see DefaultChoiceModelBuilder for a choice model builder + * @see DefaultAssemblyModelBuilder for an assembly model builder + */ +@SuppressWarnings("PMD.UseConcurrentHashMap") +public class DefaultChoiceGroupModelBuilder< + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance> { + + // collections to store model instances + @NonNull + private final Map namedModelInstances = new LinkedHashMap<>(); + @NonNull + private final Map fieldInstances = new LinkedHashMap<>(); + @NonNull + private final Map assemblyInstances = new LinkedHashMap<>(); + + /** + * Append the instance. + * + * @param instance + * the instance to append + */ + @SuppressWarnings("unchecked") + public void append(@NonNull FI instance) { + IEnhancedQName key = instance.getQName(); + namedModelInstances.put(key, (NMI) instance); + fieldInstances.put(key, instance); + } + + /** + * Append the instance. + * + * @param instance + * the instance to append + */ + @SuppressWarnings("unchecked") + public void append(@NonNull AI instance) { + IEnhancedQName key = instance.getQName(); + namedModelInstances.put(key, (NMI) instance); + assemblyInstances.put(key, instance); + } + + /** + * Get the appended named model instances. + * + * @return the instances or an empty map if no instances were appended + */ + @NonNull + protected Map getNamedModelInstances() { + return namedModelInstances; + } + + /** + * Get the appended field instances. + * + * @return the instances or an empty map if no instances were appended + */ + @NonNull + protected Map getFieldInstances() { + return fieldInstances; + } + + /** + * Get the appended assembly instances. + * + * @return the instances or an empty map if no instances were appended + */ + @NonNull + protected Map getAssemblyInstances() { + return assemblyInstances; + } + + /** + * Build an immutable choice group model container based on the appended + * instances. + * + * @return the container + */ + @NonNull + public IContainerModelSupport buildChoiceGroup() { + return getNamedModelInstances().isEmpty() + ? IContainerModelSupport.empty() + : new DefaultContainerModelChoiceGroupSupport<>( + CollectionUtil.unmodifiableMap(getNamedModelInstances()), + CollectionUtil.unmodifiableMap(getFieldInstances()), + CollectionUtil.unmodifiableMap(getAssemblyInstances())); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceModelBuilder.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceModelBuilder.java new file mode 100644 index 000000000..6495fedb8 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/DefaultChoiceModelBuilder.java @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.model; + +import gov.nist.secauto.metaschema.core.model.impl.DefaultContainerModelSupport; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; + +import java.util.LinkedList; +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * A choice model builder. + *

    + * Is extended to support other model builders (i.e. assembly model builders). + * + * @param + * the model instance Java type + * @param + * the named model instance Java type + * @param + * the field instance Java type + * @param + * the assembly instance Java type + * @see DefaultChoiceGroupModelBuilder for a choice group model builder + * @see DefaultAssemblyModelBuilder for an assembly model builder + */ +public class DefaultChoiceModelBuilder< + MI extends IModelInstance, + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance> + extends DefaultChoiceGroupModelBuilder { + // collections to store model instances + @NonNull + private final List modelInstances = new LinkedList<>(); + + @SuppressWarnings("unchecked") + @Override + public void append(FI instance) { + modelInstances.add((MI) instance); + super.append(instance); + } + + @SuppressWarnings("unchecked") + @Override + public void append(AI instance) { + modelInstances.add((MI) instance); + super.append(instance); + } + + /** + * Get the appended model instances. + * + * @return the instances or an empty list if no instances were appended + */ + @NonNull + public List getModelInstances() { + return modelInstances; + } + + /** + * Build an immutable choice model container based on the appended instances. + * + * @return the container + */ + @NonNull + public IContainerModelSupport buildChoice() { + return getModelInstances().isEmpty() + ? IContainerModelSupport.empty() + : new DefaultContainerModelSupport<>( + CollectionUtil.unmodifiableList(getModelInstances()), + CollectionUtil.unmodifiableMap(getNamedModelInstances()), + CollectionUtil.unmodifiableMap(getFieldInstances()), + CollectionUtil.unmodifiableMap(getAssemblyInstances())); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelAssemblySupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelAssemblySupport.java index 9f3e4bad8..bb3df78f1 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelAssemblySupport.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelAssemblySupport.java @@ -5,7 +5,7 @@ package gov.nist.secauto.metaschema.core.model; -import gov.nist.secauto.metaschema.core.model.xml.impl.DefaultContainerModelAssemblySupport; +import gov.nist.secauto.metaschema.core.model.impl.DefaultContainerModelAssemblySupport; import java.util.List; import java.util.Map; @@ -54,6 +54,7 @@ public interface IContainerModelAssemblySupport< * @return the empty container */ @SuppressWarnings("unchecked") + @NonNull static < MI extends IModelInstance, NMI extends INamedModelInstance, diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelSupport.java index 69b70c978..0690a81d4 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelSupport.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IContainerModelSupport.java @@ -5,7 +5,7 @@ package gov.nist.secauto.metaschema.core.model; -import gov.nist.secauto.metaschema.core.model.xml.impl.DefaultContainerModelSupport; +import gov.nist.secauto.metaschema.core.model.impl.DefaultContainerModelSupport; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import java.util.Collection; @@ -44,13 +44,13 @@ public interface IContainerModelSupport< * the assembly instance Java type * @return the empty container */ - @SuppressWarnings("unchecked") + @NonNull static < MI extends IModelInstance, NMI extends INamedModelInstance, FI extends IFieldInstance, AI extends IAssemblyInstance> IContainerModelSupport empty() { - return DefaultContainerModelSupport.EMPTY; + return DefaultContainerModelSupport.empty(); } /** diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModel.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModel.java deleted file mode 100644 index 01234bdd7..000000000 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModel.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.core.model; - -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; - -import java.util.Collection; - -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * Common interface for model container support classes. - * - * @param - * the model instance Java type - * @param - * the named model instance Java type - * @param - * the field instance Java type - * @param - * the assembly instance Java type - */ -public interface IFeatureContainerModel< - MI extends IModelInstance, - NMI extends INamedModelInstance, - FI extends IFieldInstance, - AI extends IAssemblyInstance> - extends IContainerModel { - /** - * Get the model container implementation instance. - * - * @return the model container instance - */ - @NonNull - IContainerModelSupport getModelContainer(); - - @Override - default Collection getModelInstances() { - return getModelContainer().getModelInstances(); - } - - @Override - default NMI getNamedModelInstanceByName(IEnhancedQName name) { - return getModelContainer().getNamedModelInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getNamedModelInstances() { - return getModelContainer().getNamedModelInstanceMap().values(); - } - - @Override - default FI getFieldInstanceByName(IEnhancedQName name) { - return getModelContainer().getFieldInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getFieldInstances() { - return getModelContainer().getFieldInstanceMap().values(); - } - - @Override - default AI getAssemblyInstanceByName(IEnhancedQName name) { - return getModelContainer().getAssemblyInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getAssemblyInstances() { - return getModelContainer().getAssemblyInstanceMap().values(); - } -} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelAbsolute.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelAbsolute.java index cff983d38..cf741dbaf 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelAbsolute.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelAbsolute.java @@ -9,6 +9,8 @@ import java.util.Collection; +import edu.umd.cs.findbugs.annotations.NonNull; + /** * Common interface for model container support classes. * @@ -26,9 +28,17 @@ public interface IFeatureContainerModelAbsolute< NMI extends INamedModelInstanceAbsolute, FI extends IFieldInstanceAbsolute, AI extends IAssemblyInstanceAbsolute> - extends IContainerModelAbsolute, IFeatureContainerModel { + extends IContainerModelAbsolute, IContainerModel { + /** + * Get the model container implementation instance. + * + * @return the model container instance + */ + @NonNull + IContainerModelSupport getModelContainer(); + @Override - default Collection getModelInstances() { + default Collection getModelInstances() { return getModelContainer().getModelInstances(); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelGrouped.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelGrouped.java index 2827f750c..339822377 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelGrouped.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IFeatureContainerModelGrouped.java @@ -15,13 +15,12 @@ public interface IFeatureContainerModelGrouped< NMI extends INamedModelInstanceGrouped, FI extends IFieldInstanceGrouped, AI extends IAssemblyInstanceGrouped> - extends IContainerModelGrouped, IFeatureContainerModel { + extends IContainerModelGrouped, IContainerModel { /** - * Lazy initialize the model instances associated with this choice group. + * Get the model container implementation instance. * - * @return the model container + * @return the model container instance */ - @Override @NonNull IContainerModelSupport getModelContainer(); @@ -32,7 +31,7 @@ default boolean hasChildren() { @Override default Collection getModelInstances() { - return getModelContainer().getModelInstances(); + return getNamedModelInstances(); } @Override diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/INamed.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/INamed.java index e77f0d16f..0bc59b78f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/INamed.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/INamed.java @@ -74,7 +74,6 @@ default String getEffectiveName() { * * @return the XML qualified name, or {@code null} if there isn't one */ - // FIXME: rename to getQName @NonNull IEnhancedQName getQName(); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelAssemblySupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelAssemblySupport.java similarity index 65% rename from core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelAssemblySupport.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelAssemblySupport.java index 6d1b4d51e..4f90d10a3 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelAssemblySupport.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelAssemblySupport.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: CC0-1.0 */ -package gov.nist.secauto.metaschema.core.model.xml.impl; +package gov.nist.secauto.metaschema.core.model.impl; import gov.nist.secauto.metaschema.core.model.IAssemblyInstance; import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; @@ -14,9 +14,7 @@ import gov.nist.secauto.metaschema.core.model.INamedModelInstance; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -53,7 +51,11 @@ public class DefaultContainerModelAssemblySupport< extends DefaultContainerModelSupport implements IContainerModelAssemblySupport { + /** + * An empty, immutable container. + */ @SuppressWarnings("rawtypes") + @NonNull public static final DefaultContainerModelAssemblySupport EMPTY = new DefaultContainerModelAssemblySupport<>( CollectionUtil.emptyList(), CollectionUtil.emptyMap(), @@ -81,52 +83,6 @@ public DefaultContainerModelAssemblySupport() { new LinkedHashMap<>()); } - /** - * Construct an immutable container from a collection of model instances. - * - * @param instances - * the collection of model instances to add to the new container. - * @param namedModelClass - * the Java type for named model instances - * @param fieldClass - * the Java type for field instances - * @param assemblyClass - * the Java type for assembly instances - * @param choiceClass - * the Java type for choice instances - * @param choiceGroupClass - * the Java type for choice group instances - */ - @SuppressWarnings({ "PMD.UseConcurrentHashMap" }) - public DefaultContainerModelAssemblySupport( - @NonNull Collection instances, - @NonNull Class namedModelClass, - @NonNull Class fieldClass, - @NonNull Class assemblyClass, - @NonNull Class choiceClass, - @NonNull Class choiceGroupClass) { - super(instances, namedModelClass, fieldClass, assemblyClass); - List choiceInstances = new LinkedList<>(); - Map choiceGroupInstances = new LinkedHashMap<>(); - for (MI instance : instances) { - if (choiceClass.isInstance(instance)) { - CI choice = choiceClass.cast(instance); - choiceInstances.add(choice); - } else if (choiceGroupClass.isInstance(instance)) { - CGI choiceGroup = choiceGroupClass.cast(instance); - String key = ObjectUtils.requireNonNull(choiceGroup.getGroupAsName()); - choiceGroupInstances.put(key, choiceGroup); - } - } - - this.choiceInstances = choiceInstances.isEmpty() - ? CollectionUtil.emptyList() - : CollectionUtil.unmodifiableList(choiceInstances); - this.choiceGroupInstances = choiceGroupInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(choiceGroupInstances); - } - /** * Construct an new container using the provided collections. * @@ -143,7 +99,7 @@ public DefaultContainerModelAssemblySupport( * @param choiceGroupInstances * a collection of choice group instances */ - protected DefaultContainerModelAssemblySupport( + public DefaultContainerModelAssemblySupport( @NonNull List instances, @NonNull Map namedModelInstances, @NonNull Map fieldInstances, diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelChoiceGroupSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelChoiceGroupSupport.java new file mode 100644 index 000000000..a26427566 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelChoiceGroupSupport.java @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.model.impl; + +import gov.nist.secauto.metaschema.core.model.AbstractContainerModelSupport; +import gov.nist.secauto.metaschema.core.model.IAssemblyInstance; +import gov.nist.secauto.metaschema.core.model.IFieldInstance; +import gov.nist.secauto.metaschema.core.model.INamedModelInstance; +import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Supports choice group model instance operations on assembly model instances. + *

    + * This implementation uses underlying {@link LinkedHashMap} instances to + * preserve ordering. + * + * @param + * the named model instance Java type + * @param + * the field instance Java type + * @param + * the assembly instance Java type + */ +public class DefaultContainerModelChoiceGroupSupport< + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance> + extends AbstractContainerModelSupport { + + /** + * Construct an new container using the provided collections. + * + * @param namedModelInstances + * a collection of named model instances + * @param fieldInstances + * a collection of field instances + * @param assemblyInstances + * a collection of assembly instances + */ + public DefaultContainerModelChoiceGroupSupport( + @NonNull Map namedModelInstances, + @NonNull Map fieldInstances, + @NonNull Map assemblyInstances) { + super(namedModelInstances, fieldInstances, assemblyInstances); + } + + @Override + public Collection getModelInstances() { + return ObjectUtils.notNull(getNamedModelInstanceMap().values()); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelSupport.java new file mode 100644 index 000000000..58e08242b --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/impl/DefaultContainerModelSupport.java @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.model.impl; + +import gov.nist.secauto.metaschema.core.model.AbstractContainerModelSupport; +import gov.nist.secauto.metaschema.core.model.IAssemblyInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; +import gov.nist.secauto.metaschema.core.model.IFieldInstance; +import gov.nist.secauto.metaschema.core.model.IModelInstance; +import gov.nist.secauto.metaschema.core.model.INamedModelInstance; +import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Provides model container support. + *

    + * This class supports generic model instance operations on model instances. + *

    + * This implementation uses underlying {@link LinkedHashMap} instances to + * preserve ordering. + * + * @param + * the model instance Java type + * @param + * the named model instance Java type + * @param + * the field instance Java type + * @param + * the assembly instance Java type + */ +public class DefaultContainerModelSupport< + MI extends IModelInstance, + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance> + extends AbstractContainerModelSupport { + + @NonNull + private final List modelInstances; + + @SuppressWarnings("rawtypes") + @NonNull + private static final DefaultContainerModelSupport EMPTY = new DefaultContainerModelSupport<>( + CollectionUtil.emptyList(), + CollectionUtil.emptyMap(), + CollectionUtil.emptyMap(), + CollectionUtil.emptyMap()); + + /** + * Get an empty, immutable container. + * + * @param + * the model instance Java type + * @param + * the named model instance Java type + * @param + * the field instance Java type + * @param + * the assembly instance Java type + * @return the empty container + */ + @SuppressWarnings("unchecked") + @NonNull + public static < + MI extends IModelInstance, + NMI extends INamedModelInstance, + FI extends IFieldInstance, + AI extends IAssemblyInstance> IContainerModelSupport empty() { + return EMPTY; + } + + /** + * Construct an new container using the provided collections. + * + * @param modelInstances + * a collection of model instances + * @param namedModelInstances + * a collection of named model instances + * @param fieldInstances + * a collection of field instances + * @param assemblyInstances + * a collection of assembly instances + */ + @SuppressFBWarnings(value = "SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR", justification = "false positive") + public DefaultContainerModelSupport( + @NonNull List modelInstances, + @NonNull Map namedModelInstances, + @NonNull Map fieldInstances, + @NonNull Map assemblyInstances) { + super(namedModelInstances, fieldInstances, assemblyInstances); + this.modelInstances = modelInstances; + } + + @Override + public List getModelInstances() { + return modelInstances; + } + +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelSupport.java deleted file mode 100644 index 40b52025f..000000000 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/DefaultContainerModelSupport.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.core.model.xml.impl; - -import gov.nist.secauto.metaschema.core.model.IAssemblyInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFieldInstance; -import gov.nist.secauto.metaschema.core.model.IModelInstance; -import gov.nist.secauto.metaschema.core.model.INamedModelInstance; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -/** - * Provides model container support. - *

    - * This class supports generic model instance operations on model instances. - *

    - * This implementation uses underlying {@link LinkedHashMap} instances to - * preserve ordering. - * - * @param - * the model instance Java type - * @param - * the named model instance Java type - * @param - * the field instance Java type - * @param - * the assembly instance Java type - */ -public class DefaultContainerModelSupport< - MI extends IModelInstance, - NMI extends INamedModelInstance, - FI extends IFieldInstance, - AI extends IAssemblyInstance> - implements IContainerModelSupport { - - @SuppressWarnings("rawtypes") - public static final DefaultContainerModelSupport EMPTY = new DefaultContainerModelSupport<>( - CollectionUtil.emptyList(), - CollectionUtil.emptyMap(), - CollectionUtil.emptyMap(), - CollectionUtil.emptyMap()); - - @NonNull - private final List modelInstances; - @NonNull - private final Map namedModelInstances; - @NonNull - private final Map fieldInstances; - @NonNull - private final Map assemblyInstances; - - /** - * Construct an empty, mutable container. - */ - @SuppressWarnings("PMD.UseConcurrentHashMap") - public DefaultContainerModelSupport() { - this( - new LinkedList<>(), - new LinkedHashMap<>(), - new LinkedHashMap<>(), - new LinkedHashMap<>()); - } - - /** - * Construct an immutable container from a collection of model instances. - * - * @param instances - * the collection of model instances to add to the new container. - * @param namedModelClass - * the Java type for named model instances - * @param fieldClass - * the Java type for field instances - * @param assemblyClass - * the Java type for assembly instances - */ - @SuppressWarnings({ "PMD.UseConcurrentHashMap" }) - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - protected DefaultContainerModelSupport( - @NonNull Collection instances, - @NonNull Class namedModelClass, - @NonNull Class fieldClass, - @NonNull Class assemblyClass) { - assert namedModelClass.isAssignableFrom(fieldClass) : String.format( - "The field class '%s' is not assignment compatible to class '%s'.", - fieldClass.getName(), - namedModelClass.getName()); - assert namedModelClass.isAssignableFrom(assemblyClass) : String.format( - "The assembly class '%s' is not assignment compatible to class '%s'.", - assemblyClass.getName(), - namedModelClass.getName()); - assert !fieldClass.isAssignableFrom(assemblyClass) : String.format( - "The field class '%s' must not be assignment compatible to the assembly class '%s'.", - fieldClass.getName(), - assemblyClass.getName()); - - this.modelInstances = ObjectUtils.notNull(List.copyOf(instances)); - - Map namedModelInstances = new LinkedHashMap<>(); - Map fieldInstances = new LinkedHashMap<>(); - Map assemblyInstances = new LinkedHashMap<>(); - for (MI instance : instances) { - if (namedModelClass.isInstance(instance)) { - NMI named = namedModelClass.cast(instance); - IEnhancedQName key = named.getQName(); - namedModelInstances.put(key, named); - - if (fieldClass.isInstance(instance)) { - fieldInstances.put(key, fieldClass.cast(named)); - } else if (assemblyClass.isInstance(instance)) { - assemblyInstances.put(key, assemblyClass.cast(named)); - } - } - } - - this.namedModelInstances = namedModelInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(namedModelInstances); - this.fieldInstances = fieldInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(fieldInstances); - this.assemblyInstances = assemblyInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(assemblyInstances); - } - - /** - * Construct an new container using the provided collections. - * - * @param modelInstances - * a collection of model instances - * @param namedModelInstances - * a collection of named model instances - * @param fieldInstances - * a collection of field instances - * @param assemblyInstances - * a collection of assembly instances - */ - protected DefaultContainerModelSupport( - @NonNull List modelInstances, - @NonNull Map namedModelInstances, - @NonNull Map fieldInstances, - @NonNull Map assemblyInstances) { - this.modelInstances = modelInstances; - this.namedModelInstances = namedModelInstances; - this.fieldInstances = fieldInstances; - this.assemblyInstances = assemblyInstances; - } - - @Override - public List getModelInstances() { - return modelInstances; - } - - @Override - public Map getNamedModelInstanceMap() { - return namedModelInstances; - } - - @Override - public Map getFieldInstanceMap() { - return fieldInstances; - } - - @Override - public Map getAssemblyInstanceMap() { - return assemblyInstances; - } -} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java index 27bc51d6a..e7f902300 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/ModelFactory.java @@ -495,7 +495,6 @@ public static ILet newLet( @NonNull ConstraintLetType xmlObject, @NonNull ISource source) { - // FIXME: figure out how to resolve the namespace prefix on var return ILet.of( source.getStaticContext().parseVariableName(ObjectUtils.requireNonNull(xmlObject.getVar())), ObjectUtils.notNull(xmlObject.getExpression()), diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlAssemblyModelContainerSupport.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlAssemblyModelContainerSupport.java index dd9a4862e..bc4474f32 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlAssemblyModelContainerSupport.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlAssemblyModelContainerSupport.java @@ -5,6 +5,7 @@ package gov.nist.secauto.metaschema.core.model.xml.impl; +import gov.nist.secauto.metaschema.core.model.DefaultAssemblyModelBuilder; import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; @@ -21,7 +22,6 @@ import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.GroupedChoiceType; import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.InlineAssemblyDefinitionType; import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.InlineFieldDefinitionType; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import org.apache.commons.lang3.tuple.Pair; @@ -37,17 +37,10 @@ * Used to construct the model of an assmebly defintion based on XMLBeans-based * data. */ -public class XmlAssemblyModelContainerSupport - extends DefaultContainerModelAssemblySupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute, - IChoiceInstance, - IChoiceGroupInstance> { +public final class XmlAssemblyModelContainerSupport { @SuppressWarnings("PMD.UseConcurrentHashMap") @NonNull - private static final XmlObjectParser> XML_MODEL_PARSER + private static final XmlObjectParser> XML_MODEL_PARSER = new XmlObjectParser<>(ObjectUtils.notNull( Map.ofEntries( Map.entry(XmlModuleConstants.ASSEMBLY_QNAME, XmlAssemblyModelContainerSupport::handleAssemmbly), @@ -59,9 +52,9 @@ public class XmlAssemblyModelContainerSupport Map.entry(XmlModuleConstants.CHOICE_GROUP_QNAME, XmlAssemblyModelContainerSupport::handleChoiceGroup)))) { @Override - protected Handler> + protected Handler> identifyHandler(XmlCursor cursor, XmlObject obj) { - Handler> retval; + Handler> retval; if (obj instanceof FieldReferenceType) { retval = XmlAssemblyModelContainerSupport::handleField; } else if (obj instanceof InlineFieldDefinitionType) { @@ -103,14 +96,26 @@ IChoiceGroupInstance> of( @NonNull IAssemblyDefinition parent) { return xmlObject == null ? IContainerModelAssemblySupport.empty() - : XML_MODEL_PARSER - .parse(ObjectUtils.notNull(xmlObject), Pair.of(parent, new XmlAssemblyModelContainerSupport())) - .getRight(); + : newContainer(xmlObject, parent); + } + + private static IContainerModelAssemblySupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute, + IChoiceInstance, + IChoiceGroupInstance> newContainer( + @NonNull AssemblyModelType xmlObject, + @NonNull IAssemblyDefinition parent) { + ModelBuilder builder = new ModelBuilder(); + XML_MODEL_PARSER.parse(xmlObject, Pair.of(parent, builder)); + return builder.buildAssembly(); } private static void handleField( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IFieldInstanceAbsolute instance = new XmlFieldInstance( (FieldReferenceType) obj, ObjectUtils.notNull(state.getLeft())); @@ -119,7 +124,7 @@ private static void handleField( // NOPMD false positive private static void handleDefineField( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IFieldInstanceAbsolute instance = new XmlInlineFieldDefinition( (InlineFieldDefinitionType) obj, ObjectUtils.notNull(state.getLeft())); @@ -128,7 +133,7 @@ private static void handleDefineField( // NOPMD false positive private static void handleAssemmbly( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IAssemblyInstanceAbsolute instance = new XmlAssemblyInstance( (AssemblyReferenceType) obj, ObjectUtils.notNull(state.getLeft())); @@ -137,7 +142,7 @@ private static void handleAssemmbly( // NOPMD false positive private static void handleDefineAssembly( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IAssemblyInstanceAbsolute instance = new XmlInlineAssemblyDefinition( (InlineAssemblyDefinitionType) obj, ObjectUtils.notNull(state.getLeft())); @@ -146,7 +151,7 @@ private static void handleDefineAssembly( // NOPMD false positive private static void handleChoice( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { XmlChoiceInstance instance = new XmlChoiceInstance( (ChoiceType) obj, ObjectUtils.notNull(state.getLeft())); @@ -155,11 +160,10 @@ private static void handleChoice( // NOPMD false positive private static void handleChoiceGroup( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { XmlChoiceGroupInstance instance = new XmlChoiceGroupInstance( (GroupedChoiceType) obj, ObjectUtils.notNull(state.getLeft())); - XmlAssemblyModelContainerSupport container = ObjectUtils.notNull(state.getRight()); String groupAsName = instance.getGroupAsName(); if (groupAsName == null) { @@ -170,44 +174,21 @@ private static void handleChoiceGroup( // NOPMD false positive instance.getContainingDefinition().getName(), locationCtx)); } - container.getChoiceGroupInstanceMap().put(groupAsName, instance); - container.getModelInstances().add(instance); - } - - /** - * Adds the provided instance to the tail of the model. - * - * @param instance - * the instance to append - */ - public void append(@NonNull IFieldInstanceAbsolute instance) { - IEnhancedQName key = instance.getQName(); - getFieldInstanceMap().put(key, instance); - getNamedModelInstanceMap().put(key, instance); - getModelInstances().add(instance); + ObjectUtils.notNull(state.getRight()).append(instance); } - /** - * Adds the provided instance to the tail of the model. - * - * @param instance - * the instance to append - */ - public void append(@NonNull IAssemblyInstanceAbsolute instance) { - IEnhancedQName key = instance.getQName(); - getAssemblyInstanceMap().put(key, instance); - getNamedModelInstanceMap().put(key, instance); - getModelInstances().add(instance); + private static final class ModelBuilder + extends DefaultAssemblyModelBuilder< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute, + IChoiceInstance, + IChoiceGroupInstance> { + // no other methods } - /** - * Adds the provided instance to the tail of the model. - * - * @param instance - * the instance to append - */ - public void append(@NonNull IChoiceInstance instance) { - getChoiceInstances().add(instance); - getModelInstances().add(instance); + private XmlAssemblyModelContainerSupport() { + // disable construction } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceGroupInstance.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceGroupInstance.java index 0c68dcd17..f0018fb5f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceGroupInstance.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceGroupInstance.java @@ -7,9 +7,11 @@ import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; import gov.nist.secauto.metaschema.core.model.AbstractChoiceGroupInstance; +import gov.nist.secauto.metaschema.core.model.DefaultChoiceGroupModelBuilder; import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceGrouped; import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; import gov.nist.secauto.metaschema.core.model.IFieldInstanceGrouped; import gov.nist.secauto.metaschema.core.model.INamedModelInstanceGrouped; import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior; @@ -20,7 +22,6 @@ import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.GroupedFieldReferenceType; import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.GroupedInlineAssemblyDefinitionType; import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.GroupedInlineFieldDefinitionType; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import org.apache.commons.lang3.tuple.Pair; @@ -41,7 +42,104 @@ class XmlChoiceGroupInstance @NonNull private final GroupedChoiceType xmlObject; @NonNull - private final Lazy modelContainer; + private final Lazy> modelContainer; + + @SuppressWarnings("PMD.UseConcurrentHashMap") + @NonNull + private static final XmlObjectParser> XML_MODEL_PARSER + = new XmlObjectParser<>(ObjectUtils.notNull( + Map.ofEntries( + Map.entry(XmlModuleConstants.ASSEMBLY_QNAME, XmlChoiceGroupInstance::handleAssembly), + Map.entry(XmlModuleConstants.DEFINE_ASSEMBLY_QNAME, XmlChoiceGroupInstance::handleDefineAssembly), + Map.entry(XmlModuleConstants.FIELD_QNAME, XmlChoiceGroupInstance::handleField), + Map.entry(XmlModuleConstants.DEFINE_FIELD_QNAME, XmlChoiceGroupInstance::handleDefineField)))) { + + @Override + protected Handler> + identifyHandler(XmlCursor cursor, XmlObject obj) { + Handler> retval; + if (obj instanceof GroupedFieldReferenceType) { + retval = XmlChoiceGroupInstance::handleField; + } else if (obj instanceof GroupedInlineFieldDefinitionType) { + retval = XmlChoiceGroupInstance::handleDefineField; + } else if (obj instanceof GroupedAssemblyReferenceType) { + retval = XmlChoiceGroupInstance::handleAssembly; + } else if (obj instanceof GroupedInlineAssemblyDefinitionType) { + retval = XmlChoiceGroupInstance::handleDefineAssembly; + } else { + retval = super.identifyHandler(cursor, obj); + } + return retval; + } + }; + + /** + * Parse a choice group XMLBeans object. + * + * @param xmlObject + * the XMLBeans object + * @param parent + * the parent Metaschema node, either an assembly definition or choice + */ + private static IContainerModelSupport< + INamedModelInstanceGrouped, + INamedModelInstanceGrouped, + IFieldInstanceGrouped, + IAssemblyInstanceGrouped> newContainer( + @NonNull GroupedChoiceType xmlObject, + @NonNull IChoiceGroupInstance parent) { + ModelBuilder builder = new ModelBuilder(); + XML_MODEL_PARSER.parse(xmlObject, Pair.of(parent, builder)); + return builder.buildChoiceGroup(); + } + + private static final class ModelBuilder + extends DefaultChoiceGroupModelBuilder< + INamedModelInstanceGrouped, + IFieldInstanceGrouped, + IAssemblyInstanceGrouped> { + // no other methods + } + + private static void handleField( // NOPMD false positive + @NonNull XmlObject obj, + Pair state) { + IFieldInstanceGrouped instance = new XmlGroupedFieldInstance( + (GroupedFieldReferenceType) obj, + ObjectUtils.notNull(state.getLeft())); + ObjectUtils.notNull(state.getRight()).append(instance); + } + + private static void handleDefineField( // NOPMD false positive + @NonNull XmlObject obj, + Pair state) { + IFieldInstanceGrouped instance = new XmlGroupedInlineFieldDefinition( + (GroupedInlineFieldDefinitionType) obj, + ObjectUtils.notNull(state.getLeft())); + ObjectUtils.notNull(state.getRight()).append(instance); + } + + private static void handleAssembly( // NOPMD false positive + @NonNull XmlObject obj, + Pair state) { + IAssemblyInstanceGrouped instance = new XmlGroupedAssemblyInstance( + (GroupedAssemblyReferenceType) obj, + ObjectUtils.notNull(state.getLeft())); + ObjectUtils.notNull(state.getRight()).append(instance); + } + + private static void handleDefineAssembly( // NOPMD false positive + @NonNull XmlObject obj, + Pair state) { + IAssemblyInstanceGrouped instance = new XmlGroupedInlineAssemblyDefinition( + (GroupedInlineAssemblyDefinitionType) obj, + ObjectUtils.notNull(state.getLeft())); + ObjectUtils.notNull(state.getRight()).append(instance); + } /** * Constructs a mutually exclusive choice between two possible objects. @@ -56,11 +154,15 @@ public XmlChoiceGroupInstance( @NonNull IAssemblyDefinition parent) { super(parent); this.xmlObject = xmlObject; - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> new XmlModelContainer(xmlObject, this))); + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> newContainer(xmlObject, this))); } @Override - public XmlModelContainer getModelContainer() { + public IContainerModelSupport< + INamedModelInstanceGrouped, + INamedModelInstanceGrouped, + IFieldInstanceGrouped, + IAssemblyInstanceGrouped> getModelContainer() { return ObjectUtils.notNull(modelContainer.get()); } @@ -129,102 +231,4 @@ public MarkupMultiline getRemarks() { // ------------------------------------- // - End XmlBeans driven code - CPD-ON - // ------------------------------------- - - @SuppressWarnings("PMD.UseConcurrentHashMap") - @NonNull - private static final XmlObjectParser> XML_MODEL_PARSER - = new XmlObjectParser<>(ObjectUtils.notNull( - Map.ofEntries( - Map.entry(XmlModuleConstants.ASSEMBLY_QNAME, XmlChoiceGroupInstance::handleAssembly), - Map.entry(XmlModuleConstants.DEFINE_ASSEMBLY_QNAME, XmlChoiceGroupInstance::handleDefineAssembly), - Map.entry(XmlModuleConstants.FIELD_QNAME, XmlChoiceGroupInstance::handleField), - Map.entry(XmlModuleConstants.DEFINE_FIELD_QNAME, XmlChoiceGroupInstance::handleDefineField)))) { - - @Override - protected Handler> - identifyHandler(XmlCursor cursor, XmlObject obj) { - Handler> retval; - if (obj instanceof GroupedFieldReferenceType) { - retval = XmlChoiceGroupInstance::handleField; - } else if (obj instanceof GroupedInlineFieldDefinitionType) { - retval = XmlChoiceGroupInstance::handleDefineField; - } else if (obj instanceof GroupedAssemblyReferenceType) { - retval = XmlChoiceGroupInstance::handleAssembly; - } else if (obj instanceof GroupedInlineAssemblyDefinitionType) { - retval = XmlChoiceGroupInstance::handleDefineAssembly; - } else { - retval = super.identifyHandler(cursor, obj); - } - return retval; - } - }; - - private static void handleField( // NOPMD false positive - @NonNull XmlObject obj, - Pair state) { - IFieldInstanceGrouped instance = new XmlGroupedFieldInstance( - (GroupedFieldReferenceType) obj, - ObjectUtils.notNull(state.getLeft())); - ObjectUtils.notNull(state.getRight()).append(instance); - } - - private static void handleDefineField( // NOPMD false positive - @NonNull XmlObject obj, - Pair state) { - IFieldInstanceGrouped instance = new XmlGroupedInlineFieldDefinition( - (GroupedInlineFieldDefinitionType) obj, - ObjectUtils.notNull(state.getLeft())); - ObjectUtils.notNull(state.getRight()).append(instance); - } - - private static void handleAssembly( // NOPMD false positive - @NonNull XmlObject obj, - Pair state) { - IAssemblyInstanceGrouped instance = new XmlGroupedAssemblyInstance( - (GroupedAssemblyReferenceType) obj, - ObjectUtils.notNull(state.getLeft())); - ObjectUtils.notNull(state.getRight()).append(instance); - } - - private static void handleDefineAssembly( // NOPMD false positive - @NonNull XmlObject obj, - Pair state) { - IAssemblyInstanceGrouped instance = new XmlGroupedInlineAssemblyDefinition( - (GroupedInlineAssemblyDefinitionType) obj, - ObjectUtils.notNull(state.getLeft())); - ObjectUtils.notNull(state.getRight()).append(instance); - } - - private static class XmlModelContainer - extends DefaultGroupedModelContainerSupport< - INamedModelInstanceGrouped, - IFieldInstanceGrouped, - IAssemblyInstanceGrouped> { - - /** - * Parse a choice group XMLBeans object. - * - * @param xmlObject - * the XMLBeans object - * @param parent - * the parent Metaschema node, either an assembly definition or choice - */ - public XmlModelContainer( - @NonNull GroupedChoiceType xmlObject, - @NonNull IChoiceGroupInstance parent) { - XML_MODEL_PARSER.parse(xmlObject, Pair.of(parent, this)); - } - - public void append(@NonNull IFieldInstanceGrouped instance) { - IEnhancedQName key = instance.getQName(); - getFieldInstanceMap().put(key, instance); - getNamedModelInstanceMap().put(key, instance); - } - - public void append(@NonNull IAssemblyInstanceGrouped instance) { - IEnhancedQName key = instance.getQName(); - getAssemblyInstanceMap().put(key, instance); - getNamedModelInstanceMap().put(key, instance); - } - } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceInstance.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceInstance.java index 0513f5dc9..dd4c4c265 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceInstance.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlChoiceInstance.java @@ -7,9 +7,11 @@ import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; import gov.nist.secauto.metaschema.core.model.AbstractChoiceInstance; +import gov.nist.secauto.metaschema.core.model.DefaultChoiceModelBuilder; import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; import gov.nist.secauto.metaschema.core.model.IChoiceInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; @@ -19,7 +21,6 @@ import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.FieldReferenceType; import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.InlineAssemblyDefinitionType; import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.InlineFieldDefinitionType; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import org.apache.commons.lang3.tuple.Pair; @@ -41,86 +42,74 @@ class XmlChoiceInstance @NonNull private final ChoiceType xmlChoice; @NonNull - private final Lazy modelContainer; + private final Lazy> modelContainer; + + @SuppressWarnings("PMD.UseConcurrentHashMap") + @NonNull + private static final XmlObjectParser> XML_MODEL_PARSER + = new XmlObjectParser<>(ObjectUtils.notNull( + Map.ofEntries( + Map.entry(XmlModuleConstants.ASSEMBLY_QNAME, XmlChoiceInstance::handleAssembly), + Map.entry(XmlModuleConstants.DEFINE_ASSEMBLY_QNAME, XmlChoiceInstance::handleDefineAssembly), + Map.entry(XmlModuleConstants.FIELD_QNAME, XmlChoiceInstance::handleField), + Map.entry(XmlModuleConstants.DEFINE_FIELD_QNAME, XmlChoiceInstance::handleDefineField)))) { + + @Override + protected Handler> identifyHandler( + XmlCursor cursor, + XmlObject obj) { + Handler> retval; + if (obj instanceof FieldReferenceType) { + retval = XmlChoiceInstance::handleField; + } else if (obj instanceof InlineFieldDefinitionType) { + retval = XmlChoiceInstance::handleDefineField; + } else if (obj instanceof AssemblyReferenceType) { + retval = XmlChoiceInstance::handleAssembly; + } else if (obj instanceof InlineAssemblyDefinitionType) { + retval = XmlChoiceInstance::handleDefineAssembly; + } else { + retval = super.identifyHandler(cursor, obj); + } + return retval; + } + }; /** - * Constructs a mutually exclusive choice between two possible objects. + * Parse a choice group XMLBeans object. * * @param xmlObject - * the XML for the choice definition bound to Java objects + * the XMLBeans object * @param parent - * the parent container, either a choice or assembly - */ - public XmlChoiceInstance( - @NonNull ChoiceType xmlObject, - @NonNull IAssemblyDefinition parent) { - super(parent); - this.xmlChoice = xmlObject; - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> new XmlModelContainer(xmlObject, this))); - } - - @Override - public XmlModelContainer getModelContainer() { - return ObjectUtils.notNull(modelContainer.get()); - } - - // ---------------------------------------- - // - Start XmlBeans driven code - CPD-OFF - - // ---------------------------------------- - - /** - * Get the underlying XML data. - * - * @return the underlying XML data + * the parent Metaschema node, either an assembly definition or choice */ - @NonNull - protected ChoiceType getXmlObject() { - return xmlChoice; + private static IContainerModelSupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute> newContainer( + @NonNull ChoiceType xmlObject, + @NonNull IChoiceInstance parent) { + ModelBuilder builder = new ModelBuilder(); + XML_MODEL_PARSER.parse(xmlObject, Pair.of(parent, builder)); + return builder.buildChoice(); } - @Override - public MarkupMultiline getRemarks() { - // remarks not supported - return null; + private static final class ModelBuilder + extends DefaultChoiceModelBuilder< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute> { + // no other methods } - // ------------------------------------- - // - End XmlBeans driven code - CPD-ON - - // ------------------------------------- - - @SuppressWarnings("PMD.UseConcurrentHashMap") - @NonNull - private static final XmlObjectParser> XML_MODEL_PARSER - = new XmlObjectParser<>(ObjectUtils.notNull( - Map.ofEntries( - Map.entry(XmlModuleConstants.ASSEMBLY_QNAME, XmlChoiceInstance::handleAssembly), - Map.entry(XmlModuleConstants.DEFINE_ASSEMBLY_QNAME, XmlChoiceInstance::handleDefineAssembly), - Map.entry(XmlModuleConstants.FIELD_QNAME, XmlChoiceInstance::handleField), - Map.entry(XmlModuleConstants.DEFINE_FIELD_QNAME, XmlChoiceInstance::handleDefineField)))) { - - @Override - protected Handler> identifyHandler(XmlCursor cursor, - XmlObject obj) { - Handler> retval; - if (obj instanceof FieldReferenceType) { - retval = XmlChoiceInstance::handleField; - } else if (obj instanceof InlineFieldDefinitionType) { - retval = XmlChoiceInstance::handleDefineField; - } else if (obj instanceof AssemblyReferenceType) { - retval = XmlChoiceInstance::handleAssembly; - } else if (obj instanceof InlineAssemblyDefinitionType) { - retval = XmlChoiceInstance::handleDefineAssembly; - } else { - retval = super.identifyHandler(cursor, obj); - } - return retval; - } - }; - private static void handleField( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IFieldInstanceAbsolute instance = new XmlFieldInstance( (FieldReferenceType) obj, ObjectUtils.notNull(state.getLeft())); @@ -129,7 +118,7 @@ private static void handleField( // NOPMD false positive private static void handleDefineField( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IFieldInstanceAbsolute instance = new XmlInlineFieldDefinition( (InlineFieldDefinitionType) obj, ObjectUtils.notNull(state.getLeft())); @@ -138,7 +127,7 @@ private static void handleDefineField( // NOPMD false positive private static void handleAssembly( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IAssemblyInstanceAbsolute instance = new XmlAssemblyInstance( (AssemblyReferenceType) obj, ObjectUtils.notNull(state.getLeft())); @@ -147,46 +136,59 @@ private static void handleAssembly( // NOPMD false positive private static void handleDefineAssembly( // NOPMD false positive @NonNull XmlObject obj, - Pair state) { + Pair state) { IAssemblyInstanceAbsolute instance = new XmlInlineAssemblyDefinition( (InlineAssemblyDefinitionType) obj, ObjectUtils.notNull(state.getLeft())); ObjectUtils.notNull(state.getRight()).append(instance); } - private static class XmlModelContainer - extends DefaultContainerModelSupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute> { + /** + * Constructs a mutually exclusive choice between two possible objects. + * + * @param xmlObject + * the XML for the choice definition bound to Java objects + * @param parent + * the parent container, either a choice or assembly + */ + public XmlChoiceInstance( + @NonNull ChoiceType xmlObject, + @NonNull IAssemblyDefinition parent) { + super(parent); + this.xmlChoice = xmlObject; + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> newContainer(xmlObject, this))); + } + + @Override + public IContainerModelSupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute> getModelContainer() { + return ObjectUtils.notNull(modelContainer.get()); + } - /** - * Parse a choice group XMLBeans object. - * - * @param xmlObject - * the XMLBeans object - * @param parent - * the parent Metaschema node, either an assembly definition or choice - */ - public XmlModelContainer( - @NonNull ChoiceType xmlObject, - @NonNull IChoiceInstance parent) { - XML_MODEL_PARSER.parse(xmlObject, Pair.of(parent, this)); - } - - public void append(@NonNull IFieldInstanceAbsolute instance) { - IEnhancedQName key = instance.getQName(); - getFieldInstanceMap().put(key, instance); - getNamedModelInstanceMap().put(key, instance); - getModelInstances().add(instance); - } - - public void append(@NonNull IAssemblyInstanceAbsolute instance) { - IEnhancedQName key = instance.getQName(); - getAssemblyInstanceMap().put(key, instance); - getNamedModelInstanceMap().put(key, instance); - getModelInstances().add(instance); - } + // ---------------------------------------- + // - Start XmlBeans driven code - CPD-OFF - + // ---------------------------------------- + + /** + * Get the underlying XML data. + * + * @return the underlying XML data + */ + @NonNull + protected ChoiceType getXmlObject() { + return xmlChoice; } + + @Override + public MarkupMultiline getRemarks() { + // remarks not supported + return null; + } + + // ------------------------------------- + // - End XmlBeans driven code - CPD-ON - + // ------------------------------------- } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/qname/EQNameFactory.java b/core/src/main/java/gov/nist/secauto/metaschema/core/qname/EQNameFactory.java new file mode 100644 index 000000000..0d92f2f62 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/qname/EQNameFactory.java @@ -0,0 +1,193 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.qname; + +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import nl.talsmasoftware.lazy4j.Lazy; + +public class EQNameFactory { + private static final Pattern URI_QUALIFIED_NAME = Pattern.compile("^Q\\{([^{}]*)\\}(.+)$"); + private static final Pattern LEXICAL_NAME = Pattern.compile("^(?:([^:]+):)?(.+)$"); + @NonNull + private static final Lazy INSTANCE = ObjectUtils.notNull(Lazy.lazy(EQNameFactory::new)); + + @NonNull + private final QNameCache cache; + + @NonNull + public static EQNameFactory instance() { + return ObjectUtils.notNull(INSTANCE.get()); + } + + @NonNull + public static IEnhancedQName of(@NonNull QName qname) { + return instance().newQName(qname); + } + + @NonNull + public static IEnhancedQName of(@NonNull String localName) { + return instance().newQName(localName); + } + + @NonNull + public static IEnhancedQName of(@NonNull String namespace, @NonNull String localName) { + return instance().newQName(namespace, localName); + } + + @NonNull + public static IEnhancedQName of(@NonNull URI namespace, @NonNull String localName) { + return instance().newQName(namespace, localName); + } + + private EQNameFactory() { + // disable construction + this(QNameCache.instance()); + } + + public EQNameFactory(@NonNull QNameCache cache) { + this.cache = cache; + } + + @NonNull + public IEnhancedQName newQName(@NonNull QName qname) { + return cache.of(qname); + } + + @NonNull + public IEnhancedQName newQName(@NonNull String localName) { + return cache.of("", localName); + } + + @NonNull + public IEnhancedQName newQName(@NonNull String namespace, @NonNull String localName) { + return cache.of(namespace, localName); + } + + @NonNull + public IEnhancedQName newQName(@NonNull URI namespace, @NonNull String localName) { + return cache.of(namespace, localName); + } + + /** + * Parse a name as a qualified name. + *

    + * The name can be: + *

    + * + * @param name + * the name to parse + * @param resolver + * the prefix resolver to use to determine the namespace for a given + * prefix + * @return the parsed qualified name + */ + @NonNull + public IEnhancedQName parseName( + @NonNull String name, + @NonNull PrefixToNamespaceResolver resolver) { + Matcher matcher = URI_QUALIFIED_NAME.matcher(name); + return matcher.matches() + ? newUriQualifiedName(matcher) + : parseLexicalQName(name, resolver); + } + + /** + * Parse a URI qualified name. + *

    + * The name is expected to be a URI qualified name of the form + * {URI}name, where the URI represents the namespace. + * + * @param name + * the name to parse + * @return the parsed qualified name + */ + @NonNull + public IEnhancedQName parseUriQualifiedName(@NonNull String name) { + Matcher matcher = URI_QUALIFIED_NAME.matcher(name); + if (!matcher.matches()) { + throw new IllegalArgumentException( + String.format("The name '%s' is not a valid BracedURILiteral of the form: Q{URI}local-name", name)); + } + return newUriQualifiedName(matcher); + } + + @NonNull + private IEnhancedQName newUriQualifiedName(@NonNull Matcher matcher) { + return cache.of(matcher.group(1), matcher.group(2)); + } + + /** + * Parse a lexical name as a qualified name. + *

    + * The name is expected to be a lexical name of the forms + * prefix:name or name, where the prefix represents + * the namespace. + * + * @param name + * the name to parse + * @param resolver + * the prefix resolver to use to determine the namespace for a given + * prefix + * @return the parsed qualified name + */ + @NonNull + public IEnhancedQName parseLexicalQName( + @NonNull String name, + @NonNull PrefixToNamespaceResolver resolver) { + Matcher matcher = LEXICAL_NAME.matcher(name); + if (!matcher.matches()) { + throw new IllegalArgumentException( + String.format("The name '%s' is not a valid lexical QName of the form: prefix:local-name or local-name", + name)); + } + String prefix = matcher.group(1); + + if (prefix == null) { + prefix = XMLConstants.DEFAULT_NS_PREFIX; + } + + String namespace = resolver.resolve(prefix); + if (namespace == null) { + throw new IllegalArgumentException( + String.format("The prefix '%s' is not bound for name '%s'", + prefix, + name)); + } + return cache.of(namespace, matcher.group(2)); + } + + /** + * Provides a callback for resolving namespace prefixes. + */ + @FunctionalInterface + public interface PrefixToNamespaceResolver { + /** + * Get the URI string for the provided namespace prefix. + * + * @param prefix + * the namespace prefix + * @return the URI string or {@code null} if the prefix is unbound + */ + @Nullable + String resolve(@NonNull String prefix); + } + +} diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/EQNameUtilsTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java similarity index 94% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/EQNameUtilsTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java index fba9411ea..cbb8e62b6 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/EQNameUtilsTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/StaticContextTest.java @@ -3,13 +3,11 @@ * SPDX-License-Identifier: CC0-1.0 */ -package gov.nist.secauto.metaschema.core.metapath.cst; +package gov.nist.secauto.metaschema.core.metapath; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; -import gov.nist.secauto.metaschema.core.metapath.StaticContext; import gov.nist.secauto.metaschema.core.metapath.function.IFunction; import gov.nist.secauto.metaschema.core.qname.EQNameFactory; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; @@ -22,8 +20,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -// FIXME: Move to correct package -class EQNameUtilsTest { +class StaticContextTest { private static final String MODEL_NS = "http://example.com/ns/model"; private static final StaticContext STATIC_CONTEXT = StaticContext.builder() .namespace("prefix", MetapathConstants.NS_METAPATH_FUNCTIONS) diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelAssembly.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelAssembly.java deleted file mode 100644 index 5b113ccb0..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelAssembly.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model; - -import gov.nist.secauto.metaschema.core.model.IContainerModelAssembly; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; - -import java.util.Collection; -import java.util.Map; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; - -public interface IBoundContainerModelAssembly extends IContainerModelAssembly { - @Override - @NonNull - IBoundDefinitionModelAssembly getOwningDefinition(); - - @Override - @NonNull - Collection> getModelInstances(); - - @Override - @NonNull - Collection> getNamedModelInstances(); - - @Override - @Nullable - IBoundInstanceModelNamed getNamedModelInstanceByName(IEnhancedQName name); - - @Override - @NonNull - Collection> getFieldInstances(); - - @Override - @Nullable - IBoundInstanceModelField getFieldInstanceByName(IEnhancedQName name); - - @Override - @NonNull - Collection getAssemblyInstances(); - - @Override - @Nullable - IBoundInstanceModelAssembly getAssemblyInstanceByName(IEnhancedQName name); - - @Override - IBoundInstanceModelChoiceGroup getChoiceGroupInstanceByName(String name); - - @Override - Map getChoiceGroupInstances(); -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelChoiceGroup.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelChoiceGroup.java deleted file mode 100644 index 70acb0772..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundContainerModelChoiceGroup.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model; - -import gov.nist.secauto.metaschema.core.model.IContainerModelGrouped; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; - -import java.util.Collection; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; - -public interface IBoundContainerModelChoiceGroup extends IContainerModelGrouped { - - @Override - @NonNull - Collection getModelInstances(); - - @Override - @NonNull - Collection getNamedModelInstances(); - - @Override - IBoundInstanceModelGroupedNamed getNamedModelInstanceByName(IEnhancedQName name); - - @Override - @NonNull - Collection getFieldInstances(); - - @Override - @Nullable - IBoundInstanceModelGroupedField getFieldInstanceByName(IEnhancedQName name); - - @Override - @NonNull - Collection getAssemblyInstances(); - - @Override - @Nullable - IBoundInstanceModelGroupedAssembly getAssemblyInstanceByName(IEnhancedQName name); -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundDefinitionModelAssembly.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundDefinitionModelAssembly.java index afc726000..187a72508 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundDefinitionModelAssembly.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundDefinitionModelAssembly.java @@ -7,12 +7,16 @@ import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; import gov.nist.secauto.metaschema.core.model.IBoundObject; +import gov.nist.secauto.metaschema.core.model.IChoiceInstance; +import gov.nist.secauto.metaschema.core.model.IFeatureContainerModelAssembly; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; +import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.metaschema.databind.model.info.IItemReadHandler; import gov.nist.secauto.metaschema.databind.model.info.IItemWriteHandler; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.function.Predicate; @@ -26,7 +30,14 @@ * Represents an assembly definition bound to a Java class. */ public interface IBoundDefinitionModelAssembly - extends IBoundDefinitionModelComplex, IBoundContainerModelAssembly, IAssemblyDefinition { + extends IBoundDefinitionModelComplex, IAssemblyDefinition, + IFeatureContainerModelAssembly< + IBoundInstanceModel, + IBoundInstanceModelNamed, + IBoundInstanceModelField, + IBoundInstanceModelAssembly, + IChoiceInstance, + IBoundInstanceModelChoiceGroup> { // , IBoundContainerModelAssembly // Assembly Definition Features // ============================ @@ -48,12 +59,13 @@ default IBoundInstanceModelAssembly getInlineInstance() { // never inline return null; } - // - // @Override - // @NonNull - // default QName getXmlQName() { - // return ObjectUtils.requireNonNull(getRootXmlQName()); - // } + + @Override + @NonNull + default List getChoiceInstances() { + // not supported + return CollectionUtil.emptyList(); + } @Override @NonNull diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundInstanceModelChoiceGroup.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundInstanceModelChoiceGroup.java index 18e6f2567..746c3cd29 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundInstanceModelChoiceGroup.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/IBoundInstanceModelChoiceGroup.java @@ -7,6 +7,7 @@ import gov.nist.secauto.metaschema.core.model.IBoundObject; import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; +import gov.nist.secauto.metaschema.core.model.IFeatureContainerModelGrouped; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.metaschema.databind.io.BindingException; @@ -24,7 +25,11 @@ * Represents a choice group instance bound to Java field. */ public interface IBoundInstanceModelChoiceGroup - extends IBoundInstanceModel, IBoundContainerModelChoiceGroup, IChoiceGroupInstance { + extends IBoundInstanceModel, IFeatureContainerModelGrouped< + IBoundInstanceModelGroupedNamed, + IBoundInstanceModelGroupedField, + IBoundInstanceModelGroupedAssembly>, + IChoiceGroupInstance { /** * Create a new bound choice group instance. diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AssemblyModelContainerSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AssemblyModelGenerator.java similarity index 53% rename from databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AssemblyModelContainerSupport.java rename to databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AssemblyModelGenerator.java index d9249ccae..da6c59b1e 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AssemblyModelContainerSupport.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AssemblyModelGenerator.java @@ -5,9 +5,9 @@ package gov.nist.secauto.metaschema.databind.model.impl; +import gov.nist.secauto.metaschema.core.model.DefaultAssemblyModelBuilder; import gov.nist.secauto.metaschema.core.model.IChoiceInstance; import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly; @@ -23,81 +23,52 @@ import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -class AssemblyModelContainerSupport - implements IContainerModelAssemblySupport< - IBoundInstanceModel, +final class AssemblyModelGenerator { + + @SuppressWarnings("PMD.ShortMethodName") + @NonNull + public static IContainerModelAssemblySupport< + IBoundInstanceModel, + IBoundInstanceModelNamed, + IBoundInstanceModelField, + IBoundInstanceModelAssembly, + IChoiceInstance, + IBoundInstanceModelChoiceGroup> of(@NonNull DefinitionAssembly containingDefinition) { + DefaultAssemblyModelBuilder, IBoundInstanceModelNamed, IBoundInstanceModelField, IBoundInstanceModelAssembly, IChoiceInstance, - IBoundInstanceModelChoiceGroup> { - @NonNull - private final List> modelInstances; - @NonNull - private final Map> namedModelInstances; - @NonNull - private final Map> fieldInstances; - @NonNull - private final Map assemblyInstances; - @NonNull - private final Map choiceGroupInstances; + IBoundInstanceModelChoiceGroup> builder = new DefaultAssemblyModelBuilder<>(); - @SuppressWarnings("PMD.UseConcurrentHashMap") - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - public AssemblyModelContainerSupport( - @NonNull DefinitionAssembly containingDefinition) { - this.modelInstances = CollectionUtil.unmodifiableList(ObjectUtils.notNull( + List> modelInstances = CollectionUtil.unmodifiableList(ObjectUtils.notNull( getModelInstanceStream(containingDefinition, containingDefinition.getBoundClass()) .collect(Collectors.toUnmodifiableList()))); - Map> namedModelInstances = new LinkedHashMap<>(); - Map> fieldInstances = new LinkedHashMap<>(); - Map assemblyInstances = new LinkedHashMap<>(); - Map choiceGroupInstances = new LinkedHashMap<>(); - for (IBoundInstanceModel instance : this.modelInstances) { + for (IBoundInstanceModel instance : modelInstances) { if (instance instanceof IBoundInstanceModelNamed) { IBoundInstanceModelNamed named = (IBoundInstanceModelNamed) instance; - IEnhancedQName key = named.getQName(); - namedModelInstances.put(key, named); - if (instance instanceof IBoundInstanceModelField) { - fieldInstances.put(key, (IBoundInstanceModelField) named); + builder.append((IBoundInstanceModelField) named); } else if (instance instanceof IBoundInstanceModelAssembly) { - assemblyInstances.put(key, (IBoundInstanceModelAssembly) named); + builder.append((IBoundInstanceModelAssembly) named); } } else if (instance instanceof IBoundInstanceModelChoiceGroup) { IBoundInstanceModelChoiceGroup choiceGroup = (IBoundInstanceModelChoiceGroup) instance; - String key = ObjectUtils.requireNonNull(choiceGroup.getGroupAsName()); - choiceGroupInstances.put(key, choiceGroup); + builder.append(choiceGroup); } } - - this.namedModelInstances = namedModelInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(namedModelInstances); - this.fieldInstances = fieldInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(fieldInstances); - this.assemblyInstances = assemblyInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(assemblyInstances); - this.choiceGroupInstances = choiceGroupInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(choiceGroupInstances); + return builder.buildAssembly(); } - protected static IBoundInstanceModel newBoundModelInstance( + private static IBoundInstanceModel newBoundModelInstance( @NonNull Field field, @NonNull IBoundDefinitionModelAssembly definition) { IBoundInstanceModel retval = null; @@ -112,7 +83,7 @@ protected static IBoundInstanceModel newBoundModelInstance( } @NonNull - protected static Stream> getModelInstanceStream( + private static Stream> getModelInstanceStream( @NonNull IBoundDefinitionModelAssembly definition, @NonNull Class clazz) { @@ -145,34 +116,7 @@ protected static Stream> getModelInstanceStream( .filter(Objects::nonNull))); } - @Override - public Collection> getModelInstances() { - return modelInstances; - } - - @Override - public Map> getNamedModelInstanceMap() { - return namedModelInstances; - } - - @Override - public Map> getFieldInstanceMap() { - return fieldInstances; - } - - @Override - public Map getAssemblyInstanceMap() { - return assemblyInstances; - } - - @Override - public List getChoiceInstances() { - // not supported - return CollectionUtil.emptyList(); - } - - @Override - public Map getChoiceGroupInstanceMap() { - return choiceGroupInstances; + private AssemblyModelGenerator() { + // disable construction } } diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/DefinitionAssembly.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/DefinitionAssembly.java index 13c8c884c..8d7210988 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/DefinitionAssembly.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/DefinitionAssembly.java @@ -9,6 +9,8 @@ import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; import gov.nist.secauto.metaschema.core.model.IAttributable; import gov.nist.secauto.metaschema.core.model.IBoundObject; +import gov.nist.secauto.metaschema.core.model.IChoiceInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport; import gov.nist.secauto.metaschema.core.model.ISource; import gov.nist.secauto.metaschema.core.model.constraint.AssemblyConstraintSet; import gov.nist.secauto.metaschema.core.model.constraint.IModelConstrained; @@ -47,18 +49,18 @@ @SuppressWarnings("PMD.CouplingBetweenObjects") public final class DefinitionAssembly extends AbstractBoundDefinitionModelComplex - implements IBoundDefinitionModelAssembly, - IFeatureBoundContainerModelAssembly< - IBoundInstanceModel, - IBoundInstanceModelNamed, - IBoundInstanceModelField, - IBoundInstanceModelAssembly, - IBoundInstanceModelChoiceGroup> { + implements IBoundDefinitionModelAssembly { @NonNull private final Lazy flagContainer; @NonNull - private final Lazy modelContainer; + private final Lazy, + IBoundInstanceModelNamed, + IBoundInstanceModelField, + IBoundInstanceModelAssembly, + IChoiceInstance, + IBoundInstanceModelChoiceGroup>> modelContainer; @NonNull private final Lazy constraints; @NonNull @@ -103,7 +105,7 @@ private DefinitionAssembly( ? null : getContainingModule().getModuleStaticContext().parseModelName(rootLocalName))); this.flagContainer = ObjectUtils.notNull(Lazy.lazy(() -> new FlagContainerSupport(this, null))); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> new AssemblyModelContainerSupport(this))); + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelGenerator.of(this))); ISource moduleSource = module.getSource(); this.constraints = ObjectUtils.notNull(Lazy.lazy(() -> { @@ -153,7 +155,13 @@ public FlagContainerSupport getFlagContainer() { @Override @SuppressWarnings("null") @NonNull - public AssemblyModelContainerSupport getModelContainer() { + public IContainerModelAssemblySupport< + IBoundInstanceModel, + IBoundInstanceModelNamed, + IBoundInstanceModelField, + IBoundInstanceModelAssembly, + IChoiceInstance, + IBoundInstanceModelChoiceGroup> getModelContainer() { return modelContainer.get(); } diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelAssembly.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelAssembly.java deleted file mode 100644 index 83eff58bd..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelAssembly.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.impl; - -import gov.nist.secauto.metaschema.core.model.IChoiceInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport; -import gov.nist.secauto.metaschema.core.model.IFeatureContainerModelAssembly; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import gov.nist.secauto.metaschema.databind.model.IBoundContainerModelAssembly; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModel; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelAssembly; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelField; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelNamed; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import edu.umd.cs.findbugs.annotations.NonNull; - -public interface IFeatureBoundContainerModelAssembly< - MI extends IBoundInstanceModel, - NMI extends IBoundInstanceModelNamed, - FI extends IBoundInstanceModelField, - AI extends IBoundInstanceModelAssembly, - CGI extends IBoundInstanceModelChoiceGroup> - extends IBoundContainerModelAssembly, IFeatureContainerModelAssembly { - @Override - @NonNull - IContainerModelAssemblySupport getModelContainer(); - - @Override - default Collection getModelInstances() { - return getModelContainer().getModelInstances(); - } - - @Override - default NMI getNamedModelInstanceByName(IEnhancedQName name) { - return getModelContainer().getNamedModelInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getNamedModelInstances() { - return getModelContainer().getNamedModelInstanceMap().values(); - } - - @Override - default FI getFieldInstanceByName(IEnhancedQName name) { - return getModelContainer().getFieldInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getFieldInstances() { - return getModelContainer().getFieldInstanceMap().values(); - } - - @Override - default AI getAssemblyInstanceByName(IEnhancedQName name) { - return getModelContainer().getAssemblyInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getAssemblyInstances() { - return getModelContainer().getAssemblyInstanceMap().values(); - } - - @Override - @NonNull - default List getChoiceInstances() { - // not supported - return CollectionUtil.emptyList(); - } - - @Override - default CGI getChoiceGroupInstanceByName(String name) { - return getModelContainer().getChoiceGroupInstanceMap().get(name); - } - - @Override - default Map getChoiceGroupInstances() { - return getModelContainer().getChoiceGroupInstanceMap(); - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelChoiceGroup.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelChoiceGroup.java deleted file mode 100644 index 6cfa2e7b6..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureBoundContainerModelChoiceGroup.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.impl; - -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFeatureContainerModelGrouped; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.databind.model.IBoundContainerModelChoiceGroup; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedField; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedNamed; - -import java.util.Collection; - -import edu.umd.cs.findbugs.annotations.NonNull; - -public interface IFeatureBoundContainerModelChoiceGroup - extends IBoundContainerModelChoiceGroup, IFeatureContainerModelGrouped< - IBoundInstanceModelGroupedNamed, - IBoundInstanceModelGroupedField, - IBoundInstanceModelGroupedAssembly> { - - @Override - @NonNull - IContainerModelSupport< - IBoundInstanceModelGroupedNamed, - IBoundInstanceModelGroupedNamed, - IBoundInstanceModelGroupedField, - IBoundInstanceModelGroupedAssembly> getModelContainer(); - - @Override - default Collection getModelInstances() { - return getModelContainer().getModelInstances(); - } - - @Override - default IBoundInstanceModelGroupedNamed getNamedModelInstanceByName(IEnhancedQName name) { - return getModelContainer().getNamedModelInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getNamedModelInstances() { - return getModelContainer().getNamedModelInstanceMap().values(); - } - - @Override - default IBoundInstanceModelGroupedField getFieldInstanceByName(IEnhancedQName name) { - return getModelContainer().getFieldInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getFieldInstances() { - return getModelContainer().getFieldInstanceMap().values(); - } - - @Override - default IBoundInstanceModelGroupedAssembly getAssemblyInstanceByName(IEnhancedQName name) { - return getModelContainer().getAssemblyInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getAssemblyInstances() { - return getModelContainer().getAssemblyInstanceMap().values(); - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureInstanceModelGroupAs.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureInstanceModelGroupAs.java index a5dd88bef..e4d501312 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureInstanceModelGroupAs.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/IFeatureInstanceModelGroupAs.java @@ -50,5 +50,4 @@ default JsonGroupAsBehavior getJsonGroupAsBehavior() { default XmlGroupAsBehavior getXmlGroupAsBehavior() { return getGroupAs().getXmlGroupAsBehavior(); } - } diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/InstanceModelChoiceGroup.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/InstanceModelChoiceGroup.java index 4dd23b115..a5a7b78fe 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/InstanceModelChoiceGroup.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/InstanceModelChoiceGroup.java @@ -6,11 +6,11 @@ package gov.nist.secauto.metaschema.databind.model.impl; import gov.nist.secauto.metaschema.core.model.AbstractChoiceGroupInstance; +import gov.nist.secauto.metaschema.core.model.DefaultChoiceGroupModelBuilder; import gov.nist.secauto.metaschema.core.model.IBoundObject; import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; import gov.nist.secauto.metaschema.core.qname.EQNameFactory; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly; @@ -30,14 +30,9 @@ import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -54,8 +49,7 @@ public final class InstanceModelChoiceGroup IBoundInstanceModelGroupedNamed, IBoundInstanceModelGroupedField, IBoundInstanceModelGroupedAssembly> - implements IBoundInstanceModelChoiceGroup, - IFeatureBoundContainerModelChoiceGroup, IFeatureInstanceModelGroupAs { + implements IBoundInstanceModelChoiceGroup, IFeatureInstanceModelGroupAs { @NonNull private final Field javaField; @NonNull @@ -65,7 +59,11 @@ public final class InstanceModelChoiceGroup @NonNull private final IGroupAs groupAs; @NonNull - private final Lazy modelContainer; + private final Lazy> modelContainer; @NonNull private final Lazy, IBoundInstanceModelGroupedNamed>> classToInstanceMap; @NonNull @@ -107,6 +105,34 @@ public static InstanceModelChoiceGroup newInstance( return new InstanceModelChoiceGroup(javaField, annotation, groupAs, parent); } + @NonNull + private static IContainerModelSupport< + IBoundInstanceModelGroupedNamed, + IBoundInstanceModelGroupedNamed, + IBoundInstanceModelGroupedField, + IBoundInstanceModelGroupedAssembly> newContainerModel( + @NonNull BoundGroupedAssembly[] assemblies, + @NonNull BoundGroupedField[] fields, + @NonNull IBoundInstanceModelChoiceGroup container) { + DefaultChoiceGroupModelBuilder< + IBoundInstanceModelGroupedNamed, + IBoundInstanceModelGroupedField, + IBoundInstanceModelGroupedAssembly> builder = new DefaultChoiceGroupModelBuilder<>(); + + Arrays.stream(assemblies) + .map(instance -> { + assert instance != null; + return IBoundInstanceModelGroupedAssembly.newInstance(instance, container); + }).forEachOrdered(builder::append); + Arrays.stream(fields) + .map(instance -> { + assert instance != null; + return IBoundInstanceModelGroupedField.newInstance(instance, container); + }).forEachOrdered(builder::append); + + return builder.buildChoiceGroup(); + } + @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") private InstanceModelChoiceGroup( @NonNull Field javaField, @@ -118,7 +144,7 @@ private InstanceModelChoiceGroup( this.annotation = annotation; this.groupAs = groupAs; this.collectionInfo = ObjectUtils.notNull(Lazy.lazy(() -> IModelInstanceCollectionInfo.of(this))); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> new ChoiceGroupModelContainerSupport( + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> newContainerModel( this.annotation.assemblies(), this.annotation.fields(), this))); @@ -224,7 +250,11 @@ public IGroupAs getGroupAs() { @SuppressWarnings("null") @Override - public ChoiceGroupModelContainerSupport getModelContainer() { + public IContainerModelSupport< + IBoundInstanceModelGroupedNamed, + IBoundInstanceModelGroupedNamed, + IBoundInstanceModelGroupedField, + IBoundInstanceModelGroupedAssembly> getModelContainer() { return modelContainer.get(); } @@ -275,75 +305,4 @@ public IBoundInstanceFlag getItemJsonKey(Object item) { } return retval; } - - private static class ChoiceGroupModelContainerSupport - implements IContainerModelSupport< - IBoundInstanceModelGroupedNamed, - IBoundInstanceModelGroupedNamed, - IBoundInstanceModelGroupedField, - IBoundInstanceModelGroupedAssembly> { - - @NonNull - private final Map namedModelInstances; - @NonNull - private final Map fieldInstances; - @NonNull - private final Map assemblyInstances; - - public ChoiceGroupModelContainerSupport( - @NonNull BoundGroupedAssembly[] assemblies, - @NonNull BoundGroupedField[] fields, - @NonNull IBoundInstanceModelChoiceGroup container) { - this.assemblyInstances = CollectionUtil.unmodifiableMap(ObjectUtils.notNull(Arrays.stream(assemblies) - .map(instance -> { - assert instance != null; - return IBoundInstanceModelGroupedAssembly.newInstance(instance, - container); - }) - .collect(Collectors.toMap( - IBoundInstanceModelGroupedAssembly::getQName, - Function.identity(), - CustomCollectors.useLastMapper(), - LinkedHashMap::new)))); - this.fieldInstances = CollectionUtil.unmodifiableMap(ObjectUtils.notNull(Arrays.stream(fields) - .map(instance -> { - assert instance != null; - return IBoundInstanceModelGroupedField.newInstance(instance, container); - }) - .collect(Collectors.toMap( - IBoundInstanceModelGroupedField::getQName, - Function.identity(), - CustomCollectors.useLastMapper(), - LinkedHashMap::new)))); - this.namedModelInstances = CollectionUtil.unmodifiableMap(ObjectUtils.notNull(Stream.concat( - this.assemblyInstances.entrySet().stream(), - this.fieldInstances.entrySet().stream()) - .collect(Collectors.toMap( - Entry::getKey, - Entry::getValue, - CustomCollectors.useLastMapper(), - LinkedHashMap::new)))); - } - - @SuppressWarnings("null") - @Override - public Collection getModelInstances() { - return namedModelInstances.values(); - } - - @Override - public Map getNamedModelInstanceMap() { - return namedModelInstances; - } - - @Override - public Map getFieldInstanceMap() { - return fieldInstances; - } - - @Override - public Map getAssemblyInstanceMap() { - return assemblyInstances; - } - } } diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractAbsoluteModelGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractAbsoluteModelGenerator.java new file mode 100644 index 000000000..5e816e7fc --- /dev/null +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractAbsoluteModelGenerator.java @@ -0,0 +1,226 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.databind.model.metaschema.impl; + +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; +import gov.nist.secauto.metaschema.core.model.DefaultChoiceModelBuilder; +import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; +import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IContainerModelAbsolute; +import gov.nist.secauto.metaschema.core.model.IFieldDefinition; +import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IModule; +import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyReference; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.FieldReference; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineField; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Supports generating the model contents of a Metaschema instance with a + * complex structure. + *

    + * This class is not thread safe. + * + * @param + * the Java type of the parent Metaschema object that contains the + * generated model + * @param + * the Java type of the builder to use to gather the container + * instances + */ +@SuppressWarnings({ + "PMD.AbstractClassWithoutAbstractMethod", + "PMD.UseConcurrentHashMap" }) +public abstract class AbstractAbsoluteModelGenerator< + PARENT extends IContainerModelAbsolute, + BUILDER extends DefaultChoiceModelBuilder< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute>> { + @NonNull + private final PARENT parent; + @NonNull + private final INodeItemFactory nodeItemFactory; + @NonNull + private final BUILDER builder; + + // counters to track child positions + private int assemblyReferencePosition; // 0 + private int assemblyInlineDefinitionPosition; // 0 + private int fieldReferencePosition; // 0 + private int fieldInlineDefinitionPosition; // 0 + + /** + * Construct a new generator. + * + * @param parent + * the parent that owns this container + * @param nodeItemFactory + * the factory used to create new nodes within this container + * @param builder + * the builder to use to gather the container instances + */ + protected AbstractAbsoluteModelGenerator( + @NonNull PARENT parent, + @NonNull INodeItemFactory nodeItemFactory, + @NonNull BUILDER builder) { + this.parent = parent; + this.nodeItemFactory = nodeItemFactory; + this.builder = builder; + } + + /** + * Get the parent that owns this container. + * + * @return the parent + */ + @NonNull + protected PARENT getParent() { + return parent; + } + + /** + * Get the factory used to create new nodes within this container. + * + * @return the factory + */ + @NonNull + protected INodeItemFactory getNodeItemFactory() { + return nodeItemFactory; + } + + /** + * Get the builder to use to gather the container instances. + * + * @return the builder + */ + protected BUILDER getBuilder() { + return builder; + } + + /** + * Add an assembly instance to the builder that is generated from the provided + * arguments. + * + * @param obj + * a bound assembly reference + * @param objInstance + * the Metaschema instance for the bound object + */ + protected void addAssemblyInstance( + @NonNull AssemblyReference obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + IAssemblyDefinition owningDefinition = getParent().getOwningDefinition(); + IModule module = owningDefinition.getContainingModule(); + + String name = ObjectUtils.requireNonNull(obj.getRef()); + IAssemblyDefinition definition = module.getScopedAssemblyDefinitionByName( + module.getModuleStaticContext().parseModelName(name)); + + if (definition == null) { + throw new IllegalStateException( + String.format("Unable to resolve assembly reference '%s' in definition '%s' in module '%s'", + name, + owningDefinition.getName(), + module.getShortName())); + } + getBuilder().append(new InstanceModelAssemblyReference( + obj, + objInstance, + assemblyReferencePosition++, + definition, + getParent())); + } + + /** + * Add an assembly instance to the builder that is generated from the provided + * arguments. + * + * @param obj + * a bound inline assembly + * @param objInstance + * the Metaschema instance for the bound object + */ + protected void addAssemblyInstance( + @NonNull InlineDefineAssembly obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + getBuilder().append(new InstanceModelAssemblyInline( + obj, + objInstance, + assemblyInlineDefinitionPosition++, + getParent(), + getNodeItemFactory())); + } + + /** + * Add a field instance to the builder that is generated from the provided + * arguments. + * + * @param obj + * a bound field reference + * @param objInstance + * the Metaschema instance for the bound object + */ + protected void addFieldInstance( + @NonNull FieldReference obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + IAssemblyDefinition owningDefinition = getParent().getOwningDefinition(); + IModule module = owningDefinition.getContainingModule(); + + String name = ObjectUtils.requireNonNull(obj.getRef()); + IFieldDefinition definition = module.getScopedFieldDefinitionByName( + module.getModuleStaticContext().parseModelName(name)); + if (definition == null) { + throw new IllegalStateException( + String.format("Unable to resolve field reference '%s' in definition '%s' in module '%s'", + name, + owningDefinition.getName(), + module.getShortName())); + } + getBuilder().append(new InstanceModelFieldReference( + obj, + objInstance, + fieldReferencePosition++, + definition, + getParent())); + } + + /** + * Add a field instance to the builder that is generated from the provided + * arguments. + * + * @param obj + * a bound inline field + * @param objInstance + * the Metaschema instance for the bound object + */ + + protected void addFieldInstance( + @NonNull InlineDefineField obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + getBuilder().append(new InstanceModelFieldInline( + obj, + objInstance, + fieldInlineDefinitionPosition++, + getParent())); + } + + @SuppressWarnings({ "PMD.EmptyFinalizer", "checkstyle:NoFinalizer" }) + @SuppressFBWarnings(value = "FI_EMPTY", justification = "needed to avoid finalization bug") + @Override + protected final void finalize() { + // Address SEI CERT Rule OBJ-11: + // https://wiki.sei.cmu.edu/confluence/display/java/OBJ11-J.+Be+wary+of+letting+constructors+throw+exceptions + } +} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractBindingModelContainerSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractBindingModelContainerSupport.java deleted file mode 100644 index f4dcf94b2..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AbstractBindingModelContainerSupport.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.metaschema.impl; - -import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; -import gov.nist.secauto.metaschema.core.model.IChoiceInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelAbsolute; -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFieldDefinition; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IModule; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyReference; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.FieldReference; - -import java.util.List; -import java.util.Map; - -import edu.umd.cs.findbugs.annotations.NonNull; - -public abstract class AbstractBindingModelContainerSupport - implements IContainerModelSupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute> { - - protected static void addInstance( - @NonNull IAssemblyInstanceAbsolute assembly, - @NonNull List modelInstances, - @NonNull Map namedModelInstances, - @NonNull Map assemblyInstances) { - IEnhancedQName effectiveName = assembly.getQName(); - modelInstances.add(assembly); - namedModelInstances.put(effectiveName, assembly); - assemblyInstances.put(effectiveName, assembly); - } - - protected static void addInstance( - @NonNull IFieldInstanceAbsolute field, - @NonNull List modelInstances, - @NonNull Map namedModelInstances, - @NonNull Map fieldInstances) { - IEnhancedQName effectiveName = field.getQName(); - modelInstances.add(field); - namedModelInstances.put(effectiveName, field); - fieldInstances.put(effectiveName, field); - } - - protected static void addInstance( - @NonNull IChoiceInstance choice, - @NonNull List modelInstances, - @NonNull List choiceInstances) { - modelInstances.add(choice); - choiceInstances.add(choice); - } - - protected static void addInstance( - @NonNull IChoiceGroupInstance choiceGroup, - @NonNull List modelInstances, - @NonNull Map choiceGroupInstances) { - modelInstances.add(choiceGroup); - choiceGroupInstances.put(choiceGroup.getGroupAsName(), choiceGroup); - } - - @NonNull - protected static IAssemblyInstanceAbsolute newInstance( - @NonNull AssemblyReference obj, - @NonNull IBoundInstanceModelGroupedAssembly objInstance, - int position, - @NonNull IContainerModelAbsolute parent) { - IAssemblyDefinition owningDefinition = parent.getOwningDefinition(); - IModule module = owningDefinition.getContainingModule(); - - String name = ObjectUtils.requireNonNull(obj.getRef()); - IAssemblyDefinition definition = module.getScopedAssemblyDefinitionByName( - module.getModuleStaticContext().parseModelName(name)); - - if (definition == null) { - throw new IllegalStateException( - String.format("Unable to resolve assembly reference '%s' in definition '%s' in module '%s'", - name, - owningDefinition.getName(), - module.getShortName())); - } - return new InstanceModelAssemblyReference(obj, objInstance, position, definition, parent); - } - - @NonNull - protected static IFieldInstanceAbsolute newInstance( - @NonNull FieldReference obj, - @NonNull IBoundInstanceModelGroupedAssembly objInstance, - int position, - @NonNull IContainerModelAbsolute parent) { - IAssemblyDefinition owningDefinition = parent.getOwningDefinition(); - IModule module = owningDefinition.getContainingModule(); - - String name = ObjectUtils.requireNonNull(obj.getRef()); - IFieldDefinition definition = module.getScopedFieldDefinitionByName( - module.getModuleStaticContext().parseModelName(name)); - if (definition == null) { - throw new IllegalStateException( - String.format("Unable to resolve field reference '%s' in definition '%s' in module '%s'", - name, - owningDefinition.getName(), - module.getShortName())); - } - return new InstanceModelFieldReference(obj, objInstance, position, definition, parent); - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelContainerSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelContainerSupport.java deleted file mode 100644 index 6be5a5ed2..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelContainerSupport.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.metaschema.impl; - -import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; -import gov.nist.secauto.metaschema.core.model.IChoiceInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelAssembly; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingDefinitionModelAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel.Choice; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel.ChoiceGroup; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyReference; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.FieldReference; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineField; - -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -class AssemblyModelContainerSupport - extends AbstractBindingModelContainerSupport - implements IContainerModelAssemblySupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute, - IChoiceInstance, - IChoiceGroupInstance> { - @NonNull - private final List modelInstances; - @NonNull - private final Map namedModelInstances; - @NonNull - private final Map fieldInstances; - @NonNull - private final Map assemblyInstances; - @NonNull - private final List choiceInstances; - @NonNull - private final Map choiceGroupInstances; - - @SuppressWarnings("PMD.ShortMethodName") - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - public static IContainerModelAssemblySupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute, - IChoiceInstance, - IChoiceGroupInstance> of( - @Nullable AssemblyModel binding, - @NonNull IBoundInstanceModelAssembly bindingInstance, - @NonNull IBindingDefinitionModelAssembly parent, - @NonNull INodeItemFactory nodeItemFactory) { - List instances; - return binding == null || (instances = binding.getInstances()) == null || instances.isEmpty() - ? IContainerModelAssemblySupport.empty() - : new AssemblyModelContainerSupport( - binding, - bindingInstance, - parent, - nodeItemFactory); - } - - /** - * Construct a new assembly model container. - * - * @param model - * the assembly model object bound to a Java class - * @param modelInstance - * the Metaschema module instance for the bound model object - * @param parent - * the assembly definition containing this container - * @param nodeItemFactory - * the node item factory used to generate child nodes - */ - @SuppressWarnings({ - "PMD.AvoidInstantiatingObjectsInLoops", - "PMD.UseConcurrentHashMap", - "PMD.PrematureDeclaration", - "PMD.NPathComplexity" }) - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - protected AssemblyModelContainerSupport( - @NonNull AssemblyModel model, - @NonNull IBoundInstanceModelAssembly modelInstance, - @NonNull IBindingDefinitionModelAssembly parent, - @NonNull INodeItemFactory nodeItemFactory) { - - // create temporary collections to store the child binding objects - final List modelInstances = new LinkedList<>(); - final Map namedModelInstances = new LinkedHashMap<>(); - final Map fieldInstances = new LinkedHashMap<>(); - final Map assemblyInstances = new LinkedHashMap<>(); - final List choiceInstances = new LinkedList<>(); - final Map choiceGroupInstances = new LinkedHashMap<>(); - - // create counters to track child positions - AtomicInteger assemblyReferencePosition = new AtomicInteger(); - AtomicInteger assemblyInlineDefinitionPosition = new AtomicInteger(); - AtomicInteger fieldReferencePosition = new AtomicInteger(); - AtomicInteger fieldInlineDefinitionPosition = new AtomicInteger(); - AtomicInteger choicePosition = new AtomicInteger(); - AtomicInteger choiceGroupPosition = new AtomicInteger(); - - IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull( - modelInstance.getDefinition() - .getChoiceGroupInstanceByName(BindingConstants.METASCHEMA_CHOICE_GROUP_GROUP_AS_NAME)); - ObjectUtils.notNull(model.getInstances()).forEach(obj -> { - assert obj != null; - - IBoundInstanceModelGroupedAssembly objInstance - = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj); - - if (obj instanceof AssemblyReference) { - IAssemblyInstanceAbsolute assembly = newInstance( - (AssemblyReference) obj, - objInstance, - assemblyReferencePosition.getAndIncrement(), - parent); - addInstance(assembly, modelInstances, namedModelInstances, assemblyInstances); - } else if (obj instanceof InlineDefineAssembly) { - IAssemblyInstanceAbsolute assembly = new InstanceModelAssemblyInline( - (InlineDefineAssembly) obj, - objInstance, - assemblyInlineDefinitionPosition.getAndIncrement(), - parent, - nodeItemFactory); - addInstance(assembly, modelInstances, namedModelInstances, assemblyInstances); - } else if (obj instanceof FieldReference) { - IFieldInstanceAbsolute field = newInstance( - (FieldReference) obj, - objInstance, - fieldReferencePosition.getAndIncrement(), - parent); - addInstance(field, modelInstances, namedModelInstances, fieldInstances); - } else if (obj instanceof InlineDefineField) { - IFieldInstanceAbsolute field = new InstanceModelFieldInline( - (InlineDefineField) obj, - objInstance, - fieldInlineDefinitionPosition.getAndIncrement(), - parent); - addInstance(field, modelInstances, namedModelInstances, fieldInstances); - } else if (obj instanceof AssemblyModel.Choice) { - IChoiceInstance choice = new InstanceModelChoice( - (Choice) obj, - objInstance, - choicePosition.getAndIncrement(), - parent, - nodeItemFactory); - addInstance(choice, modelInstances, choiceInstances); - } else if (obj instanceof AssemblyModel.ChoiceGroup) { - IChoiceGroupInstance choiceGroup = new InstanceModelChoiceGroup( - (ChoiceGroup) obj, - objInstance, - choiceGroupPosition.getAndIncrement(), - parent, - nodeItemFactory); - addInstance(choiceGroup, modelInstances, choiceGroupInstances); - } else { - throw new UnsupportedOperationException(String.format("Unknown model instance class: %s", obj.getClass())); - } - }); - - this.modelInstances = modelInstances.isEmpty() - ? CollectionUtil.emptyList() - : CollectionUtil.unmodifiableList(modelInstances); - this.namedModelInstances = namedModelInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(namedModelInstances); - this.fieldInstances = fieldInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(fieldInstances); - this.assemblyInstances = assemblyInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(assemblyInstances); - this.choiceInstances = choiceInstances.isEmpty() - ? CollectionUtil.emptyList() - : CollectionUtil.unmodifiableList(choiceInstances); - this.choiceGroupInstances = choiceGroupInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(choiceGroupInstances); - } - - @Override - public List getModelInstances() { - return modelInstances; - } - - @Override - public Map getNamedModelInstanceMap() { - return namedModelInstances; - } - - @Override - public Map getFieldInstanceMap() { - return fieldInstances; - } - - @Override - public Map getAssemblyInstanceMap() { - return assemblyInstances; - } - - @Override - public List getChoiceInstances() { - return choiceInstances; - } - - @Override - public Map getChoiceGroupInstanceMap() { - return choiceGroupInstances; - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelGenerator.java new file mode 100644 index 000000000..cfd7fbd7d --- /dev/null +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/AssemblyModelGenerator.java @@ -0,0 +1,158 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.databind.model.metaschema.impl; + +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; +import gov.nist.secauto.metaschema.core.model.DefaultAssemblyModelBuilder; +import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; +import gov.nist.secauto.metaschema.core.model.IChoiceInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport; +import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelAssembly; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingDefinitionModelAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyReference; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.FieldReference; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineField; + +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; + +/** + * Supports building the model contents of a Metaschema assembly definition. + *

    + * This class is not thread safe. + */ +@SuppressWarnings("PMD.UseConcurrentHashMap") +public final class AssemblyModelGenerator + extends AbstractAbsoluteModelGenerator< + IBindingDefinitionModelAssembly, + DefaultAssemblyModelBuilder< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute, + IChoiceInstance, + IChoiceGroupInstance>> { + // counters to track child positions + private int choicePosition; // 0 + private int choiceGroupPosition; // 0 + + /** + * Construct a new choice model container. + * + * @param binding + * the choice model object bound to a Java class + * @param bindingInstance + * the Metaschema module instance for the bound model object + * @param parent + * the assembly definition containing this container + * @param nodeItemFactory + * the node item factory used to generate child nodes + * @return the container + */ + @SuppressWarnings("PMD.ShortMethodName") + public static IContainerModelAssemblySupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute, + IChoiceInstance, + IChoiceGroupInstance> of( + @Nullable AssemblyModel binding, + @NonNull IBoundInstanceModelAssembly bindingInstance, + @NonNull IBindingDefinitionModelAssembly parent, + @NonNull INodeItemFactory nodeItemFactory) { + List instances; + return binding == null || (instances = binding.getInstances()) == null || instances.isEmpty() + ? IContainerModelAssemblySupport.empty() + : newInstance( + binding, + bindingInstance, + parent, + nodeItemFactory); + } + + private static IContainerModelAssemblySupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute, + IChoiceInstance, + IChoiceGroupInstance> newInstance( + @NonNull AssemblyModel binding, + @NonNull IBoundInstanceModelAssembly bindingInstance, + @NonNull IBindingDefinitionModelAssembly parent, + @NonNull INodeItemFactory nodeItemFactory) { + AssemblyModelGenerator generator = new AssemblyModelGenerator(parent, nodeItemFactory); + + // TODO: make "instances" a constant + IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull( + bindingInstance.getDefinition() + .getChoiceGroupInstanceByName(BindingConstants.METASCHEMA_CHOICE_GROUP_GROUP_AS_NAME)); + + ObjectUtils.notNull(binding.getInstances()).forEach(obj -> { + assert obj != null; + IBoundInstanceModelGroupedAssembly objInstance + = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj); + + if (obj instanceof AssemblyReference) { + generator.addAssemblyInstance((AssemblyReference) obj, objInstance); + } else if (obj instanceof InlineDefineAssembly) { + generator.addAssemblyInstance((InlineDefineAssembly) obj, objInstance); + } else if (obj instanceof FieldReference) { + generator.addFieldInstance((FieldReference) obj, objInstance); + } else if (obj instanceof InlineDefineField) { + generator.addFieldInstance((InlineDefineField) obj, objInstance); + } else if (obj instanceof AssemblyModel.Choice) { + generator.addChoiceInstance((AssemblyModel.Choice) obj, objInstance); + } else if (obj instanceof AssemblyModel.ChoiceGroup) { + generator.addChoiceGroupInstance((AssemblyModel.ChoiceGroup) obj, objInstance); + } else { + throw new UnsupportedOperationException(String.format("Unknown model instance class: %s", obj.getClass())); + } + }); + + return generator.getBuilder().buildAssembly(); + } + + private AssemblyModelGenerator( + @NonNull IBindingDefinitionModelAssembly parent, + @NonNull INodeItemFactory nodeItemFactory) { + super(parent, nodeItemFactory, new DefaultAssemblyModelBuilder<>()); + } + + private void addChoiceInstance( + @NonNull AssemblyModel.Choice obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + getBuilder().append(new InstanceModelChoice( + obj, + objInstance, + choicePosition++, + getParent(), + getNodeItemFactory())); + } + + private void addChoiceGroupInstance( + @NonNull AssemblyModel.ChoiceGroup obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + getBuilder().append(new InstanceModelChoiceGroup( + obj, + objInstance, + choiceGroupPosition++, + getParent(), + getNodeItemFactory())); + } +} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelContainerSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelContainerSupport.java deleted file mode 100644 index 0faac25c7..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelContainerSupport.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.metaschema.impl; - -import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; -import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceGrouped; -import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFieldDefinition; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceGrouped; -import gov.nist.secauto.metaschema.core.model.IModule; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceGrouped; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -class ChoiceGroupModelContainerSupport - implements IContainerModelSupport< - INamedModelInstanceGrouped, - INamedModelInstanceGrouped, - IFieldInstanceGrouped, - IAssemblyInstanceGrouped> { - @NonNull - private final Map namedModelInstances; - @NonNull - private final Map fieldInstances; - @NonNull - private final Map assemblyInstances; - - @SuppressWarnings("PMD.ShortMethodName") - public static IContainerModelSupport< - INamedModelInstanceGrouped, - INamedModelInstanceGrouped, - IFieldInstanceGrouped, - IAssemblyInstanceGrouped> of( - @Nullable AssemblyModel.ChoiceGroup binding, - @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, - @NonNull IChoiceGroupInstance parent, - @NonNull INodeItemFactory nodeItemFactory) { - List instances; - return binding == null || (instances = binding.getChoices()) == null || instances.isEmpty() - ? IContainerModelSupport.empty() - : new ChoiceGroupModelContainerSupport( - binding, - bindingInstance, - parent, - nodeItemFactory); - } - - /** - * Construct a new assembly model container. - * - * @param binding - * the choice model object bound to a Java class - * @param bindingInstance - * the Metaschema module instance for the bound model object - * @param parent - * the assembly definition containing this container - * @param nodeItemFactory - * the node item factory used to generate child nodes - */ - @SuppressWarnings({ "PMD.AvoidInstantiatingObjectsInLoops", "PMD.UseConcurrentHashMap", "PMD.PrematureDeclaration" }) - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - public ChoiceGroupModelContainerSupport( - @NonNull AssemblyModel.ChoiceGroup binding, - @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, - @NonNull IChoiceGroupInstance parent, - @NonNull INodeItemFactory nodeItemFactory) { - - // create temporary collections to store the child binding objects - final Map namedModelInstances = new LinkedHashMap<>(); - final Map fieldInstances = new LinkedHashMap<>(); - final Map assemblyInstances = new LinkedHashMap<>(); - - // create counters to track child positions - int assemblyReferencePosition = 0; - int assemblyInlineDefinitionPosition = 0; - int fieldReferencePosition = 0; - int fieldInlineDefinitionPosition = 0; - - // TODO: make "instances" a constant - IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull( - bindingInstance.getDefinition().getChoiceGroupInstanceByName("choices")); - for (Object obj : ObjectUtils.notNull(binding.getChoices())) { - assert obj != null; - - IBoundInstanceModelGroupedAssembly objInstance - = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj); - - if (obj instanceof AssemblyModel.ChoiceGroup.Assembly) { - IAssemblyInstanceGrouped assembly = newInstance( - (AssemblyModel.ChoiceGroup.Assembly) obj, - objInstance, - assemblyReferencePosition++, - parent); - addInstance(assembly, namedModelInstances, assemblyInstances); - } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineAssembly) { - IAssemblyInstanceGrouped assembly = new InstanceModelGroupedAssemblyInline( - (AssemblyModel.ChoiceGroup.DefineAssembly) obj, - objInstance, - assemblyInlineDefinitionPosition++, - parent, - nodeItemFactory); - addInstance(assembly, namedModelInstances, assemblyInstances); - } else if (obj instanceof AssemblyModel.ChoiceGroup.Field) { - IFieldInstanceGrouped field = newInstance( - (AssemblyModel.ChoiceGroup.Field) obj, - objInstance, - fieldReferencePosition++, - parent); - addInstance(field, namedModelInstances, fieldInstances); - } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineField) { - IFieldInstanceGrouped field = new InstanceModelGroupedFieldInline( - (AssemblyModel.ChoiceGroup.DefineField) obj, - objInstance, - fieldInlineDefinitionPosition++, - parent); - addInstance(field, namedModelInstances, fieldInstances); - } else { - throw new UnsupportedOperationException( - String.format("Unknown choice group model instance class: %s", obj.getClass())); - } - } - - this.namedModelInstances = namedModelInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(namedModelInstances); - this.fieldInstances = fieldInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(fieldInstances); - this.assemblyInstances = assemblyInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(assemblyInstances); - } - - protected static void addInstance( - @NonNull IAssemblyInstanceGrouped assembly, - @NonNull Map namedModelInstances, - @NonNull Map assemblyInstances) { - IEnhancedQName effectiveName = assembly.getQName(); - namedModelInstances.put(effectiveName, assembly); - assemblyInstances.put(effectiveName, assembly); - } - - protected static void addInstance( - @NonNull IFieldInstanceGrouped field, - @NonNull Map namedModelInstances, - @NonNull Map fieldInstances) { - IEnhancedQName effectiveName = field.getQName(); - namedModelInstances.put(effectiveName, field); - fieldInstances.put(effectiveName, field); - } - - @NonNull - protected static IAssemblyInstanceGrouped newInstance( - @NonNull AssemblyModel.ChoiceGroup.Assembly obj, - @NonNull IBoundInstanceModelGroupedAssembly objInstance, - int position, - @NonNull IChoiceGroupInstance parent) { - IAssemblyDefinition owningDefinition = parent.getOwningDefinition(); - IModule module = owningDefinition.getContainingModule(); - - IEnhancedQName name = parent.getContainingModule().getModuleStaticContext() - .parseModelName(ObjectUtils.requireNonNull(obj.getRef())); - IAssemblyDefinition definition = module.getScopedAssemblyDefinitionByName(name); - - if (definition == null) { - throw new IllegalStateException( - String.format("Unable to resolve assembly reference '%s' in definition '%s' in module '%s'", - name, - owningDefinition.getName(), - module.getShortName())); - } - return new InstanceModelGroupedAssemblyReference(obj, objInstance, position, definition, parent); - } - - @NonNull - protected static IFieldInstanceGrouped newInstance( - @NonNull AssemblyModel.ChoiceGroup.Field obj, - @NonNull IBoundInstanceModelGroupedAssembly objInstance, - int position, - @NonNull IChoiceGroupInstance parent) { - IAssemblyDefinition owningDefinition = parent.getOwningDefinition(); - IModule module = owningDefinition.getContainingModule(); - - IEnhancedQName name = parent.getContainingModule().getModuleStaticContext() - .parseModelName(ObjectUtils.requireNonNull(obj.getRef())); - IFieldDefinition definition = module.getScopedFieldDefinitionByName(name); - if (definition == null) { - throw new IllegalStateException( - String.format("Unable to resolve field reference '%s' in definition '%s' in module '%s'", - name, - owningDefinition.getName(), - module.getShortName())); - } - return new InstanceModelGroupedFieldReference(obj, objInstance, position, definition, parent); - } - - @SuppressWarnings("null") - @Override - public Collection getModelInstances() { - return namedModelInstances.values(); - } - - @Override - public Map getNamedModelInstanceMap() { - return namedModelInstances; - } - - @Override - public Map getFieldInstanceMap() { - return fieldInstances; - } - - @Override - public Map getAssemblyInstanceMap() { - return assemblyInstances; - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelGenerator.java new file mode 100644 index 000000000..98463f6cd --- /dev/null +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceGroupModelGenerator.java @@ -0,0 +1,216 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.databind.model.metaschema.impl; + +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; +import gov.nist.secauto.metaschema.core.model.DefaultChoiceGroupModelBuilder; +import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; +import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceGrouped; +import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; +import gov.nist.secauto.metaschema.core.model.IFieldDefinition; +import gov.nist.secauto.metaschema.core.model.IFieldInstanceGrouped; +import gov.nist.secauto.metaschema.core.model.IModule; +import gov.nist.secauto.metaschema.core.model.INamedModelInstanceGrouped; +import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel; + +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; + +/** + * Generates a model container for a choice group. + *

    + * This method isn't thread safe. + */ +public final class ChoiceGroupModelGenerator + extends DefaultChoiceGroupModelBuilder< + INamedModelInstanceGrouped, + IFieldInstanceGrouped, + IAssemblyInstanceGrouped> { + @NonNull + private final IChoiceGroupInstance parent; + @NonNull + private final INodeItemFactory nodeItemFactory; + + // counters to track child positions + private int assemblyReferencePosition; // 0 + private int assemblyInlineDefinitionPosition; // 0 + private int fieldReferencePosition; // 0 + private int fieldInlineDefinitionPosition; // 0 + + /** + * Construct a new assembly model container. + * + * @param binding + * the choice group model object bound to a Java class + * @param bindingInstance + * the Metaschema binding instance + * @param parent + * the choice group owning this container + * @param nodeItemFactory + * the node item factory used to generate child nodes + * @return the container + */ + @SuppressWarnings("PMD.ShortMethodName") + public static IContainerModelSupport< + INamedModelInstanceGrouped, + INamedModelInstanceGrouped, + IFieldInstanceGrouped, + IAssemblyInstanceGrouped> of( + @Nullable AssemblyModel.ChoiceGroup binding, + @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, + @NonNull IChoiceGroupInstance parent, + @NonNull INodeItemFactory nodeItemFactory) { + List instances; + return binding == null || (instances = binding.getChoices()) == null || instances.isEmpty() + ? IContainerModelSupport.empty() + : newInstance( + binding, + bindingInstance, + parent, + nodeItemFactory); + } + + @NonNull + private static IContainerModelSupport< + INamedModelInstanceGrouped, + INamedModelInstanceGrouped, + IFieldInstanceGrouped, + IAssemblyInstanceGrouped> newInstance( + @NonNull AssemblyModel.ChoiceGroup binding, + @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, + @NonNull IChoiceGroupInstance parent, + @NonNull INodeItemFactory nodeItemFactory) { + + ChoiceGroupModelGenerator generator = new ChoiceGroupModelGenerator(parent, nodeItemFactory); + + // TODO: make "instances" a constant + IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull( + bindingInstance.getDefinition().getChoiceGroupInstanceByName("choices")); + for (Object obj : ObjectUtils.notNull(binding.getChoices())) { + assert obj != null; + + IBoundInstanceModelGroupedAssembly objInstance + = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj); + + if (obj instanceof AssemblyModel.ChoiceGroup.Assembly) { + generator.addAssemblyInstance( + (AssemblyModel.ChoiceGroup.Assembly) obj, + objInstance); + } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineAssembly) { + generator.addAssemblyInstance( + (AssemblyModel.ChoiceGroup.DefineAssembly) obj, + objInstance); + } else if (obj instanceof AssemblyModel.ChoiceGroup.Field) { + generator.addFieldInstance( + (AssemblyModel.ChoiceGroup.Field) obj, + objInstance); + } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineField) { + generator.addFieldInstance( + (AssemblyModel.ChoiceGroup.DefineField) obj, + objInstance); + } else { + throw new UnsupportedOperationException( + String.format("Unknown choice group model instance class: %s", obj.getClass())); + } + } + + return generator.buildChoiceGroup(); + } + + private ChoiceGroupModelGenerator( + @NonNull IChoiceGroupInstance parent, + @NonNull INodeItemFactory nodeItemFactory) { + this.parent = parent; + this.nodeItemFactory = nodeItemFactory; + } + + @NonNull + private IChoiceGroupInstance getParent() { + return parent; + } + + @NonNull + private INodeItemFactory getNodeItemFactory() { + return nodeItemFactory; + } + + private void addAssemblyInstance( + @NonNull AssemblyModel.ChoiceGroup.Assembly obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + IAssemblyDefinition owningDefinition = parent.getOwningDefinition(); + IModule module = owningDefinition.getContainingModule(); + + IEnhancedQName name = parent.getContainingModule().getModuleStaticContext() + .parseModelName(ObjectUtils.requireNonNull(obj.getRef())); + IAssemblyDefinition definition = module.getScopedAssemblyDefinitionByName(name); + + if (definition == null) { + throw new IllegalStateException( + String.format("Unable to resolve assembly reference '%s' in definition '%s' in module '%s'", + name, + owningDefinition.getName(), + module.getShortName())); + } + append(new InstanceModelGroupedAssemblyReference( + obj, + objInstance, + assemblyReferencePosition++, + definition, + getParent())); + } + + private void addAssemblyInstance( + @NonNull AssemblyModel.ChoiceGroup.DefineAssembly obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + append(new InstanceModelGroupedAssemblyInline( + obj, + objInstance, + assemblyInlineDefinitionPosition++, + getParent(), + getNodeItemFactory())); + } + + private void addFieldInstance( + @NonNull AssemblyModel.ChoiceGroup.Field obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + IAssemblyDefinition owningDefinition = parent.getOwningDefinition(); + IModule module = owningDefinition.getContainingModule(); + + IEnhancedQName name = parent.getContainingModule().getModuleStaticContext() + .parseModelName(ObjectUtils.requireNonNull(obj.getRef())); + IFieldDefinition definition = module.getScopedFieldDefinitionByName(name); + if (definition == null) { + throw new IllegalStateException( + String.format("Unable to resolve field reference '%s' in definition '%s' in module '%s'", + name, + owningDefinition.getName(), + module.getShortName())); + } + append(new InstanceModelGroupedFieldReference( + obj, + objInstance, + fieldReferencePosition++, + definition, + getParent())); + } + + private void addFieldInstance( + @NonNull AssemblyModel.ChoiceGroup.DefineField obj, + @NonNull IBoundInstanceModelGroupedAssembly objInstance) { + append(new InstanceModelGroupedFieldInline( + obj, + objInstance, + fieldInlineDefinitionPosition++, + getParent())); + } +} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelContainerSupport.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelContainerSupport.java deleted file mode 100644 index bb548605e..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelContainerSupport.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.metaschema.impl; - -import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IChoiceInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; -import gov.nist.secauto.metaschema.core.util.CollectionUtil; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; -import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel.Choice; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyReference; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.FieldReference; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineAssembly; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineField; - -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -class ChoiceModelContainerSupport - extends AbstractBindingModelContainerSupport { - @NonNull - private final List modelInstances; - @NonNull - private final Map namedModelInstances; - @NonNull - private final Map fieldInstances; - @NonNull - private final Map assemblyInstances; - - @SuppressWarnings("PMD.ShortMethodName") - public static IContainerModelSupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute> of( - @Nullable Choice binding, - @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, - @NonNull IChoiceInstance parent, - @NonNull INodeItemFactory nodeItemFactory) { - List instances; - return binding == null || (instances = binding.getChoices()) == null || instances.isEmpty() - ? IContainerModelSupport.empty() - : new ChoiceModelContainerSupport( - binding, - bindingInstance, - parent, - nodeItemFactory); - } - - /** - * Construct a new assembly model container. - * - * @param binding - * the choice model object bound to a Java class - * @param bindingInstance - * the Metaschema module instance for the bound model object - * @param parent - * the assembly definition containing this container - * @param nodeItemFactory - * the node item factory used to generate child nodes - */ - @SuppressWarnings({ "PMD.AvoidInstantiatingObjectsInLoops", "PMD.UseConcurrentHashMap", "PMD.PrematureDeclaration" }) - @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields") - public ChoiceModelContainerSupport( - @NonNull Choice binding, - @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, - @NonNull IChoiceInstance parent, - @NonNull INodeItemFactory nodeItemFactory) { - - // create temporary collections to store the child binding objects - final List modelInstances = new LinkedList<>(); - final Map namedModelInstances = new LinkedHashMap<>(); - final Map fieldInstances = new LinkedHashMap<>(); - final Map assemblyInstances = new LinkedHashMap<>(); - - // create counters to track child positions - AtomicInteger assemblyReferencePosition = new AtomicInteger(); - AtomicInteger assemblyInlineDefinitionPosition = new AtomicInteger(); - AtomicInteger fieldReferencePosition = new AtomicInteger(); - AtomicInteger fieldInlineDefinitionPosition = new AtomicInteger(); - - // TODO: make "instances" a constant - IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull( - bindingInstance.getDefinition().getChoiceGroupInstanceByName("choices")); - - ObjectUtils.notNull(binding.getChoices()).forEach(obj -> { - assert obj != null; - IBoundInstanceModelGroupedAssembly objInstance - = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj); - - if (obj instanceof AssemblyReference) { - addInstance( - newInstance( - (AssemblyReference) obj, - objInstance, - assemblyReferencePosition.getAndIncrement(), - parent), - modelInstances, - namedModelInstances, - assemblyInstances); - } else if (obj instanceof InlineDefineAssembly) { - IAssemblyInstanceAbsolute assembly = new InstanceModelAssemblyInline( - (InlineDefineAssembly) obj, - objInstance, - assemblyInlineDefinitionPosition.getAndIncrement(), - parent, - nodeItemFactory); - addInstance(assembly, modelInstances, namedModelInstances, assemblyInstances); - } else if (obj instanceof FieldReference) { - IFieldInstanceAbsolute field = newInstance( - (FieldReference) obj, - objInstance, - fieldReferencePosition.getAndIncrement(), - parent); - addInstance(field, modelInstances, namedModelInstances, fieldInstances); - } else if (obj instanceof InlineDefineField) { - IFieldInstanceAbsolute field = new InstanceModelFieldInline( - (InlineDefineField) obj, - objInstance, - fieldInlineDefinitionPosition.getAndIncrement(), - parent); - addInstance(field, modelInstances, namedModelInstances, fieldInstances); - } else { - throw new UnsupportedOperationException(String.format("Unknown model instance class: %s", obj.getClass())); - } - }); - - this.modelInstances = modelInstances.isEmpty() - ? CollectionUtil.emptyList() - : CollectionUtil.unmodifiableList(modelInstances); - this.namedModelInstances = namedModelInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(namedModelInstances); - this.fieldInstances = fieldInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(fieldInstances); - this.assemblyInstances = assemblyInstances.isEmpty() - ? CollectionUtil.emptyMap() - : CollectionUtil.unmodifiableMap(assemblyInstances); - } - - @Override - public List getModelInstances() { - return modelInstances; - } - - @Override - public Map getNamedModelInstanceMap() { - return namedModelInstances; - } - - @Override - public Map getFieldInstanceMap() { - return fieldInstances; - } - - @Override - public Map getAssemblyInstanceMap() { - return assemblyInstances; - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelGenerator.java new file mode 100644 index 000000000..70dd58999 --- /dev/null +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/ChoiceModelGenerator.java @@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.databind.model.metaschema.impl; + +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory; +import gov.nist.secauto.metaschema.core.model.DefaultChoiceModelBuilder; +import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IChoiceInstance; +import gov.nist.secauto.metaschema.core.model.IContainerModelAbsolute; +import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; +import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; +import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup; +import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyReference; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.FieldReference; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineAssembly; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineField; + +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; + +/** + * Supports building the model contents of a Metaschema choice instance. + *

    + * This class is not thread safe. + */ +public final class ChoiceModelGenerator + extends AbstractAbsoluteModelGenerator< + IContainerModelAbsolute, + DefaultChoiceModelBuilder< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute>> { + + /** + * Construct a new choice model container. + * + * @param binding + * the choice model object bound to a Java class + * @param bindingInstance + * the Metaschema module instance for the bound model object + * @param parent + * the assembly definition containing this container + * @param nodeItemFactory + * the node item factory used to generate child nodes + * @return the container + */ + @SuppressWarnings("PMD.ShortMethodName") + public static IContainerModelSupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute> of( + @Nullable AssemblyModel.Choice binding, + @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, + @NonNull IChoiceInstance parent, + @NonNull INodeItemFactory nodeItemFactory) { + List instances; + return binding == null || (instances = binding.getChoices()) == null || instances.isEmpty() + ? IContainerModelSupport.empty() + : newInstance( + binding, + bindingInstance, + parent, + nodeItemFactory); + } + + private static IContainerModelSupport< + IModelInstanceAbsolute, + INamedModelInstanceAbsolute, + IFieldInstanceAbsolute, + IAssemblyInstanceAbsolute> newInstance( + @NonNull AssemblyModel.Choice binding, + @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, + @NonNull IChoiceInstance parent, + @NonNull INodeItemFactory nodeItemFactory) { + ChoiceModelGenerator generator = new ChoiceModelGenerator(parent, nodeItemFactory); + + // TODO: make "instances" a constant + IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull( + bindingInstance.getDefinition().getChoiceGroupInstanceByName("choices")); + + ObjectUtils.notNull(binding.getChoices()).forEach(obj -> { + assert obj != null; + IBoundInstanceModelGroupedAssembly objInstance + = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj); + + if (obj instanceof AssemblyReference) { + generator.addAssemblyInstance((AssemblyReference) obj, objInstance); + } else if (obj instanceof InlineDefineAssembly) { + generator.addAssemblyInstance((InlineDefineAssembly) obj, objInstance); + } else if (obj instanceof FieldReference) { + generator.addFieldInstance((FieldReference) obj, objInstance); + } else if (obj instanceof InlineDefineField) { + generator.addFieldInstance((InlineDefineField) obj, objInstance); + } else { + throw new UnsupportedOperationException(String.format("Unknown model instance class: %s", obj.getClass())); + } + }); + + return generator.getBuilder().buildChoice(); + } + + private ChoiceModelGenerator( + @NonNull IContainerModelAbsolute parent, + @NonNull INodeItemFactory nodeItemFactory) { + super( + parent, + nodeItemFactory, + new DefaultChoiceModelBuilder<>()); + } +} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/DefinitionAssemblyGlobal.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/DefinitionAssemblyGlobal.java index 6b436804c..df0dccbda 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/DefinitionAssemblyGlobal.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/DefinitionAssemblyGlobal.java @@ -102,7 +102,7 @@ public DefinitionAssemblyGlobal( this, jsonKey == null ? null : jsonKey.getFlagRef()); })); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelContainerSupport.of( + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelGenerator.of( binding.getModel(), ObjectUtils.requireNonNull(bindingInstance.getDefinition() .getAssemblyInstanceByName(XmlModuleConstants.MODEL_QNAME)), @@ -123,7 +123,7 @@ public DefinitionAssemblyGlobal( } @NonNull - protected METASCHEMA.DefineAssembly getBinding() { + private METASCHEMA.DefineAssembly getBinding() { return binding; } diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModel.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModel.java deleted file mode 100644 index 04cc5bd7d..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModel.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.metaschema.impl; - -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IContainerModelAbsolute; -import gov.nist.secauto.metaschema.core.model.IContainerModelSupport; -import gov.nist.secauto.metaschema.core.model.IFeatureContainerModel; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; - -import java.util.Collection; - -import edu.umd.cs.findbugs.annotations.NonNull; - -public interface IFeatureBindingContainerModel - extends IContainerModelAbsolute, IFeatureContainerModel< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute> { - @Override - @NonNull - IContainerModelSupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute> getModelContainer(); - - @Override - default Collection getModelInstances() { - return getModelContainer().getModelInstances(); - } - - @Override - default INamedModelInstanceAbsolute getNamedModelInstanceByName(IEnhancedQName name) { - return getModelContainer().getNamedModelInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getNamedModelInstances() { - return getModelContainer().getNamedModelInstanceMap().values(); - } - - @Override - default IFieldInstanceAbsolute getFieldInstanceByName(IEnhancedQName name) { - return getModelContainer().getFieldInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getFieldInstances() { - return getModelContainer().getFieldInstanceMap().values(); - } - - @Override - default IAssemblyInstanceAbsolute getAssemblyInstanceByName(IEnhancedQName name) { - return getModelContainer().getAssemblyInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getAssemblyInstances() { - return getModelContainer().getAssemblyInstanceMap().values(); - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModelAssembly.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModelAssembly.java deleted file mode 100644 index f4d8e6720..000000000 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/IFeatureBindingContainerModelAssembly.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SPDX-FileCopyrightText: none - * SPDX-License-Identifier: CC0-1.0 - */ - -package gov.nist.secauto.metaschema.databind.model.metaschema.impl; - -import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance; -import gov.nist.secauto.metaschema.core.model.IChoiceInstance; -import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport; -import gov.nist.secauto.metaschema.core.model.IFeatureContainerModelAssembly; -import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute; -import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import edu.umd.cs.findbugs.annotations.NonNull; - -public interface IFeatureBindingContainerModelAssembly - extends IFeatureBindingContainerModel, - IFeatureContainerModelAssembly< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute, - IChoiceInstance, - IChoiceGroupInstance> { - @Override - @NonNull - IContainerModelAssemblySupport< - IModelInstanceAbsolute, - INamedModelInstanceAbsolute, - IFieldInstanceAbsolute, - IAssemblyInstanceAbsolute, - IChoiceInstance, - IChoiceGroupInstance> getModelContainer(); - - @Override - default Collection getModelInstances() { - return getModelContainer().getModelInstances(); - } - - @Override - default INamedModelInstanceAbsolute getNamedModelInstanceByName(IEnhancedQName name) { - return getModelContainer().getNamedModelInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getNamedModelInstances() { - return getModelContainer().getNamedModelInstanceMap().values(); - } - - @Override - default IFieldInstanceAbsolute getFieldInstanceByName(IEnhancedQName name) { - return getModelContainer().getFieldInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getFieldInstances() { - return getModelContainer().getFieldInstanceMap().values(); - } - - @Override - default IAssemblyInstanceAbsolute getAssemblyInstanceByName(IEnhancedQName name) { - return getModelContainer().getAssemblyInstanceMap().get(name); - } - - @SuppressWarnings("null") - @Override - default Collection getAssemblyInstances() { - return getModelContainer().getAssemblyInstanceMap().values(); - } - - @Override - default List getChoiceInstances() { - return getModelContainer().getChoiceInstances(); - } - - @Override - default IChoiceGroupInstance getChoiceGroupInstanceByName(String name) { - return getModelContainer().getChoiceGroupInstanceMap().get(name); - } - - @Override - default Map getChoiceGroupInstances() { - return getModelContainer().getChoiceGroupInstanceMap(); - } -} diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyInline.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyInline.java index 770c0c278..8b7247414 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyInline.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyInline.java @@ -57,7 +57,7 @@ public class InstanceModelAssemblyInline IChoiceInstance, IChoiceGroupInstance> implements IAssemblyInstanceAbsolute, IBindingInstance, IBindingDefinitionModelAssembly, - IFeatureInstanceModelGroupAs, IFeatureBindingContainerModelAssembly { + IFeatureInstanceModelGroupAs { @NonNull private final InlineDefineAssembly binding; @NonNull @@ -116,7 +116,7 @@ public InstanceModelAssemblyInline( this, jsonKey == null ? null : jsonKey.getFlagRef()); })); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelContainerSupport.of( + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelGenerator.of( binding.getModel(), ObjectUtils.requireNonNull(bindingInstance.getDefinition() .getAssemblyInstanceByName(XmlModuleConstants.MODEL_QNAME)), diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyReference.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyReference.java index a91f33a36..b07133235 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyReference.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelAssemblyReference.java @@ -54,7 +54,7 @@ public class InstanceModelAssemblyReference * @param binding * the assembly reference instance object bound to a Java class * @param bindingInstance - * the Metaschema module instance for the bound object + * the Metaschema instance for the bound object * @param position * the zero-based position of this bound object relative to its bound * object siblings diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoice.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoice.java index 1ff69d4c9..08ce71696 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoice.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoice.java @@ -20,7 +20,7 @@ import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingDefinitionModelAssembly; import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingInstance; import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingMetaschemaModule; -import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel.Choice; +import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel; import edu.umd.cs.findbugs.annotations.NonNull; import nl.talsmasoftware.lazy4j.Lazy; @@ -43,13 +43,13 @@ public class InstanceModelChoice private final Lazy boundNodeItem; public InstanceModelChoice( - @NonNull Choice binding, + @NonNull AssemblyModel.Choice binding, @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, int position, @NonNull IBindingDefinitionModelAssembly parent, @NonNull INodeItemFactory nodeItemFactory) { super(parent); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> ChoiceModelContainerSupport.of( + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> ChoiceModelGenerator.of( binding, bindingInstance, this, diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoiceGroup.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoiceGroup.java index db00e7569..abd76cf08 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoiceGroup.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelChoiceGroup.java @@ -57,7 +57,7 @@ public InstanceModelChoiceGroup( super(parent); this.binding = binding; this.groupAs = ModelSupport.groupAs(binding.getGroupAs(), parent.getContainingModule()); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> ChoiceGroupModelContainerSupport.of( + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> ChoiceGroupModelGenerator.of( binding, bindingInstance, this, diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelFieldReference.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelFieldReference.java index b4fcaee84..f462689ba 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelFieldReference.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelFieldReference.java @@ -51,6 +51,21 @@ public class InstanceModelFieldReference @Nullable private final Object defaultValue; + /** + * Construct a new field reference. + * + * @param binding + * the field reference instance object bound to a Java class + * @param bindingInstance + * the Metaschema instance for the bound object + * @param position + * the zero-based position of this bound object relative to its bound + * object siblings + * @param definition + * the referenced global field definition + * @param parent + * the assembly definition containing this binding + */ public InstanceModelFieldReference( @NonNull FieldReference binding, @NonNull IBoundInstanceModelGroupedAssembly bindingInstance, diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelGroupedAssemblyInline.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelGroupedAssemblyInline.java index adcbff52c..1746e0c37 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelGroupedAssemblyInline.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/metaschema/impl/InstanceModelGroupedAssemblyInline.java @@ -52,8 +52,7 @@ public class InstanceModelGroupedAssemblyInline IAssemblyInstanceAbsolute, IChoiceInstance, IChoiceGroupInstance> - implements IAssemblyInstanceGrouped, IBindingInstance, IBindingDefinitionModelAssembly, - IFeatureBindingContainerModelAssembly { + implements IAssemblyInstanceGrouped, IBindingInstance, IBindingDefinitionModelAssembly { @NonNull private final AssemblyModel.ChoiceGroup.DefineAssembly binding; @NonNull @@ -87,7 +86,7 @@ public InstanceModelGroupedAssemblyInline( bindingInstance, this, getParentContainer().getJsonKeyFlagInstanceName()))); - this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelContainerSupport.of( + this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelGenerator.of( binding.getModel(), ObjectUtils.requireNonNull(bindingInstance.getDefinition() .getAssemblyInstanceByName(XmlModuleConstants.MODEL_QNAME)),