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