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