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 com.rapiddweller.platform.xml;
28
29 import com.rapiddweller.benerator.engine.BeneratorContext;
30 import com.rapiddweller.benerator.engine.ResourceManager;
31 import com.rapiddweller.benerator.engine.ResourceManagerSupport;
32 import com.rapiddweller.benerator.engine.parser.xml.BeanParser;
33 import com.rapiddweller.benerator.engine.parser.xml.BeneratorParseContext;
34 import com.rapiddweller.benerator.engine.parser.xml.IncludeParser;
35 import com.rapiddweller.benerator.engine.statement.BeanStatement;
36 import com.rapiddweller.benerator.engine.statement.IncludeStatement;
37 import com.rapiddweller.benerator.parser.ModelParser;
38 import com.rapiddweller.common.Assert;
39 import com.rapiddweller.common.BeanUtil;
40 import com.rapiddweller.common.CollectionUtil;
41 import com.rapiddweller.common.ConfigurationError;
42 import com.rapiddweller.common.Context;
43 import com.rapiddweller.common.IOUtil;
44 import com.rapiddweller.common.StringUtil;
45 import com.rapiddweller.common.context.ContextAware;
46 import com.rapiddweller.common.xml.XMLUtil;
47 import com.rapiddweller.model.data.AlternativeGroupDescriptor;
48 import com.rapiddweller.model.data.ComplexTypeDescriptor;
49 import com.rapiddweller.model.data.ComponentDescriptor;
50 import com.rapiddweller.model.data.DataModel;
51 import com.rapiddweller.model.data.DefaultDescriptorProvider;
52 import com.rapiddweller.model.data.FeatureDescriptor;
53 import com.rapiddweller.model.data.InstanceDescriptor;
54 import com.rapiddweller.model.data.Mode;
55 import com.rapiddweller.model.data.PartDescriptor;
56 import com.rapiddweller.model.data.SimpleTypeDescriptor;
57 import com.rapiddweller.model.data.TypeDescriptor;
58 import com.rapiddweller.model.data.UnionSimpleTypeDescriptor;
59 import com.rapiddweller.model.data.UnresolvedTypeDescriptor;
60 import com.rapiddweller.script.Expression;
61 import com.rapiddweller.script.PrimitiveType;
62 import com.rapiddweller.script.expression.ConstantExpression;
63 import org.apache.logging.log4j.LogManager;
64 import org.apache.logging.log4j.Logger;
65 import org.w3c.dom.Document;
66 import org.w3c.dom.Element;
67
68 import java.io.Closeable;
69 import java.io.IOException;
70 import java.util.HashMap;
71 import java.util.Map;
72 import java.util.Set;
73
74 import static com.rapiddweller.common.xml.XMLUtil.getNamespaces;
75 import static com.rapiddweller.common.xml.XMLUtil.getTargetNamespace;
76 import static com.rapiddweller.common.xml.XMLUtil.localName;
77 import static com.rapiddweller.common.xml.XMLUtil.normalizedAttributeValue;
78 import static com.rapiddweller.common.xml.XMLUtil.parse;
79 import static com.rapiddweller.script.expression.ExpressionUtil.constant;
80
81
82
83
84
85
86
87
88
89 public class XMLSchemaDescriptorProvider extends DefaultDescriptorProvider implements ContextAware, ResourceManager {
90
91
92
93
94 public static final String INCLUDE = "include";
95
96
97
98 public static final String IMPORT = "import";
99
100
101
102 public static final String SIMPLE_TYPE = "simpleType";
103
104
105
106 public static final String COMPLEX_TYPE = "complexType";
107
108
109
110 public static final String ANNOTATION = "annotation";
111
112
113
114 public static final String SEQUENCE = "sequence";
115
116
117
118 public static final String CHOICE = "choice";
119
120
121
122 public static final String EXTENSION = "extension";
123
124
125
126 public static final String UNION = "union";
127
128
129
130 public static final String ELEMENT = "element";
131
132
133
134 public static final String GROUP = "group";
135
136
137
138 public static final String ATTRIBUTE_GROUP = "attributeGroup";
139
140
141
142 public static final String NAME = "name";
143
144
145
146 public static final String RESTRICTION = "restriction";
147
148
149
150 public static final String BASE = "base";
151
152
153
154 public static final String VALUE = "value";
155
156
157
158 public static final String LENGTH = "length";
159
160
161
162 public static final String MIN_INCLUSIVE = "minInclusive";
163
164
165
166 public static final String MIN_EXCLUSIVE = "minExclusive";
167
168
169
170 public static final String MAX_EXCLUSIVE = "maxExclusive";
171
172
173
174 public static final String MAX_INCLUSIVE = "maxInclusive";
175
176
177
178 public static final String ENUMERATION = "enumeration";
179 private static final String SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema";
180 private static final String TYPE = "type";
181 private static final String REF = "ref";
182 private static final String KEY = "key";
183 private static final String KEYREF = "keyref";
184 private static final String UNIQUE = "unique";
185 private static final String ALL = "all";
186 private static final String COMPLEX_CONTENT = "complexContent";
187 private static final String SIMPLE_CONTENT = "simpleContent";
188 private static final String ATTRIBUTE = "attribute";
189 private static final Logger LOGGER = LogManager.getLogger(XMLSchemaDescriptorProvider.class);
190
191
192 private BeneratorContext context;
193 private String schemaUri;
194
195 private final ModelParser parser;
196 private Map<String, String> namespaces;
197 private final ResourceManager resourceManager = new ResourceManagerSupport();
198
199
200
201
202
203
204
205
206
207
208 public XMLSchemaDescriptorProvider(String schemaUri, BeneratorContext context) {
209 super(schemaUri, context.getDataModel(), true);
210 new XMLNativeTypeDescriptorProvider(SCHEMA_NAMESPACE, dataModel);
211 this.namespaces = new HashMap<>();
212 parser = new ModelParser(context);
213 setContext(context);
214 setSchemaUri(schemaUri);
215 }
216
217
218
219 private static void parseOccurrences(Element element, InstanceDescriptor descriptor) {
220 Long minOccurs = XMLUtil.getLongAttribute(element, "minOccurs", 1L);
221 String maxOccursString = element.getAttribute("maxOccurs");
222 Long maxOccurs = 1L;
223 if (!StringUtil.isEmpty(maxOccursString)) {
224 maxOccurs = ("unbounded".equals(maxOccursString) ? null : Long.parseLong(maxOccursString));
225 }
226 if (minOccurs.equals(maxOccurs) && descriptor.getCount() != null) {
227 descriptor.setCount(constant(maxOccurs));
228 descriptor.setMinCount(null);
229 descriptor.setMaxCount(null);
230 } else {
231 descriptor.setCount(null);
232 if (descriptor.getMinCount() == null) {
233 descriptor.setMinCount(constant(minOccurs));
234 }
235 if (descriptor.getMaxCount() == null) {
236 descriptor.setMaxCount(constant(maxOccurs));
237 }
238 }
239 }
240
241 private static void parseRestrictionChildren(Element restriction,
242 SimpleTypeDescriptor descriptor) {
243 Element[] children = XMLUtil.getChildElements(restriction);
244 for (Element child : children) {
245 String nodeName = localName(child);
246 String value = child.getAttribute(VALUE);
247 if (ENUMERATION.equals(nodeName)) {
248 if (PrimitiveType.STRING.equals(descriptor.getPrimitiveType())) {
249 descriptor.addValue("'" + value + "'");
250 } else {
251 descriptor.addValue(value);
252 }
253 } else if (MIN_INCLUSIVE.equals(nodeName)) {
254 descriptor.setMin(value);
255 descriptor.setMinInclusive(true);
256 } else if (MIN_EXCLUSIVE.equals(nodeName)) {
257 descriptor.setMin(value);
258 descriptor.setMinInclusive(false);
259 } else if (MAX_INCLUSIVE.equals(nodeName)) {
260 descriptor.setMax(value);
261 descriptor.setMaxInclusive(true);
262 } else if (MAX_EXCLUSIVE.equals(nodeName)) {
263 descriptor.setMax(value);
264 descriptor.setMaxInclusive(false);
265 } else if (LENGTH.equals(nodeName)) {
266 int length = Integer.parseInt(value);
267 descriptor.setMinLength(length);
268 descriptor.setMaxLength(length);
269 } else if (BeanUtil.hasProperty(descriptor.getClass(), nodeName)) {
270 BeanUtil.setPropertyValue(descriptor, nodeName, value, false);
271 } else {
272 LOGGER.warn("Ignoring restriction " + nodeName + ": " + value);
273 }
274 }
275 }
276
277 private static UnsupportedOperationException unsupportedElementType(Element element, Element parent) {
278 String message = "Element type " + element.getNodeName() + " not supported";
279 if (parent != null) {
280 message += " in " + parent.getNodeName();
281 }
282 return new UnsupportedOperationException(message);
283 }
284
285
286
287
288
289
290
291
292 public void setSchemaUri(String schemaUri) {
293 this.schemaUri = schemaUri;
294 checkSchema();
295 }
296
297
298
299
300
301
302 public BeneratorContext getContext() {
303 return context;
304 }
305
306
307
308 @Override
309 public void setContext(Context context) {
310 this.context = (BeneratorContext) context;
311 checkSchema();
312 }
313
314 @Override
315 public boolean addResource(Closeable resource) {
316 return resourceManager.addResource(resource);
317 }
318
319 @Override
320 public void close() {
321 resourceManager.close();
322 }
323
324 private void checkSchema() {
325 if (!StringUtil.isEmpty(schemaUri) && context != null) {
326 try {
327 Document document = parse(schemaUri);
328 this.namespaces = getNamespaces(document);
329 this.id = getTargetNamespace(document);
330 dataModel.addDescriptorProvider(this);
331 parseStructure(document);
332 parseDetails(document);
333 } catch (IOException e) {
334 throw new ConfigurationError("Error parsing schemaUri: " + schemaUri, e);
335 }
336 }
337 }
338
339 private void parseStructure(Document document) throws IOException {
340 LOGGER.debug("parseStructure()");
341 Element root = document.getDocumentElement();
342 Element[] childElements = XMLUtil.getChildElements(root);
343 for (Element element : childElements) {
344 String nodeName = localName(element);
345 String nameAttribute = element.getAttribute("name");
346 Set<String> COMPLEX_ELEMENTS = CollectionUtil.toSet(COMPLEX_TYPE, GROUP, ATTRIBUTE_GROUP);
347 if (COMPLEX_ELEMENTS.contains(nodeName)) {
348 addTypeDescriptor(new ComplexTypeDescriptor(nameAttribute, this));
349 } else if (SIMPLE_TYPE.equals(nodeName)) {
350 addTypeDescriptor(new SimpleTypeDescriptor(nameAttribute, this));
351 } else if (ELEMENT.equals(nodeName)) {
352 String typeName = element.getAttribute("type");
353 if (!StringUtil.isEmpty(typeName)) {
354 TypeDescriptor elementType = dataModel.getTypeDescriptor(typeName);
355 if (elementType instanceof SimpleTypeDescriptor) {
356 addTypeDescriptor(new SimpleTypeDescriptor(nameAttribute, this));
357 } else if (elementType instanceof ComplexTypeDescriptor) {
358 addTypeDescriptor(new ComplexTypeDescriptor(nameAttribute, this));
359 } else {
360 addTypeDescriptor(new UnresolvedTypeDescriptor(nameAttribute, this, typeName));
361 }
362 } else if (XMLUtil.getChildElements(element, false, "complexType").length > 0) {
363 addTypeDescriptor(new ComplexTypeDescriptor(nameAttribute, this));
364 } else if (XMLUtil.getChildElements(element, false, SIMPLE_TYPE).length > 0) {
365 addTypeDescriptor(new SimpleTypeDescriptor(nameAttribute, this));
366 } else {
367 addTypeDescriptor(new ComplexTypeDescriptor(nameAttribute, this));
368 }
369 } else if (ANNOTATION.equals(nodeName)) {
370 parseDocumentAnnotation(element);
371 } else if (IMPORT.equals(nodeName)) {
372 parseImport(element);
373 } else if (INCLUDE.equals(nodeName)) {
374 parseStructureOfInclude(element);
375 }
376 }
377 resolveTypes();
378 }
379
380 private void resolveTypes() {
381 boolean unresolved = false;
382 do {
383 for (TypeDescriptor type : typeMap.values()) {
384 if (type instanceof UnresolvedTypeDescriptor) {
385 TypeDescriptor parent = type.getParent();
386 if (parent instanceof SimpleTypeDescriptor) {
387 addTypeDescriptor(new SimpleTypeDescriptor(type.getName(), this, type.getParentName()));
388 } else if (parent instanceof ComplexTypeDescriptor) {
389 addTypeDescriptor(new ComplexTypeDescriptor(type.getName(), this, type.getParentName()));
390 } else if (parent == null) {
391 throw new ConfigurationError("parentType " + type.getParentName() + " not found for " + type.getName());
392 } else {
393 unresolved = true;
394 }
395
396 }
397 }
398 } while (unresolved);
399 }
400
401 private void parseDetails(Document document) throws IOException {
402 LOGGER.debug("parseDetails()");
403 Element root = document.getDocumentElement();
404 Element[] childElements = XMLUtil.getChildElements(root);
405 for (Element element : childElements) {
406 String nodeName = localName(element);
407 if (ELEMENT.equals(nodeName)) {
408 parseTopLevelElement(element);
409 } else if (COMPLEX_TYPE.equals(nodeName)) {
410 parseComplexType(element, null, null, true);
411 } else if (SIMPLE_TYPE.equals(nodeName)) {
412 addTypeDescriptor(parseSimpleType(null, element));
413 } else if (GROUP.equals(nodeName)) {
414 parseGroup(element);
415 } else if (ATTRIBUTE_GROUP.equals(nodeName)) {
416 parseAttributeGroup(element);
417 } else if (IMPORT.equals(nodeName)) {
418 parseImport(element);
419 } else if (INCLUDE.equals(nodeName)) {
420 parseDetailsOfInclude(element);
421 } else if (!ANNOTATION.equals(nodeName)) {
422 throw unsupportedElementType(element, root);
423 }
424 }
425 }
426
427 private void parseDocumentAnnotation(Element element) {
428 Annotationtion.html#Annotation">Annotation annotation = new Annotation(element);
429 Element appInfo = annotation.getAppInfo();
430 if (appInfo == null) {
431 return;
432 }
433 for (Element child : XMLUtil.getChildElements(appInfo)) {
434 String childName = XMLUtil.localName(child);
435 if (INCLUDE.equals(childName)) {
436 IncludeStatementom/rapiddweller/benerator/engine/statement/IncludeStatement.html#IncludeStatement">IncludeStatement statement = (IncludeStatement) new IncludeParser().parse(child, null, new BeneratorParseContext(this));
437 statement.execute(context);
438 } else if ("bean".equals(childName)) {
439 Expression<?> constructionExpression = BeanParser.parseBeanExpression(child);
440 String id = child.getAttribute("id");
441 BeanStatementt/BeanStatement.html#BeanStatement">BeanStatement beanStatement = new BeanStatement(id, constructionExpression, this);
442 try {
443 beanStatement.execute(context);
444 } finally {
445 IOUtil.close(beanStatement);
446 }
447 } else {
448 throw new UnsupportedOperationException("Document annotation type not supported: "
449 + child.getNodeName());
450 }
451 }
452 }
453
454 private ComplexTypeDescriptor parseComplexType(Element complexTypeElement, String parentName, Annotation annotationBefore, boolean global) {
455 String name = (parentName != null ? parentName : complexTypeElement.getAttribute(NAME));
456 LOGGER.debug("parseComplexType({})", name);
457 if (name == null) {
458 throw new ConfigurationError("unnamed complex type");
459 }
460 ComplexTypeDescriptoror.html#ComplexTypeDescriptor">ComplexTypeDescriptor descriptor = new ComplexTypeDescriptor(name, this);
461 if (annotationBefore != null) {
462 descriptor = parseElementAppInfo(descriptor, annotationBefore);
463 }
464 Annotation annotation = null;
465 Element[] children = XMLUtil.getChildElements(complexTypeElement);
466 for (Element child : children) {
467 String nodeName = localName(child);
468 if ("annotation".equals(nodeName)) {
469 annotation = new Annotation(child);
470 } else if (SEQUENCE.equals(nodeName)) {
471 parseSequence(child, descriptor);
472 } else if (COMPLEX_CONTENT.equals(nodeName)) {
473 parseComplexContent(child, descriptor);
474 } else if (ALL.equals(nodeName)) {
475 parseAll(child, descriptor);
476 } else if (SIMPLE_CONTENT.equals(nodeName)) {
477 parseSimpleContent(child, descriptor);
478 } else if (ATTRIBUTE.equals(nodeName)) {
479 parseAttribute(child, descriptor);
480 } else if (ATTRIBUTE_GROUP.equals(nodeName)) {
481 ComplexTypeDescriptor group = parseAttributeGroup(child);
482 for (InstanceDescriptor component : group.getParts()) {
483 descriptor.addPart(component);
484 }
485 } else {
486 throw unsupportedElementType(child, complexTypeElement);
487 }
488 }
489 descriptor = parseComplexTypeAppinfo(descriptor, annotation);
490 if (global) {
491 addTypeDescriptor(descriptor);
492 }
493 return descriptor;
494 }
495
496 private ComplexTypeDescriptor parseComplexTypeAppinfo(
497 ComplexTypeDescriptor descriptor, Annotation annotation) {
498 if (annotation == null || annotation.getAppInfo() == null) {
499 return descriptor;
500 }
501
502 Element appInfo = annotation.getAppInfo();
503 Element[] infos = XMLUtil.getChildElements(appInfo);
504 if (infos.length > 1) {
505 throw new ConfigurationError("Cannot handle more than one appinfo in a complex type");
506 }
507 Element info = infos[0];
508
509 parser.parseComplexTypeChild(info, descriptor);
510 return descriptor;
511 }
512
513 private void parseComplexContent(Element complexContent, ComplexTypeDescriptor owner) {
514 Element[] children = XMLUtil.getChildElements(complexContent);
515 for (Element child : children) {
516 String nodeName = localName(child);
517 if (EXTENSION.equals(nodeName)) {
518 parseExtension(child, owner);
519 } else if (RESTRICTION.equals(nodeName)) {
520 parseComplexRestriction(child, owner);
521 } else {
522 throw unsupportedElementType(child, complexContent);
523 }
524 }
525 }
526
527 private void parseComplexRestriction(Element restrictionElement, ComplexTypeDescriptor owner) {
528
529 Element[] children = XMLUtil.getChildElements(restrictionElement);
530 for (Element child : children) {
531 String nodeName = localName(child);
532 if (ATTRIBUTE.equals(nodeName)) {
533 parseAttribute(child, owner);
534 } else {
535 throw unsupportedElementType(child, restrictionElement);
536 }
537 }
538 }
539
540 private void parseSimpleContent(Element simpleContentElement, ComplexTypeDescriptor complexType) {
541 Annotation annotation = null;
542 LOGGER.debug("parseSimpleContent()");
543 for (Element child : XMLUtil.getChildElements(simpleContentElement)) {
544 String localName = localName(child);
545 if (ANNOTATION.equals(localName)) {
546 annotation = new Annotation(child);
547 } else if (RESTRICTION.equals(localName)) {
548 parseSimpleContentRestriction(child, complexType);
549 } else if (EXTENSION.equals(localName)) {
550 parseSimpleContentExtension(child, complexType);
551 } else {
552 throw unsupportedElementType(child, simpleContentElement);
553 }
554 }
555 if (annotation != null && annotation.getAppInfo() != null) {
556 complexType = parseComplexTypeAppinfo(complexType, annotation);
557 }
558 }
559
560 private void parseSimpleContentRestriction(Element restriction, ComplexTypeDescriptor complexType) {
561 String baseName = restriction.getAttribute("base");
562 Assert.notNull(baseName, "base attribute");
563 TypeDescriptor base = dataModel.getTypeDescriptor(baseName);
564 Assert.notNull(base, "base type");
565 if (!(base instanceof ComplexTypeDescriptor)) {
566 throw new ConfigurationError("Expected ComplexTypeDescriptor for " + baseName + ", found: " +
567 base.getClass().getSimpleName());
568 }
569 complexType.setParent(base);
570 SimpleTypeDescriptor/rapiddweller/model/data/SimpleTypeDescriptor.html#SimpleTypeDescriptor">SimpleTypeDescriptor content = (SimpleTypeDescriptor) complexType.getComponent(ComplexTypeDescriptor.__SIMPLE_CONTENT).getLocalType(false);
571 Assert.notNull(content, "content");
572 parseRestrictionChildren(restriction, content);
573 }
574
575 private void parseSimpleContentExtension(Element extension, ComplexTypeDescriptor complexType) {
576 String baseName = extension.getAttribute("base");
577 Assert.notNull(baseName, "base attribute");
578 TypeDescriptor base = dataModel.getTypeDescriptor(baseName);
579 Assert.notNull(base, "base type");
580 if (base instanceof SimpleTypeDescriptor) {
581 complexType.addComponent(new PartDescriptor(ComplexTypeDescriptor.__SIMPLE_CONTENT, this, baseName, null,
582 new ConstantExpression<>(1L), new ConstantExpression<>(1L)));
583 } else if (base instanceof ComplexTypeDescriptor) {
584 complexType.setParentName(baseName);
585 } else {
586 throw new UnsupportedOperationException("not a supported type: " + base.getClass());
587 }
588 parseAttributes(extension, complexType);
589 }
590
591 private void parseExtension(Element extension, ComplexTypeDescriptor descriptor) {
592 String base = extension.getAttribute(BASE);
593 descriptor.setParentName(base);
594 parseAttributes(extension, descriptor);
595 }
596
597 private void parseAttributes(Element extension, ComplexTypeDescriptor owner) {
598 Element[] children = XMLUtil.getChildElements(extension);
599 for (Element child : children) {
600 String nodeName = localName(child);
601 if (ATTRIBUTE.equals(nodeName)) {
602 parseAttribute(child, owner);
603 } else {
604 throw unsupportedElementType(child, extension);
605 }
606 }
607 }
608
609 private void parseTopLevelElement(Element element) {
610 String name = element.getAttribute(NAME);
611 LOGGER.debug("parseTopLevelElement({})", name);
612 TypeDescriptor descriptor = null;
613 Annotation annotation = null;
614 Element[] children = XMLUtil.getChildElements(element);
615 for (Element child : children) {
616 String nodeName = localName(child);
617 if (COMPLEX_TYPE.equals(nodeName)) {
618 descriptor = parseComplexType(child, name, annotation, false);
619 annotation = null;
620 } else if (SIMPLE_TYPE.equals(nodeName)) {
621 descriptor = parseSimpleType(name, child);
622 } else if (KEY.equals(nodeName)) {
623 parseKey(child);
624 } else if (KEYREF.equals(nodeName)) {
625 parseKeyRef(child);
626 } else if (ANNOTATION.equals(nodeName)) {
627 annotation = new Annotation(child);
628 } else {
629 throw unsupportedElementType(child, element);
630 }
631 }
632
633 if (descriptor == null) {
634 String type = element.getAttribute("type");
635 if (!StringUtil.isEmpty(type)) {
636 descriptor = parseTopLevelElementWithType(element);
637 }
638 }
639 descriptor = parseElementAppInfo(descriptor, annotation);
640 if (descriptor == null) {
641 descriptor = new ComplexTypeDescriptor(name, this);
642 }
643 addTypeDescriptor(descriptor);
644 }
645
646 private void parseContainedElement(Element element, ComplexTypeDescriptor owner) {
647 String name = element.getAttribute(NAME);
648 LOGGER.debug("parseElement({})", element.getAttribute(NAME));
649 Assert.notNull(owner, "owner");
650 PartDescriptor descriptor = null;
651 if (!StringUtil.isEmpty(element.getAttribute(REF))) {
652 descriptor = parseElementRef(element);
653 }
654 Annotation annotation = null;
655 Element[] children = XMLUtil.getChildElements(element);
656 for (Element child : children) {
657 String nodeName = localName(child);
658 if (COMPLEX_TYPE.equals(nodeName)) {
659 ComplexTypeDescriptor type = parseComplexType(child, name, annotation, false);
660 descriptor = new PartDescriptor(name, this, type);
661 annotation = null;
662 } else if (SIMPLE_TYPE.equals(nodeName)) {
663 SimpleTypeDescriptor simpleType = parseSimpleType(name, child);
664 ComplexTypeDescriptor complexType = wrapSimpleTypeWithComplexType(simpleType);
665 descriptor = new PartDescriptor(name, this, complexType);
666 } else if (KEY.equals(nodeName)) {
667 parseKey(child);
668 } else if (KEYREF.equals(nodeName)) {
669 parseKeyRef(child);
670 } else if (UNIQUE.equals(nodeName)) {
671 parseUnique(child);
672 } else if (ANNOTATION.equals(nodeName)) {
673 annotation = new Annotation(child);
674 } else {
675 throw unsupportedElementType(child, element);
676 }
677 }
678
679 if (descriptor == null) {
680 String type = element.getAttribute("type");
681 if (!StringUtil.isEmpty(type)) {
682 descriptor = parseElementWithType(element);
683 }
684 } else {
685 parseElementAppInfo(descriptor, annotation);
686 }
687 if (descriptor == null) {
688 descriptor = new PartDescriptor(name, this, "string");
689 }
690 parseOccurrences(element, descriptor);
691 if ("false".equals(element.getAttribute("nillable"))) {
692 descriptor.setNullable(false);
693 }
694 owner.addComponent(descriptor);
695 }
696
697 private ComplexTypeDescriptor wrapSimpleTypeWithComplexType(SimpleTypeDescriptor simpleType) {
698 ComplexTypeDescriptorr.html#ComplexTypeDescriptor">ComplexTypeDescriptor complexType = new ComplexTypeDescriptor(simpleType.getName(), this);
699 complexType.addComponent(new PartDescriptor(ComplexTypeDescriptor.__SIMPLE_CONTENT, this, simpleType));
700 return complexType;
701 }
702
703 @SuppressWarnings("static-method")
704 private void parseUnique(Element child) {
705
706 LOGGER.warn("<unique> is not supported. Please define own annotations or setup for uniqueness assurance");
707 }
708
709 private PartDescriptor parseElementRef(Element element) {
710 String refName = element.getAttribute(REF);
711 if (StringUtil.isEmpty(refName)) {
712 throw new ConfigurationError("no ref specified in element");
713 }
714 TypeDescriptor type = dataModel.getTypeDescriptor(refName);
715 PartDescriptor descriptor;
716 if (type instanceof SimpleTypeDescriptor) {
717 ComplexTypeDescriptorr.html#ComplexTypeDescriptor">ComplexTypeDescriptor complexType = new ComplexTypeDescriptor(refName, this);
718 complexType.addComponent(new PartDescriptor(ComplexTypeDescriptor.__SIMPLE_CONTENT, this, refName));
719 descriptor = new PartDescriptor(refName, this, complexType);
720 } else {
721 descriptor = new PartDescriptor(refName, this, type);
722 }
723 return descriptor;
724 }
725
726 @SuppressWarnings("unchecked")
727 private <T extends FeatureDescriptor> T parseElementAppInfo(T descriptor, Annotation annotation) {
728 if (annotation == null || annotation.getAppInfo() == null) {
729 return descriptor;
730 }
731
732 Element appInfo = annotation.getAppInfo();
733 Element[] infos = XMLUtil.getChildElements(appInfo);
734
735 for (Element info : infos) {
736 String childName = XMLUtil.localName(info);
737 if ("bean".equals(childName)) {
738 BeanParser.parseBeanExpression(info);
739 } else if ("variable".equals(childName)) {
740 parser.parseVariable(info, (ComplexTypeDescriptor) descriptor);
741 } else if (ATTRIBUTE.equals(childName)) {
742 descriptor = (T) parser.parseAttribute(info, null, (PartDescriptor) descriptor);
743 } else if ("part".equals(childName)) {
744 descriptor = (T) parser.parsePart(info, null, (PartDescriptor) descriptor);
745 } else if (descriptor instanceof ComplexTypeDescriptor) {
746 descriptor = (T) parser.parseComplexType(info, (ComplexTypeDescriptor) descriptor);
747 } else if (descriptor instanceof SimpleTypeDescriptor) {
748 descriptor = (T) parser.parseSimpleType(info, (SimpleTypeDescriptor) descriptor);
749 } else if ("type".equals(childName)) {
750 TypeDescriptor typeDescriptor =
751 (descriptor instanceof InstanceDescriptor../../com/rapiddweller/model/data/InstanceDescriptor.html#InstanceDescriptor">InstanceDescriptor ? ((InstanceDescriptor) descriptor).getTypeDescriptor() : (TypeDescriptor) descriptor);
752 if (typeDescriptor instanceof SimpleTypeDescriptor) {
753 descriptor = (T) parser.parseSimpleType(info, (SimpleTypeDescriptor) typeDescriptor);
754 } else {
755 descriptor = (T) parser.parseComplexType(info, (ComplexTypeDescriptor) typeDescriptor);
756 }
757 } else {
758 throw new UnsupportedOperationException("Unsupported element (" + childName + ") " +
759 "or descriptor type: " + descriptor.getClass().getName());
760 }
761 }
762 return descriptor;
763 }
764
765
766
767
768
769
770
771
772
773 private TypeDescriptor parseTopLevelElementWithType(Element element) {
774 String name = element.getAttribute(NAME);
775 String typeName = element.getAttribute("type");
776 TypeDescriptor type = getType(typeName);
777 if (type == null) {
778 type = getType(name);
779 }
780 if (type != null) {
781 if (type instanceof SimpleTypeDescriptor) {
782 return new SimpleTypeDescriptor(name, this, typeName);
783 } else if (type instanceof ComplexTypeDescriptor) {
784 return new ComplexTypeDescriptor(name, this, typeName);
785 } else {
786 throw new UnsupportedOperationException("Unsupported descriptor: " + type);
787 }
788 } else {
789 throw new UnsupportedOperationException("Unsupported type: " + typeName);
790 }
791 }
792
793 private PartDescriptor parseElementWithType(Element element) {
794 String name = element.getAttribute(NAME);
795 String typeName = element.getAttribute("type");
796 TypeDescriptor type = getType(typeName);
797 if (type == null) {
798 throw new ConfigurationError("Undefined type: " + typeName);
799 }
800 PartDescriptor refDesc;
801 if (type instanceof SimpleTypeDescriptor) {
802
803 SimpleTypeDescriptortor.html#SimpleTypeDescriptor">SimpleTypeDescriptor localType = new SimpleTypeDescriptor(name, this, typeName);
804 ComplexTypeDescriptor contentType = wrapSimpleTypeWithComplexType(localType);
805 refDesc = new PartDescriptor(name, this, contentType);
806 Element anno = XMLUtil.getChildElement(element, false, false, "annotation");
807 if (anno != null) {
808 parseSimpleTypeAppinfo(new Annotation(anno), localType);
809 }
810 } else {
811 ComplexTypeDescriptortor.html#ComplexTypeDescriptor">ComplexTypeDescriptor localType = new ComplexTypeDescriptor(name, this, typeName);
812 refDesc = new PartDescriptor(name, this, localType);
813 Element anno = XMLUtil.getChildElement(element, false, false, "annotation");
814 if (anno != null) {
815 refDesc = parseAttributeAppinfo(new Annotation(anno), refDesc);
816 }
817 }
818 parseOccurrences(element, refDesc);
819 return refDesc;
820 }
821
822 private TypeDescriptor getType(String typeName) {
823 int sep = typeName.indexOf(':');
824 if (sep < 0) {
825 return dataModel.getTypeDescriptor(typeName);
826 }
827 String nsAlias = typeName.substring(0, sep);
828 String namespace = getNamespaceForAlias(nsAlias);
829 String typeInNs = typeName.substring(sep + 1);
830 return dataModel.getTypeDescriptor(namespace, typeInNs);
831 }
832
833 private String getNamespaceForAlias(String nsAlias) {
834 return namespaces.get(nsAlias);
835 }
836
837 @SuppressWarnings("static-method")
838 private void parseKeyRef(Element child) {
839
840 LOGGER.warn("KeyRefs are not supported, yet. Ignoring keyRef: " + child.getAttribute("name"));
841 }
842
843 @SuppressWarnings("static-method")
844 private void parseKey(Element child) {
845
846 LOGGER.warn("Keys are not supported, yet. Ignoring key: " + child.getAttribute("name"));
847 }
848
849 @SuppressWarnings("null")
850 private void parseAttribute(Element attributeElement, ComplexTypeDescriptor owner) {
851 String name = attributeElement.getAttribute(NAME);
852 LOGGER.debug("parseAttribute({})", name);
853 if (StringUtil.isEmpty(name)) {
854 throw new ConfigurationError("Unnamed attribute");
855 }
856 Element[] children = XMLUtil.getChildElements(attributeElement);
857 String use = attributeElement.getAttribute("use");
858 Boolean nullable = ("required".equals(use) ? Boolean.FALSE : null);
859 Annotation annotation = null;
860 ComponentDescriptor descriptor = null;
861 for (Element child : children) {
862 String nodeName = localName(child);
863 if ("annotation".equals(nodeName)) {
864 annotation = new Annotation(child);
865 } else if (SIMPLE_TYPE.equals(nodeName)) {
866 descriptor = new PartDescriptor(name, this, parseSimpleType(null, child));
867 } else {
868 throw unsupportedElementType(child, attributeElement);
869 }
870 }
871 String type = attributeElement.getAttribute("type");
872 if (descriptor == null && type != null) {
873 descriptor = new PartDescriptor(name, this, type);
874 if (nullable != null && !nullable) {
875 descriptor.setNullable(false);
876 }
877 }
878 if (annotation != null && annotation.getAppInfo() != null) {
879 descriptor = parseAttributeAppinfo(annotation, descriptor);
880 }
881 String fixed = attributeElement.getAttribute("fixed");
882 if (!StringUtil.isEmpty(fixed)) {
883 ((SimpleTypeDescriptor) descriptor.getLocalType(false)).setValues(fixed);
884 } else {
885 String defaultValue = attributeElement.getAttribute("default");
886 if (!StringUtil.isEmpty(defaultValue)) {
887 ((SimpleTypeDescriptor) descriptor.getLocalType(false)).setValues(defaultValue);
888 }
889 }
890 descriptor.setCount(new ConstantExpression<>(1L));
891 if ("prohibited".equals(attributeElement.getAttribute("use"))) {
892 descriptor.setMode(Mode.ignored);
893 }
894 owner.addComponent(descriptor);
895 }
896
897 @SuppressWarnings("unchecked")
898 private <T extends ComponentDescriptor> T parseAttributeAppinfo(Annotation annotation, T descriptor) {
899 Element appInfo = annotation.getAppInfo();
900 if (appInfo == null) {
901 return descriptor;
902 }
903 Element[] infos = XMLUtil.getChildElements(appInfo);
904 if (infos.length > 1) {
905 throw new ConfigurationError("Cannot handle more than one appinfo in a simple type");
906 }
907 if (infos.length == 0) {
908 return descriptor;
909 }
910 Element info = infos[0];
911 return (T) parser.parseSimpleTypeComponent(info, null, descriptor);
912 }
913
914 private SimpleTypeDescriptor parseSimpleType(String name, Element simpleType) {
915 Annotation annotation = null;
916 SimpleTypeDescriptor descriptor = null;
917 if (name == null) {
918 name = simpleType.getAttribute("name");
919 }
920 LOGGER.debug("parseSimpleType({})", name);
921 for (Element child : XMLUtil.getChildElements(simpleType)) {
922 String localName = localName(child);
923 if (ANNOTATION.equals(localName)) {
924 annotation = new Annotation(child);
925 } else if (UNION.equals(localName)) {
926 descriptor = parseUnion(child, name);
927 } else if (RESTRICTION.equals(localName)) {
928 descriptor = parseSimpleTypeRestriction(child, name);
929 } else {
930 throw unsupportedElementType(child, simpleType);
931 }
932 }
933 if (descriptor == null) {
934 String type = simpleType.getAttribute(TYPE);
935 descriptor = new SimpleTypeDescriptor(name, this, type);
936 }
937 if (annotation != null && annotation.getAppInfo() != null) {
938 descriptor = parseSimpleTypeAppinfo(annotation, descriptor);
939 }
940 return descriptor;
941 }
942
943 private SimpleTypeDescriptor parseSimpleTypeAppinfo(
944 Annotation annotation, SimpleTypeDescriptor descriptor) {
945 Element appInfo = annotation.getAppInfo();
946 if (appInfo != null) {
947 Element[] infos = XMLUtil.getChildElements(appInfo);
948 if (infos.length > 1) {
949 throw new ConfigurationError("Cannot handle more than one appinfo in a simple type");
950 }
951 parser.parseSimpleType(infos[0], descriptor);
952 }
953 return descriptor;
954 }
955
956 private SimpleTypeDescriptor parseUnion(Element union, String name) {
957 LOGGER.debug("parseUnion({})", name);
958 UnionSimpleTypeDescriptoror.html#UnionSimpleTypeDescriptor">UnionSimpleTypeDescriptor descriptor = new UnionSimpleTypeDescriptor(name, this);
959 Element[] children = XMLUtil.getChildElements(union);
960 for (Element child : children) {
961 String nodeName = localName(child);
962 if (SIMPLE_TYPE.equals(nodeName)) {
963 descriptor.addAlternative(parseSimpleType(null, child));
964 } else {
965 throw unsupportedElementType(child, union);
966 }
967 }
968 String memberTypes = union.getAttribute("memberTypes");
969 if (!StringUtil.isEmpty(memberTypes)) {
970 String[] tokens = StringUtil.tokenize(memberTypes, ' ');
971 for (String token : tokens) {
972 if (!StringUtil.isEmpty(token)) {
973 descriptor.addAlternative(new SimpleTypeDescriptor("_local", this, token));
974 }
975 }
976 }
977 return descriptor;
978 }
979
980 private SimpleTypeDescriptor parseSimpleTypeRestriction(Element restriction, String name) {
981 String base = XMLUtil.localName(restriction.getAttribute(BASE));
982 SimpleTypeDescriptoror.html#SimpleTypeDescriptor">SimpleTypeDescriptor descriptor = new SimpleTypeDescriptor(name, this, base);
983 parseRestrictionChildren(restriction, descriptor);
984 return descriptor;
985 }
986
987 @SuppressWarnings("static-method")
988 private void parseImport(Element importElement) {
989 LOGGER.debug("parseImport()");
990 throw unsupportedElementType(importElement, null);
991 }
992
993
994
995
996 private void parseStructureOfInclude(Element includeElement) throws IOException {
997 LOGGER.debug("parseStructureOfInclude()");
998 assert "include".equals(localName(includeElement));
999 String location = includeElement.getAttribute("schemaLocation");
1000 parseStructure(parse(location));
1001 }
1002
1003 private void parseDetailsOfInclude(Element includeElement) throws IOException {
1004 LOGGER.debug("parseDetailsOfInclude()");
1005 assert "include".equals(localName(includeElement));
1006 String location = includeElement.getAttribute("schemaLocation");
1007 parseDetails(parse(location));
1008 }
1009
1010 @SuppressWarnings("static-method")
1011 private void parseGroup(Element group) {
1012 LOGGER.debug("parseGroup()");
1013 throw unsupportedElementType(group, null);
1014 }
1015
1016 private ComplexTypeDescriptor parseAttributeGroup(Element group) {
1017 LOGGER.debug("parseAttributeGroup()");
1018
1019 String refName = normalizedAttributeValue(group, REF);
1020 if (refName != null) {
1021 ComplexTypeDescriptorapiddweller/model/data/ComplexTypeDescriptor.html#ComplexTypeDescriptor">ComplexTypeDescriptor refdType = (ComplexTypeDescriptor) getType(refName);
1022 if (refdType == null) {
1023 throw new ConfigurationError("referenced attributeGroup not found: " + refName);
1024 }
1025 return refdType;
1026 }
1027
1028 String name = normalizedAttributeValue(group, "name");
1029 ComplexTypeDescriptorscriptor.html#ComplexTypeDescriptor">ComplexTypeDescriptor type = new ComplexTypeDescriptor(name, this);
1030 Annotation annotation = null;
1031 for (Element child : XMLUtil.getChildElements(group)) {
1032 String elType = XMLUtil.localName(child);
1033 if (ATTRIBUTE.equals(elType)) {
1034 parseAttribute(child, type);
1035 } else if ("attributeGroup".equals(elType)) {
1036
1037 ComplexTypeDescriptor childGroup = parseAttributeGroup(child);
1038 for (InstanceDescriptor component : childGroup.getParts()) {
1039 type.addPart(component);
1040 }
1041 } else if ("annotation".equals(elType)) {
1042 annotation = new Annotation(child);
1043 } else {
1044 throw unsupportedElementType(child, group);
1045 }
1046 }
1047 if (annotation != null && annotation.getAppInfo() != null) {
1048 LOGGER.warn("ignoring appinfo of attributeGroup: " + name);
1049 }
1050 addTypeDescriptor(type);
1051 return type;
1052 }
1053
1054 private void parseSequence(Element sequence, ComplexTypeDescriptor owner) {
1055 LOGGER.debug("parseSequence()");
1056 parseComponentGroupChildren(sequence, owner);
1057 }
1058
1059 private void parseChoice(Element choice, ComplexTypeDescriptor owner) {
1060 LOGGER.debug("parseChoice()");
1061 AlternativeGroupDescriptorl#AlternativeGroupDescriptor">AlternativeGroupDescriptor choiceDescriptor = new AlternativeGroupDescriptor(null, this);
1062 parseComponentGroupChildren(choice, choiceDescriptor);
1063 PartDescriptortml#PartDescriptor">PartDescriptor partDescriptor = new PartDescriptor(null, this, choiceDescriptor);
1064 parseOccurrences(choice, partDescriptor);
1065 owner.addComponent(partDescriptor);
1066 }
1067
1068 private void parseAll(Element all, ComplexTypeDescriptor owner) {
1069 LOGGER.debug("parseAll()");
1070 parseComponentGroupChildren(all, owner);
1071 }
1072
1073 private void parseComponentGroupChildren(Element choice, ComplexTypeDescriptor groupDescriptor) {
1074 Element[] children = XMLUtil.getChildElements(choice);
1075 for (Element child : children) {
1076 String nodeName = localName(child);
1077 if (ELEMENT.equals(nodeName)) {
1078 parseContainedElement(child, groupDescriptor);
1079 } else if (SEQUENCE.equals(nodeName)) {
1080 parseSequence(child, groupDescriptor);
1081 } else if (CHOICE.equals(nodeName)) {
1082 parseChoice(child, groupDescriptor);
1083 } else {
1084 throw unsupportedElementType(child, choice);
1085 }
1086 }
1087 }
1088
1089 }