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.xml.XmlModuleConstants;
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.metaschema.IBindingDefinitionModelAssembly;
32  import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingInstance;
33  import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingMetaschemaModule;
34  import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyConstraints;
35  import gov.nist.secauto.metaschema.databind.model.metaschema.binding.InlineDefineAssembly;
36  import gov.nist.secauto.metaschema.databind.model.metaschema.binding.JsonKey;
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.requireNonNull(bindingInstance.getDefinition()
122             .getAssemblyInstanceByName(XmlModuleConstants.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             parent.getOwningDefinition().getContainingModule().getSource());
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 ObjectUtils.notNull(boundNodeItem.get());
162   }
163 
164   @Override
165   public IContainerFlagSupport<IFlagInstance> getFlagContainer() {
166     return ObjectUtils.notNull(flagContainer.get());
167   }
168 
169   @Override
170   public IContainerModelAssemblySupport<
171       IModelInstanceAbsolute,
172       INamedModelInstanceAbsolute,
173       IFieldInstanceAbsolute,
174       IAssemblyInstanceAbsolute,
175       IChoiceInstance,
176       IChoiceGroupInstance> getModelContainer() {
177     return ObjectUtils.notNull(modelContainer.get());
178   }
179 
180   @Override
181   public IModelConstrained getConstraintSupport() {
182     return ObjectUtils.notNull(modelConstraints.get());
183   }
184 
185   // ---------------------------------------
186   // - Start binding driven code - CPD-OFF -
187   // ---------------------------------------
188 
189   @Override
190   public String getName() {
191     return ObjectUtils.notNull(getBinding().getName());
192   }
193 
194   @Override
195   public Integer getIndex() {
196     return ModelSupport.index(getBinding().getIndex());
197   }
198 
199   @Override
200   public String getFormalName() {
201     return getBinding().getFormalName();
202   }
203 
204   @Override
205   public MarkupLine getDescription() {
206     return getBinding().getDescription();
207   }
208 
209   @Override
210   public MarkupMultiline getRemarks() {
211     return ModelSupport.remarks(getBinding().getRemarks());
212   }
213 
214   @Override
215   public int getMinOccurs() {
216     BigInteger min = getBinding().getMinOccurs();
217     return min == null ? DEFAULT_GROUP_AS_MIN_OCCURS : min.intValueExact();
218   }
219 
220   @Override
221   public int getMaxOccurs() {
222     String max = getBinding().getMaxOccurs();
223     return max == null ? DEFAULT_GROUP_AS_MAX_OCCURS : ModelSupport.maxOccurs(max);
224   }
225 }