1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind.model.metaschema.impl;
7   
8   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
9   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
10  import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem;
11  import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory;
12  import gov.nist.secauto.metaschema.core.model.AbstractInlineAssemblyDefinition;
13  import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
14  import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceAbsolute;
15  import gov.nist.secauto.metaschema.core.model.IAttributable;
16  import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance;
17  import gov.nist.secauto.metaschema.core.model.IChoiceInstance;
18  import gov.nist.secauto.metaschema.core.model.IContainerFlagSupport;
19  import gov.nist.secauto.metaschema.core.model.IContainerModelAbsolute;
20  import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport;
21  import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute;
22  import gov.nist.secauto.metaschema.core.model.IFlagInstance;
23  import gov.nist.secauto.metaschema.core.model.IModelInstanceAbsolute;
24  import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute;
25  import gov.nist.secauto.metaschema.core.model.constraint.AssemblyConstraintSet;
26  import gov.nist.secauto.metaschema.core.model.constraint.IModelConstrained;
27  import gov.nist.secauto.metaschema.core.model.constraint.ISource;
28  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
29  import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly;
30  import gov.nist.secauto.metaschema.databind.model.IGroupAs;
31  import gov.nist.secauto.metaschema.databind.model.binding.metaschema.AssemblyConstraints;
32  import gov.nist.secauto.metaschema.databind.model.binding.metaschema.InlineDefineAssembly;
33  import gov.nist.secauto.metaschema.databind.model.binding.metaschema.JsonKey;
34  import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingDefinitionModelAssembly;
35  import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingInstance;
36  import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingMetaschemaModule;
37  
38  import java.math.BigInteger;
39  import java.util.Map;
40  import java.util.Set;
41  
42  import edu.umd.cs.findbugs.annotations.NonNull;
43  import nl.talsmasoftware.lazy4j.Lazy;
44  
45  public class InstanceModelAssemblyInline
46      extends AbstractInlineAssemblyDefinition<
47          IContainerModelAbsolute,
48          IAssemblyDefinition,
49          IAssemblyInstanceAbsolute,
50          IBindingDefinitionModelAssembly,
51          IFlagInstance,
52          IModelInstanceAbsolute,
53          INamedModelInstanceAbsolute,
54          IFieldInstanceAbsolute,
55          IAssemblyInstanceAbsolute,
56          IChoiceInstance,
57          IChoiceGroupInstance>
58      implements IAssemblyInstanceAbsolute, IBindingInstance, IBindingDefinitionModelAssembly,
59      IFeatureInstanceModelGroupAs,
60      IFeatureBindingContainerModelAssembly {
61    @NonNull
62    private final InlineDefineAssembly binding;
63    @NonNull
64    private final Map<IAttributable.Key, Set<String>> properties;
65    @NonNull
66    private final IGroupAs groupAs;
67    @NonNull
68    private final Lazy<IAssemblyNodeItem> boundNodeItem;
69    @NonNull
70    private final Lazy<IContainerFlagSupport<IFlagInstance>> flagContainer;
71    @NonNull
72    private final Lazy<IContainerModelAssemblySupport<
73        IModelInstanceAbsolute,
74        INamedModelInstanceAbsolute,
75        IFieldInstanceAbsolute,
76        IAssemblyInstanceAbsolute,
77        IChoiceInstance,
78        IChoiceGroupInstance>> modelContainer;
79    @NonNull
80    private final Lazy<IModelConstrained> modelConstraints;
81  
82    /**
83     * Construct a new assembly instance that defines the assembly inline.
84     *
85     * @param binding
86     *          the assembly reference instance object bound to a Java class
87     * @param bindingInstance
88     *          the Metaschema module instance for the bound object
89     * @param position
90     *          the zero-based position of this bound object relative to its bound
91     *          object siblings
92     * @param parent
93     *          the assembly definition containing this binding
94     * @param nodeItemFactory
95     *          the node item factory used to generate child nodes
96     */
97    public InstanceModelAssemblyInline(
98        @NonNull InlineDefineAssembly binding,
99        @NonNull IBoundInstanceModelGroupedAssembly bindingInstance,
100       int position,
101       @NonNull IContainerModelAbsolute parent,
102       @NonNull INodeItemFactory nodeItemFactory) {
103     super(parent);
104     this.binding = binding;
105     this.properties = ModelSupport.parseProperties(ObjectUtils.requireNonNull(binding.getProps()));
106     this.groupAs = ModelSupport.groupAs(binding.getGroupAs(), parent.getOwningDefinition().getContainingModule());
107     this.boundNodeItem = ObjectUtils.notNull(
108         Lazy.lazy(() -> (IAssemblyNodeItem) ObjectUtils.notNull(getContainingDefinition().getSourceNodeItem())
109             .getModelItemsByName(bindingInstance.getXmlQName())
110             .get(position)));
111     this.flagContainer = ObjectUtils.notNull(Lazy.lazy(() -> {
112       JsonKey jsonKey = getBinding().getJsonKey();
113       return FlagContainerSupport.newFlagContainer(
114           binding.getFlags(),
115           bindingInstance,
116           this,
117           jsonKey == null ? null : jsonKey.getFlagRef());
118     }));
119     this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelContainerSupport.of(
120         binding.getModel(),
121         ObjectUtils
122             .requireNonNull(bindingInstance.getDefinition().getAssemblyInstanceByName(MODEL_QNAME)),
123         this,
124         nodeItemFactory)));
125     this.modelConstraints = ObjectUtils.notNull(Lazy.lazy(() -> {
126       IModelConstrained retval = new AssemblyConstraintSet();
127       AssemblyConstraints constraints = getBinding().getConstraint();
128       if (constraints != null) {
129         ConstraintBindingSupport.parse(
130             retval,
131             constraints,
132             ISource.modelSource(parent.getOwningDefinition().getContainingModule()));
133       }
134       return retval;
135     }));
136   }
137 
138   @NonNull
139   protected InlineDefineAssembly getBinding() {
140     getContainingDefinition();
141     return binding;
142   }
143 
144   @Override
145   public IBindingMetaschemaModule getContainingModule() {
146     return getContainingDefinition().getContainingModule();
147   }
148 
149   @Override
150   public Map<IAttributable.Key, Set<String>> getProperties() {
151     return properties;
152   }
153 
154   @Override
155   public IGroupAs getGroupAs() {
156     return groupAs;
157   }
158 
159   @Override
160   public IAssemblyNodeItem getSourceNodeItem() {
161     return boundNodeItem.get();
162   }
163 
164   @SuppressWarnings("null")
165   @Override
166   public IContainerFlagSupport<IFlagInstance> getFlagContainer() {
167     return flagContainer.get();
168   }
169 
170   @Override
171   public IContainerModelAssemblySupport<
172       IModelInstanceAbsolute,
173       INamedModelInstanceAbsolute,
174       IFieldInstanceAbsolute,
175       IAssemblyInstanceAbsolute,
176       IChoiceInstance,
177       IChoiceGroupInstance> getModelContainer() {
178     return ObjectUtils.notNull(modelContainer.get());
179   }
180 
181   @Override
182   public IModelConstrained getConstraintSupport() {
183     return ObjectUtils.notNull(modelConstraints.get());
184   }
185 
186   // ---------------------------------------
187   // - Start binding driven code - CPD-OFF -
188   // ---------------------------------------
189 
190   @Override
191   public String getName() {
192     return ObjectUtils.notNull(getBinding().getName());
193   }
194 
195   @Override
196   public Integer getIndex() {
197     return ModelSupport.index(getBinding().getIndex());
198   }
199 
200   @Override
201   public String getFormalName() {
202     return getBinding().getFormalName();
203   }
204 
205   @Override
206   public MarkupLine getDescription() {
207     return getBinding().getDescription();
208   }
209 
210   @Override
211   public MarkupMultiline getRemarks() {
212     return ModelSupport.remarks(getBinding().getRemarks());
213   }
214 
215   @Override
216   public int getMinOccurs() {
217     BigInteger min = getBinding().getMinOccurs();
218     return min == null ? DEFAULT_GROUP_AS_MIN_OCCURS : min.intValueExact();
219   }
220 
221   @Override
222   public int getMaxOccurs() {
223     String max = getBinding().getMaxOccurs();
224     return max == null ? DEFAULT_GROUP_AS_MAX_OCCURS : ModelSupport.maxOccurs(max);
225   }
226 }