View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.metaschema.core.model.xml; // NOPMD - intentional
28  
29  import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
30  import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
31  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupDataTypeProvider;
32  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
33  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
34  import gov.nist.secauto.metaschema.core.model.AbstractFieldInstance;
35  import gov.nist.secauto.metaschema.core.model.IFeatureFlagContainer;
36  import gov.nist.secauto.metaschema.core.model.IFeatureInlinedDefinition;
37  import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
38  import gov.nist.secauto.metaschema.core.model.IFieldInstance;
39  import gov.nist.secauto.metaschema.core.model.IFlagInstance;
40  import gov.nist.secauto.metaschema.core.model.IModelContainer;
41  import gov.nist.secauto.metaschema.core.model.IModule;
42  import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior;
43  import gov.nist.secauto.metaschema.core.model.MetaschemaModelConstants;
44  import gov.nist.secauto.metaschema.core.model.ModuleScopeEnum;
45  import gov.nist.secauto.metaschema.core.model.XmlGroupAsBehavior;
46  import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.ExternalModelSource;
47  import gov.nist.secauto.metaschema.core.model.constraint.IValueConstrained;
48  import gov.nist.secauto.metaschema.core.model.xml.xmlbeans.InlineFieldDefinitionType;
49  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
50  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
51  
52  import java.util.Collection;
53  import java.util.Collections;
54  import java.util.Map;
55  import java.util.Set;
56  
57  import javax.xml.namespace.QName;
58  
59  import edu.umd.cs.findbugs.annotations.NonNull;
60  import edu.umd.cs.findbugs.annotations.Nullable;
61  import nl.talsmasoftware.lazy4j.Lazy;
62  
63  class XmlInlineFieldDefinition
64      extends AbstractFieldInstance {
65    @NonNull
66    private final InlineFieldDefinitionType xmlField;
67    @NonNull
68    private final InternalFieldDefinition fieldDefinition;
69  
70    /**
71     * Constructs a new Metaschema field definition from an XML representation bound
72     * to Java objects.
73     *
74     * @param xmlField
75     *          the XML representation bound to Java objects
76     * @param parent
77     *          the parent container, either a choice or assembly
78     */
79    public XmlInlineFieldDefinition(
80        @NonNull InlineFieldDefinitionType xmlField,
81        @NonNull IModelContainer parent) {
82      super(parent);
83      this.xmlField = xmlField;
84      this.fieldDefinition = new InternalFieldDefinition(xmlField);
85    }
86  
87    @Override
88    public InternalFieldDefinition getDefinition() {
89      return fieldDefinition;
90    }
91  
92    @Override
93    public IModule getContainingModule() {
94      return getContainingDefinition().getContainingModule();
95    }
96  
97    // ----------------------------------------
98    // - Start annotation driven code - CPD-OFF
99    // ----------------------------------------
100 
101   /**
102    * Get the underlying XML model.
103    *
104    * @return the XML model
105    */
106   @NonNull
107   protected final InlineFieldDefinitionType getXmlField() {
108     return xmlField;
109   }
110 
111   @Override
112   public boolean isInXmlWrapped() {
113     boolean retval;
114     if (MarkupDataTypeProvider.MARKUP_MULTILINE.equals(getDefinition().getJavaTypeAdapter())) {
115       // default value
116       retval = MetaschemaModelConstants.DEFAULT_FIELD_IN_XML_WRAPPED;
117       if (getXmlField().isSetInXml()) {
118         retval = getXmlField().getInXml();
119       }
120     } else {
121       // All other data types get "wrapped"
122       retval = true;
123     }
124     return retval;
125   }
126 
127   @Override
128   public String getFormalName() {
129     return getXmlField().isSetFormalName() ? getXmlField().getFormalName() : null;
130   }
131 
132   @SuppressWarnings("null")
133   @Override
134   public MarkupLine getDescription() {
135     return getXmlField().isSetDescription() ? MarkupStringConverter.toMarkupString(getXmlField().getDescription())
136         : null;
137   }
138 
139   @Override
140   public Map<QName, Set<String>> getProperties() {
141     return ModelFactory.toProperties(CollectionUtil.listOrEmpty(getXmlField().getPropList()));
142   }
143 
144   @SuppressWarnings("null")
145   @Override
146   public String getName() {
147     return getXmlField().getName();
148   }
149 
150   @Override
151   public String getGroupAsName() {
152     return getXmlField().isSetGroupAs() ? getXmlField().getGroupAs().getName() : null;
153   }
154 
155   @Override
156   public int getMinOccurs() {
157     return XmlModelParser.getMinOccurs(getXmlField().getMinOccurs());
158   }
159 
160   @Override
161   public int getMaxOccurs() {
162     return XmlModelParser.getMaxOccurs(getXmlField().getMaxOccurs());
163   }
164 
165   @Override
166   public JsonGroupAsBehavior getJsonGroupAsBehavior() {
167     return XmlModelParser.getJsonGroupAsBehavior(getXmlField().getGroupAs());
168   }
169 
170   @Override
171   public XmlGroupAsBehavior getXmlGroupAsBehavior() {
172     return XmlModelParser.getXmlGroupAsBehavior(getXmlField().getGroupAs());
173   }
174 
175   @SuppressWarnings("null")
176   @Override
177   public MarkupMultiline getRemarks() {
178     return getXmlField().isSetRemarks() ? MarkupStringConverter.toMarkupString(getXmlField().getRemarks()) : null;
179   }
180 
181   // --------------------------------------
182   // - End annotation driven code - CPD-ON
183   // --------------------------------------
184 
185   @Override
186   public String getUseName() {
187     // an inline definition doesn't have a use name
188     return null;
189   }
190 
191   @Override
192   public Object getValue(@NonNull Object parentValue) {
193     // there is no value
194     return null;
195   }
196 
197   @SuppressWarnings("null")
198   @Override
199   public Collection<?> getItemValues(Object instanceValue) {
200     // there are no item values
201     return Collections.emptyList();
202   }
203 
204   /**
205    * The corresponding definition for the local flag instance.
206    */
207   private final class InternalFieldDefinition
208       implements IFieldDefinition,
209       IFeatureInlinedDefinition<IFieldInstance>,
210       IFeatureFlagContainer<IFlagInstance> {
211     @Nullable
212     private final Object defaultValue;
213     private final Lazy<XmlFlagContainerSupport> flagContainer;
214     private final Lazy<IValueConstrained> constraints;
215 
216     private InternalFieldDefinition(
217         @NonNull InlineFieldDefinitionType xmlField) {
218       Object defaultValue = null;
219       if (xmlField.isSetDefault()) {
220         defaultValue = getJavaTypeAdapter().parse(ObjectUtils.requireNonNull(xmlField.getDefault()));
221       }
222       this.defaultValue = defaultValue;
223       this.flagContainer = Lazy.lazy(() -> new XmlFlagContainerSupport(xmlField, this));
224       this.constraints = Lazy.lazy(() -> {
225         IValueConstrained retval;
226         if (xmlField.isSetConstraint()) {
227           retval = new ValueConstraintSupport(
228               ObjectUtils.notNull(xmlField.getConstraint()),
229               ExternalModelSource.instance(
230                   ObjectUtils.requireNonNull(getContainingModule().getLocation())));
231         } else {
232           retval = new ValueConstraintSupport();
233         }
234         return retval;
235       });
236     }
237 
238     // ----------------------------------------
239     // - Start annotation driven code - CPD-OFF
240     // ----------------------------------------
241 
242     @SuppressWarnings("null")
243     @Override
244     public IDataTypeAdapter<?> getJavaTypeAdapter() {
245       return getXmlField().isSetAsType() ? getXmlField().getAsType() : MetaschemaDataTypeProvider.DEFAULT_DATA_TYPE;
246     }
247 
248     @Override
249     public boolean hasJsonValueKeyFlagInstance() {
250       return getXmlField().isSetJsonValueKeyFlag() && getXmlField().getJsonValueKeyFlag().isSetFlagRef();
251     }
252 
253     @Override
254     public IFlagInstance getJsonValueKeyFlagInstance() {
255       IFlagInstance retval = null;
256       if (getXmlField().isSetJsonValueKeyFlag() && getXmlField().getJsonValueKeyFlag().isSetFlagRef()) {
257         retval = getFlagInstanceByName(ObjectUtils.notNull(getXmlField().getJsonValueKeyFlag().getFlagRef()));
258       }
259       return retval;
260     }
261 
262     @Override
263     public String getJsonValueKeyName() {
264       String retval = null;
265 
266       if (getXmlField().isSetJsonValueKey()) {
267         retval = getXmlField().getJsonValueKey();
268       }
269 
270       if (retval == null || retval.isEmpty()) {
271         retval = getJavaTypeAdapter().getDefaultJsonValueKey();
272       }
273       return retval;
274     }
275 
276     // --------------------------------------
277     // - End annotation driven code - CPD-ON
278     // --------------------------------------
279 
280     @Override
281     public Object getDefaultValue() {
282       return defaultValue;
283     }
284 
285     @Override
286     public boolean isInline() {
287       return true;
288     }
289 
290     @Override
291     @NonNull
292     public IFieldInstance getInlineInstance() {
293       return XmlInlineFieldDefinition.this;
294     }
295 
296     @Override
297     public String getFormalName() {
298       return XmlInlineFieldDefinition.this.getFormalName();
299     }
300 
301     @Override
302     public MarkupLine getDescription() {
303       return XmlInlineFieldDefinition.this.getDescription();
304     }
305 
306     @Override
307     public @NonNull Map<QName, Set<String>> getProperties() {
308       return XmlInlineFieldDefinition.this.getProperties();
309     }
310 
311     @Override
312     public ModuleScopeEnum getModuleScope() {
313       return ModuleScopeEnum.LOCAL;
314     }
315 
316     @Override
317     public String getName() {
318       return XmlInlineFieldDefinition.this.getName();
319     }
320 
321     @Override
322     public String getUseName() {
323       // always use the name instead
324       return null;
325     }
326 
327     @SuppressWarnings("null")
328     @Override
329     public XmlFlagContainerSupport getFlagContainer() {
330       return flagContainer.get();
331     }
332 
333     /**
334      * Used to generate the instances for the constraints in a lazy fashion when the
335      * constraints are first accessed.
336      *
337      * @return the constraints instance
338      */
339     @SuppressWarnings("null")
340     @Override
341     public IValueConstrained getConstraintSupport() {
342       return constraints.get();
343     }
344 
345     @Override
346     public MarkupMultiline getRemarks() {
347       return XmlInlineFieldDefinition.this.getRemarks();
348     }
349 
350     @Override
351     public IModule getContainingModule() {
352       return XmlInlineFieldDefinition.super.getContainingDefinition().getContainingModule();
353     }
354 
355     @Override
356     public Object getFieldValue(@NonNull Object parentFieldValue) {
357       // there is no value
358       return null;
359     }
360   }
361 }