1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.metaschema.schemagen.xml.schematype;
28
29 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupDataTypeProvider;
30 import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
31 import gov.nist.secauto.metaschema.core.model.IChoiceInstance;
32 import gov.nist.secauto.metaschema.core.model.IFieldInstance;
33 import gov.nist.secauto.metaschema.core.model.IFlagContainer;
34 import gov.nist.secauto.metaschema.core.model.IFlagInstance;
35 import gov.nist.secauto.metaschema.core.model.IModelInstance;
36 import gov.nist.secauto.metaschema.core.model.INamedModelInstance;
37 import gov.nist.secauto.metaschema.core.model.XmlGroupAsBehavior;
38 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
39 import gov.nist.secauto.metaschema.schemagen.SchemaGenerationException;
40 import gov.nist.secauto.metaschema.schemagen.xml.XmlSchemaGenerator;
41 import gov.nist.secauto.metaschema.schemagen.xml.impl.DocumentationGenerator;
42 import gov.nist.secauto.metaschema.schemagen.xml.impl.XmlGenerationState;
43
44 import java.util.Collection;
45
46 import javax.xml.namespace.QName;
47 import javax.xml.stream.XMLStreamException;
48
49 import edu.umd.cs.findbugs.annotations.NonNull;
50
51 public class XmlComplexTypeAssemblyDefinition
52 extends AbstractXmlComplexType<IAssemblyDefinition> {
53
54 public XmlComplexTypeAssemblyDefinition(
55 @NonNull QName qname,
56 @NonNull IAssemblyDefinition definition) {
57 super(qname, definition);
58 }
59
60 @Override
61 protected void generateTypeBody(XmlGenerationState state) throws XMLStreamException {
62 IAssemblyDefinition definition = getDefinition();
63
64 Collection<? extends IModelInstance> modelInstances = definition.getModelInstances();
65 if (!modelInstances.isEmpty()) {
66 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "sequence", XmlSchemaGenerator.NS_XML_SCHEMA);
67 for (IModelInstance modelInstance : modelInstances) {
68 assert modelInstance != null;
69 generateModelInstance(modelInstance, state);
70 }
71 state.writeEndElement();
72 }
73
74 Collection<? extends IFlagInstance> flagInstances = definition.getFlagInstances();
75 if (!flagInstances.isEmpty()) {
76 for (IFlagInstance flagInstance : flagInstances) {
77 assert flagInstance != null;
78 generateFlagInstance(flagInstance, state);
79 }
80 }
81 }
82
83 protected void generateModelInstance(
84 @NonNull IModelInstance modelInstance,
85 @NonNull XmlGenerationState state)
86 throws XMLStreamException {
87
88 boolean grouped = false;
89 if (XmlGroupAsBehavior.GROUPED.equals(modelInstance.getXmlGroupAsBehavior())) {
90
91 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "element", XmlSchemaGenerator.NS_XML_SCHEMA);
92
93 QName groupAsQName = ObjectUtils.requireNonNull(modelInstance.getXmlGroupAsQName());
94
95 if (state.getDefaultNS().equals(groupAsQName.getNamespaceURI())) {
96 state.writeAttribute("name", ObjectUtils.requireNonNull(groupAsQName.getLocalPart()));
97 } else {
98 throw new SchemaGenerationException(
99 String.format("Attempt to create element '%s' on definition '%s' with different namespace", groupAsQName,
100 getDefinition().toCoordinates()));
101 }
102
103 if (modelInstance.getMinOccurs() == 0) {
104
105 state.writeAttribute("minOccurs", "0");
106 }
107
108
109 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "complexType", XmlSchemaGenerator.NS_XML_SCHEMA);
110 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "sequence", XmlSchemaGenerator.NS_XML_SCHEMA);
111
112
113 grouped = true;
114 }
115
116 switch (modelInstance.getModelType()) {
117 case ASSEMBLY:
118 generateNamedModelInstance((INamedModelInstance) modelInstance, grouped, state);
119 break;
120 case FIELD: {
121 IFieldInstance fieldInstance = (IFieldInstance) modelInstance;
122 if (!fieldInstance.isInXmlWrapped()
123 && fieldInstance.getDefinition().getJavaTypeAdapter().isUnrappedValueAllowedInXml()) {
124 generateUnwrappedFieldInstance(fieldInstance, grouped, state);
125 } else {
126 generateNamedModelInstance(fieldInstance, grouped, state);
127 }
128 break;
129 }
130 case CHOICE:
131 generateChoiceModelInstance((IChoiceInstance) modelInstance, state);
132 break;
133 default:
134 throw new UnsupportedOperationException();
135 }
136
137 if (grouped) {
138 state.writeEndElement();
139 state.writeEndElement();
140 state.writeEndElement();
141 }
142 }
143
144 protected void generateNamedModelInstance(
145 @NonNull INamedModelInstance modelInstance,
146 boolean grouped,
147 @NonNull XmlGenerationState state) throws XMLStreamException {
148 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "element", XmlSchemaGenerator.NS_XML_SCHEMA);
149
150 state.writeAttribute("name", modelInstance.getEffectiveName());
151
152
153
154 if (!grouped && modelInstance.getMinOccurs() != 1) {
155 state.writeAttribute("minOccurs", ObjectUtils.notNull(Integer.toString(modelInstance.getMinOccurs())));
156 }
157
158 if (modelInstance.getMaxOccurs() != 1) {
159 state.writeAttribute("maxOccurs",
160 modelInstance.getMaxOccurs() == -1 ? "unbounded"
161 : ObjectUtils.notNull(Integer.toString(modelInstance.getMaxOccurs())));
162 }
163
164 IFlagContainer definition = modelInstance.getDefinition();
165 IXmlType type = state.getTypeForDefinition(definition);
166
167 if (state.isInline(definition)) {
168 DocumentationGenerator.generateDocumentation(modelInstance, state);
169 type.generateType(state, true);
170 } else {
171 state.writeAttribute("type", type.getTypeReference());
172 DocumentationGenerator.generateDocumentation(modelInstance, state);
173 }
174 state.writeEndElement();
175 }
176
177 protected static void generateUnwrappedFieldInstance(
178 @NonNull IFieldInstance fieldInstance,
179 boolean grouped,
180 @NonNull XmlGenerationState state) throws XMLStreamException {
181
182 if (!MarkupDataTypeProvider.MARKUP_MULTILINE.equals(fieldInstance.getDefinition().getJavaTypeAdapter())) {
183 throw new IllegalStateException();
184 }
185
186 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "group", XmlSchemaGenerator.NS_XML_SCHEMA);
187
188 state.writeAttribute("ref", "blockElementGroup");
189
190
191 if (!grouped && fieldInstance.getMinOccurs() != 1) {
192 state.writeAttribute("minOccurs", ObjectUtils.notNull(Integer.toString(fieldInstance.getMinOccurs())));
193 }
194
195
196
197
198
199
200
201
202
203
204 state.writeAttribute("maxOccurs", "unbounded");
205
206 DocumentationGenerator.generateDocumentation(fieldInstance, state);
207
208 state.writeEndElement();
209 }
210
211 protected void generateChoiceModelInstance(@NonNull IChoiceInstance choice,
212 @NonNull XmlGenerationState state) throws XMLStreamException {
213 state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "choice", XmlSchemaGenerator.NS_XML_SCHEMA);
214
215 for (IModelInstance instance : choice.getModelInstances()) {
216 assert instance != null;
217
218 if (instance instanceof IChoiceInstance) {
219 generateChoiceModelInstance((IChoiceInstance) instance, state);
220 } else {
221 generateModelInstance(instance, state);
222 }
223 }
224
225 state.writeEndElement();
226 }
227 }