Merge pull request #83 from eadrkir/master
[deliverable/titan.core.git] / xsdconvert / ComplexType.cc
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Balasko, Jeno
10 * Beres, Szabolcs
11 * Godar, Marton
12 * Ormandi, Matyas
13 * Raduly, Csaba
14 * Szabo, Bence Janos
15 *
16 ******************************************************************************/
17 #include "ComplexType.hh"
18
19 #include "GeneralFunctions.hh"
20 #include "XMLParser.hh"
21 #include "TTCN3Module.hh"
22 #include "TTCN3ModuleInventory.hh"
23 #include "Annotation.hh"
24
25 #include <assert.h>
26
27 ComplexType::ComplexType(XMLParser * a_parser, TTCN3Module * a_module, ConstructType a_construct)
28 : SimpleType(a_parser, a_module, a_construct)
29 , top(true)
30 , nillable(false)
31 , enumerated(false)
32 , embed(false)
33 , with_union(false)
34 , first_child(false)
35 , fromAll(false)
36 , max_alt(0)
37 , skipback(0)
38 , lastType()
39 , actualPath(empty_string)
40 , actfield(this)
41 , nameDep(NULL)
42 , nillable_field(NULL)
43 , basefield(NULL)
44 , cmode(CT_undefined_mode)
45 , resolved(No)
46 , parentTypeSubsGroup(NULL)
47 , complexfields()
48 , attribfields()
49 , enumfields()
50 , tagNames() {
51 xsdtype = n_complexType;
52 }
53
54 ComplexType::ComplexType(ComplexType & other)
55 : SimpleType(other)
56 , top(other.top)
57 , nillable(other.nillable)
58 , enumerated(other.enumerated)
59 , embed(other.embed)
60 , with_union(other.with_union)
61 , first_child(other.first_child)
62 , fromAll(other.fromAll)
63 , max_alt(other.max_alt)
64 , skipback(other.skipback)
65 , lastType(other.lastType)
66 , actualPath(other.actualPath)
67 , actfield(this)
68 , nameDep(other.nameDep)
69 , nillable_field(NULL)
70 , basefield(NULL)
71 , cmode(other.cmode)
72 , resolved(other.resolved)
73 , parentTypeSubsGroup(other.parentTypeSubsGroup) {
74 type.originalValueWoPrefix = other.type.originalValueWoPrefix;
75 for (List<AttributeType*>::iterator attr = other.attribfields.begin(); attr; attr = attr->Next) {
76 attribfields.push_back(new AttributeType(*attr->Data));
77 attribfields.back()->parent = this;
78 }
79
80 for (List<ComplexType*>::iterator field = other.complexfields.begin(); field; field = field->Next) {
81 complexfields.push_back(new ComplexType(*field->Data));
82 complexfields.back()->parent = this;
83 if(field->Data == other.basefield){
84 basefield = complexfields.back();
85 }else if(field->Data == other.nillable_field){
86 nillable_field = complexfields.back();
87 }
88 }
89
90 if (other.nameDep != NULL) {
91 SimpleType* dep = other.nameDep;
92 if(dep->getSubstitution() != NULL){
93 dep->getSubstitution()->addToNameDepList(this);
94 nameDep = dep->getSubstitution();
95 }else {
96 other.nameDep->addToNameDepList(this);
97 }
98 }
99 }
100
101 ComplexType::ComplexType(ComplexType * other)
102 : SimpleType(other->getParser(), other->getModule(), c_unknown)
103 , top(false)
104 , nillable(false)
105 , enumerated(false)
106 , embed(false)
107 , with_union(false)
108 , first_child(false)
109 , fromAll(false)
110 , max_alt(0)
111 , skipback(0)
112 , lastType()
113 , actualPath(empty_string)
114 , actfield(this)
115 , nameDep(NULL)
116 , nillable_field(NULL)
117 , basefield(NULL)
118 , cmode(CT_undefined_mode)
119 , resolved(No)
120 , parentTypeSubsGroup(NULL)
121 , complexfields()
122 , attribfields()
123 , enumfields()
124 , tagNames() {
125 xsdtype = n_complexType;
126 parent = other;
127 outside_reference = ReferenceData();
128 }
129
130 ComplexType::ComplexType(const SimpleType & other, CT_fromST c)
131 : SimpleType(other)
132 , top(true)
133 , nillable(false)
134 , enumerated(false)
135 , embed(false)
136 , with_union(false)
137 , first_child(false)
138 , fromAll(false)
139 , max_alt(0)
140 , skipback(0)
141 , lastType()
142 , actualPath(empty_string)
143 , actfield(this)
144 , nameDep(NULL)
145 , nillable_field(NULL)
146 , basefield(NULL)
147 , cmode(CT_simpletype_mode)
148 , resolved(No)
149 , parentTypeSubsGroup(NULL)
150 , complexfields()
151 , attribfields()
152 , enumfields()
153 , tagNames() {
154
155 if(c != fromTagSubstitution && c != fromTypeSubstitution){
156 module->replaceLastMainType(this);
157 module->setActualXsdConstruct(c_complexType);
158 }
159 construct = c_complexType;
160
161 switch (c) {
162 case fromTagUnion:
163 type.upload(Mstring("union"));
164 with_union = true;
165 xsdtype = n_union;
166 break;
167 case fromTagNillable:
168 addVariant(V_useNil);
169 type.upload(Mstring("record"));
170 break;
171 case fromTagComplexType:
172 type.upload(Mstring("record"));
173 xsdtype = n_complexType;
174 break;
175 case fromTagSubstitution:
176 type.upload(Mstring("union"));
177 name.upload(getName().originalValueWoPrefix + Mstring("_group"));
178 xsdtype = n_union;
179 subsGroup = this;
180 variant.clear();
181 hidden_variant.clear();
182 enumeration.modified = false;
183 value.modified = false;
184 pattern.modified = false;
185 length.modified = false;
186 whitespace.modified = false;
187 break;
188 case fromTypeSubstitution:
189 type.upload(Mstring("union"));
190 name.upload(getName().originalValueWoPrefix + Mstring("_derivations"));
191 xsdtype = n_union;
192 substitutionGroup = empty_string;
193 typeSubsGroup = this;
194 variant.clear();
195 hidden_variant.clear();
196 enumeration.modified = false;
197 value.modified = false;
198 pattern.modified = false;
199 length.modified = false;
200 whitespace.modified = false;
201 }
202 }
203
204 ComplexType::~ComplexType() {
205 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
206 delete field->Data;
207 field->Data = NULL;
208 }
209 complexfields.clear();
210
211 for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
212 delete field->Data;
213 field->Data = NULL;
214 }
215 attribfields.clear();
216 }
217
218 void ComplexType::loadWithValues() {
219 //Find the last field where the tag is found
220 if (this != actfield) {
221 actfield->loadWithValues();
222 return;
223 }
224
225 const XMLParser::TagAttributes & atts = parser->getActualTagAttributes();
226
227 switch (parser->getActualTagName()) {
228 case n_sequence:
229 if (!top && xsdtype != n_sequence && xsdtype != n_complexType && xsdtype != n_extension && xsdtype != n_restriction && xsdtype != n_element) {
230 //Create new record
231 ComplexType * rec = new ComplexType(this);
232 rec->type.upload(Mstring("record"));
233 rec->name.upload(Mstring("sequence"));
234 rec->addVariant(V_untagged);
235 rec->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
236 rec->setXsdtype(n_sequence);
237 complexfields.push_back(rec);
238 actfield = rec;
239 } else {
240 //Do not create new record, it is an embedded sequence
241 if (xsdtype == n_sequence && atts.minOccurs == 1 && atts.maxOccurs == 1) {
242 skipback += 1;
243 }
244 type.upload(Mstring("record"));
245 xsdtype = n_sequence;
246 setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
247 }
248 break;
249 case n_choice:
250 if (!top || xsdtype != n_group) {
251 //Create new union field
252 ComplexType * choice = new ComplexType(this);
253 choice->type.upload(Mstring("union"));
254 choice->name.upload(Mstring("choice"));
255 choice->setXsdtype(n_choice);
256 choice->addVariant(V_untagged);
257 choice->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
258 actfield = choice;
259 complexfields.push_back(choice);
260 } else {
261 xsdtype = n_choice;
262 type.upload(Mstring("union"));
263 }
264 break;
265 case n_all:
266 {
267 //Create the record of enumerated field
268 xsdtype = n_all;
269 ComplexType * enumField = new ComplexType(this);
270 enumField->setTypeValue(Mstring("enumerated"));
271 enumField->setNameValue(Mstring("order"));
272 enumField->setBuiltInBase(Mstring("string"));
273 enumField->enumerated = true;
274 enumField->setMinMaxOccurs(0, ULLONG_MAX, false);
275 setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
276 addVariant(V_useOrder);
277 complexfields.push_back(enumField);
278 if (atts.minOccurs == 0) {
279 isOptional = true;
280 }
281 break;
282 }
283 case n_restriction:
284 mode = restrictionMode;
285 //If it is an xsd:union then call SimpleType::loadWithValues
286 if (parent != NULL && parent->with_union) {
287 SimpleType::loadWithValues();
288 break;
289 }
290 if (cmode == CT_simpletype_mode) {
291 //if it is from a SimpleType, then create a base field
292 ComplexType * f = new ComplexType(this);
293 f->name.upload(Mstring("base"));
294 f->type.upload(atts.base);
295 f->setReference(atts.base);
296 f->addVariant(V_untagged);
297 complexfields.push_back(f);
298 basefield = f;
299 actfield = f;
300
301 // If it is a restriction of a list, then no new basefield will be
302 // present, to we apply the references to the parent.
303 if(parent != NULL && parent->inList) {
304 parent->applyReference(*f, true);
305 }
306 } else if (cmode == CT_complextype_mode) {
307 setReference(atts.base);
308 xsdtype = n_restriction;
309 }
310 break;
311 case n_extension:
312 mode = extensionMode;
313 if (cmode == CT_simpletype_mode) {
314 //if it is from a SimpleType, then create a base field
315 ComplexType * f = new ComplexType(this);
316 f->name.upload(Mstring("base"));
317 f->type.upload(atts.base);
318 f->setReference(atts.base);
319 f->addVariant(V_untagged);
320 complexfields.push_back(f);
321 basefield = f;
322 actfield = f;
323 } else if (cmode == CT_complextype_mode) {
324 setReference(atts.base);
325 xsdtype = n_extension;
326 }
327 break;
328 case n_element:
329 {
330 if (atts.nillable) {
331 if(cmode == CT_simpletype_mode){
332 //If a simple top level element is nillable
333 ComplexType * nilrec = new ComplexType(this);
334 if (atts.type.empty()) {
335 nilrec->type.upload(Mstring("record"));
336 } else {
337 nilrec->type.upload(atts.type);
338 }
339 nilrec->name.upload(Mstring("content"));
340 nilrec->isOptional = true;
341 nilrec->nillable = true;
342 setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
343 complexfields.push_back(nilrec);
344 type.upload(Mstring("record"));
345 name.upload(atts.name);
346 actfield = nilrec;
347 nillable_field = nilrec;
348 } else {
349 //From a complexType element is nillable
350 ComplexType * record = new ComplexType(this);
351 ComplexType * nilrec = new ComplexType(record);
352 if (atts.type.empty()) {
353 nilrec->type.upload(Mstring("record"));
354 } else {
355 nilrec->type.upload(atts.type);
356 }
357 record->name.upload(atts.name);
358 record->type.upload(Mstring("record"));
359 record->complexfields.push_back(nilrec);
360 record->addVariant(V_useNil);
361 record->nillable_field = nilrec;
362 record->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
363
364 nilrec->name.upload(Mstring("content"));
365 nilrec->nillable = true;
366 nilrec->isOptional = true;
367 nilrec->tagNames.push_back(parser->getActualTagName());
368 complexfields.push_back(record);
369 actfield = nilrec;
370 }
371 }else {
372 //It is a simple element
373 ComplexType* c = new ComplexType(this);
374 c->setXsdtype(n_element);
375 c->type.upload(atts.type);
376 c->name.upload(atts.name);
377 c->setReference(atts.type);
378 c->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
379 c->applyDefaultAttribute(atts.default_);
380 c->applyFixedAttribute(atts.fixed);
381 c->setElementFormAs(atts.form);
382 if (atts.ref.empty()) {
383 c->setReference(atts.type);
384 } else {
385 c->applyRefAttribute(atts.ref);
386 c->name.upload(atts.ref.getValueWithoutPrefix(':'));
387 c->type.upload(atts.ref);
388 }
389 c->applySubstitionGroupAttribute(atts.substitionGroup);
390 c->applyBlockAttribute(atts.block);
391 actfield = c;
392
393 //Inside all have some special conditions
394 if (xsdtype == n_all) {
395 if (atts.minOccurs > 1) {
396 printError(getModule()->getSchemaname(), name.convertedValue,
397 Mstring("Inside <all>, minOccurs must be 0 or 1"));
398 TTCN3ModuleInventory::incrNumErrors();
399 }
400 if (atts.maxOccurs != 1) {
401 printError(getModule()->getSchemaname(), name.convertedValue,
402 Mstring("Inside <all>, maxOccurs must be 1"));
403 TTCN3ModuleInventory::incrNumErrors();
404 }
405 c->fromAll = true;
406 complexfields.push_back(c);
407 if (isOptional) {
408 c->isOptional = true;
409 }
410 } else {
411 complexfields.push_back(c);
412 }
413 }
414 break;
415 }
416 case n_attribute:
417 {
418 AttributeType * attribute = new AttributeType(this);
419 attribute->addVariant(V_attribute);
420 attribute->applyMinMaxOccursAttribute(0, 1);
421 attribute->setXsdtype(n_attribute);
422 attribute->applyDefaultAttribute(atts.default_);
423 attribute->applyFixedAttribute(atts.fixed);
424 attribute->setUseVal(atts.use);
425 attribute->setAttributeFormAs(atts.form);
426 lastType = n_attribute;
427 if (atts.ref.empty()) {
428 attribute->setNameOfField(atts.name);
429 attribute->setTypeOfField(atts.type);
430 attribute->setReference(atts.type, true);
431 } else {
432 attribute->applyRefAttribute(atts.ref);
433 }
434 actfield = attribute;
435
436 //In case of nillable parent it is difficult...
437 if (nillable && parent != NULL) {
438 parent->attribfields.push_back(attribute);
439 attribute->parent = parent;
440 } else if (nillable && !complexfields.empty() && parent == NULL) {
441 complexfields.back()->attribfields.push_back(attribute);
442 } else if (parent != NULL && (parent->mode == extensionMode || parent->mode == restrictionMode) && name.convertedValue == Mstring("base")) {
443 parent->attribfields.push_back(attribute);
444 attribute->parent = parent;
445 } else {
446 attribfields.push_back(attribute);
447 }
448 break;
449 }
450 case n_any:
451 {
452 ComplexType * any = new ComplexType(this);
453 any->name.upload(Mstring("elem"));
454 any->type.upload(Mstring("xsd:string"));
455 any->applyNamespaceAttribute(V_anyElement, atts.namespace_);
456 any->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
457 any->setXsdtype(n_any);
458 complexfields.push_back(any);
459 break;
460 }
461 case n_anyAttribute:
462 {
463 AttributeType * anyattr = new AttributeType(this);
464 anyattr->setXsdtype(n_anyAttribute);
465 anyattr->setNameOfField(Mstring("attr"));
466 anyattr->setTypeValue(Mstring("xsd:string"));
467 anyattr->setToAnyAttribute();
468 anyattr->applyMinMaxOccursAttribute(0, ULLONG_MAX);
469 anyattr->addNameSpaceAttribute(atts.namespace_);
470 actfield = anyattr;
471
472 //In case of nillable parent it is difficult...
473 if (nillable && parent != NULL) {
474 parent->attribfields.push_back(anyattr);
475 anyattr->parent = parent;
476 } else if (nillable && !complexfields.empty() && parent == NULL) {
477 complexfields.back()->attribfields.push_back(anyattr);
478 } else if (parent != NULL && (parent->mode == extensionMode || parent->mode == restrictionMode) && name.convertedValue == Mstring("base")) {
479 parent->attribfields.push_back(anyattr);
480 anyattr->parent = parent;
481 } else {
482 attribfields.push_back(anyattr);
483 }
484 break;
485 }
486 case n_attributeGroup:
487 if (!atts.ref.empty()) {
488 ComplexType * g = new ComplexType(this);
489 g->setXsdtype(n_attributeGroup);
490 g->setReference(atts.ref);
491 complexfields.push_back(g);
492 actfield = g;
493 } else {
494 xsdtype = n_attributeGroup;
495 name.upload(Mstring(atts.name));
496 setInvisible();
497 }
498 break;
499 case n_group:
500 if (atts.ref.empty()) {
501 //It is a definition
502 xsdtype = n_group;
503 name.upload(atts.name);
504 } else {
505 //It is a reference
506 ComplexType* group = new ComplexType(this);
507 group->setXsdtype(n_group);
508 group->name.upload(atts.name);
509 group->setReference(Mstring(atts.ref));
510 group->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
511 complexfields.push_back(group);
512 actfield = group;
513 }
514 break;
515 case n_union:
516 {
517 with_union = true;
518 xsdtype = n_union;
519 type.upload(Mstring("union"));
520 addVariant(V_useUnion);
521 if (!atts.memberTypes.empty()) {
522 List<Mstring> types;
523 //Get the union values
524 expstring_t valueToSplitIntoTokens = mcopystr(atts.memberTypes.c_str());
525 char * token;
526 token = strtok(valueToSplitIntoTokens, " ");
527 while (token != NULL) {
528 types.push_back(Mstring(token));
529 token = strtok(NULL, " ");
530 }
531 Free(valueToSplitIntoTokens);
532
533 //Create the union elements and push into the container
534 for (List<Mstring>::iterator memberType = types.begin(); memberType; memberType = memberType->Next) {
535 Mstring tmp_name = memberType->Data.getValueWithoutPrefix(':');
536 ComplexType * f = new ComplexType(this);
537 f->name.upload(tmp_name);
538 f->type.upload(memberType->Data);
539 f->setXsdtype(n_simpleType);
540 f->setReference(memberType->Data);
541 complexfields.push_back(f);
542 }
543 }
544 break;
545 }
546 case n_simpleType:
547 case n_simpleContent:
548 {
549 xsdtype = parser->getActualTagName();
550 cmode = CT_simpletype_mode;
551 Mstring fieldname;
552 if (with_union) {
553 if (max_alt == 0) {
554 fieldname = Mstring("alt_");
555 } else {
556 fieldname = mprintf("alt_%d", max_alt);
557 }
558 max_alt++;
559 ComplexType * field = new ComplexType(this);
560 field->name.upload(fieldname);
561 field->setXsdtype(n_simpleType);
562 field->addVariant(V_nameAs, empty_string, true);
563 complexfields.push_back(field);
564 actfield = field;
565 }
566 break;
567 }
568 case n_complexType:
569 name.upload(atts.name);
570 type.upload(Mstring("record"));
571 applyAbstractAttribute(atts.abstract);
572 applySubstitionGroupAttribute(atts.substitionGroup);
573 applyBlockAttribute(atts.block);
574 // fall through
575 case n_complexContent:
576 tagNames.push_back(parser->getActualTagName());
577 cmode = CT_complextype_mode;
578 if (atts.mixed) {
579 ComplexType * mixed = new ComplexType(this);
580 mixed->name.upload(Mstring("embed_values"));
581 mixed->type.upload(Mstring("xsd:string"));
582 mixed->setMinMaxOccurs(0, ULLONG_MAX, false);
583 mixed->embed = true;
584 complexfields.push_back(mixed);
585 addVariant(V_embedValues);
586 }
587 break;
588 case n_list:
589 if (parent != NULL && parent->basefield == this) {
590 parent->inList = true;
591 parent->SimpleType::loadWithValues();
592 parent->basefield = NULL;
593 setInvisible();
594 } else if(parent != NULL) {
595 SimpleType::loadWithValues();
596 }
597 break;
598 case n_length:
599 case n_minLength:
600 case n_maxLength:
601 case n_pattern:
602 case n_enumeration:
603 case n_whiteSpace:
604 case n_minInclusive:
605 case n_maxInclusive:
606 case n_minExclusive:
607 case n_maxExclusive:
608 case n_totalDigits:
609 case n_fractionDigits:
610 SimpleType::loadWithValues();
611 break;
612 case n_label:
613 addComment(Mstring("LABEL:"));
614 break;
615 case n_definition:
616 addComment(Mstring("DEFINITION:"));
617 break;
618 default:
619 break;
620 }
621 }
622
623 // called from endelementHandler
624 void ComplexType::modifyValues() {
625 if (this != actfield) {
626 actfield->modifyValues();
627 return;
628 }
629 if (xsdtype == n_sequence) {
630 skipback = skipback - 1;
631 }
632
633
634 if ( parent != NULL &&
635 (xsdtype == n_element ||
636 xsdtype == n_complexType ||
637 xsdtype == n_complexContent ||
638 xsdtype == n_all ||
639 xsdtype == n_attribute ||
640 xsdtype == n_anyAttribute ||
641 xsdtype == n_choice ||
642 xsdtype == n_group ||
643 xsdtype == n_attributeGroup ||
644 xsdtype == n_extension ||
645 xsdtype == n_restriction ||
646 (xsdtype == n_simpleType && !inList) ||
647 xsdtype == n_simpleContent ||
648 (xsdtype == n_sequence && skipback < 0)
649 )) {
650 if (!tagNames.empty() && tagNames.back() == parser->getParentTagName()) {
651 if (nillable && tagNames.back() == n_element) {
652 parent->modifyValues();
653 }
654 tagNames.pop_back();
655 } else if (tagNames.empty()) {
656 parent->actfield = parent;
657 parent->lastType = xsdtype;
658 }
659 }
660 if (xsdtype == n_simpleType) {
661 inList = false;
662 }
663 }
664
665 void ComplexType::referenceResolving() {
666 if (resolved != No) return; // nothing to do
667 if(this == subsGroup){
668 resolved = Yes;
669 return;
670 }
671 resolved = InProgress;
672 for (List<ComplexType*>::iterator ct = complexfields.begin(); ct; ct = ct->Next) {
673 // Referenece resolving of ComplexTypes
674 ct->Data->referenceResolving();
675 }
676 for (List<AttributeType*>::iterator attr = attribfields.begin(); attr; attr = attr->Next) {
677 //Reference resolving for Attributes
678 resolveAttribute(attr->Data);
679 }
680
681 reference_resolving_funtion();
682
683 if(!substitutionGroup.empty()){
684 addToSubstitutions();
685 }
686 resolved = Yes;
687 }
688
689 void ComplexType::reference_resolving_funtion() {
690 //Every child element references are resolved here.
691 if (outside_reference.empty() && basefield == NULL) {
692 //Its not in the resolveElement function because we need the built in type
693 //reference too, and then the outside_reference is empty.
694 if(xsdtype == n_element){
695 collectElementTypes(NULL, NULL);
696 }
697 return;
698 }
699
700 SimpleType * st = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(this, want_BOTH);
701 if (st == NULL && basefield == NULL) {
702 printError(module->getSchemaname(), name.convertedValue,
703 "Reference for a non-defined type: " + getReference().repr());
704 TTCN3ModuleInventory::getInstance().incrNumErrors();
705 outside_reference.set_resolved(NULL);
706 return;
707 }
708
709 resolveAttributeGroup(st);
710
711 resolveGroup(st);
712
713 resolveElement(st);
714
715 resolveSimpleTypeExtension();
716
717 resolveSimpleTypeRestriction();
718
719 resolveComplexTypeExtension();
720
721 resolveComplexTypeRestriction();
722
723 resolveUnion(st);
724
725 addToTypeSubstitutions();
726
727 }
728
729 void ComplexType::setParent(ComplexType * par, SimpleType * child) {
730 child->parent = par;
731 }
732
733 void ComplexType::applyReference(const SimpleType & other, const bool on_attributes) {
734 type.convertedValue = other.getType().convertedValue;
735 type.originalValueWoPrefix = other.getType().convertedValue.getValueWithoutPrefix(':');
736
737 if (other.getMinOccurs() > getMinOccurs() ||
738 other.getMaxOccurs() < getMaxOccurs()) {
739 if (!on_attributes) {
740 expstring_t temp = memptystr();
741 temp = mputprintf(
742 temp,
743 "The occurrence range (%llu .. %llu) of the element (%s) is not compatible "
744 "with the occurrence range (%llu .. %llu) of the referenced element.",
745 getMinOccurs(),
746 getMaxOccurs(),
747 name.originalValueWoPrefix.c_str(),
748 other.getMinOccurs(),
749 other.getMaxOccurs());
750 printError(module->getSchemaname(), parent->getName().originalValueWoPrefix,
751 Mstring(temp));
752 Free(temp);
753 TTCN3ModuleInventory::getInstance().incrNumErrors();
754 }
755 } else {
756 setMinOccurs(llmax(getMinOccurs(), other.getMinOccurs()));
757 setMaxOccurs(llmin(getMaxOccurs(), other.getMaxOccurs()));
758 }
759
760 for (List<Mstring>::iterator var = other.getVariantRef().begin(); var; var = var->Next) {
761 bool found = false;
762 for (List<Mstring>::iterator var1 = variant.begin(); var1; var1 = var1->Next) {
763 if (var->Data == var1->Data) {
764 found = true;
765 break;
766 }
767 }
768 if (!found) {
769 variant.push_back(var->Data);
770 variant_ref.push_back(var->Data);
771 }
772 }
773
774 builtInBase = other.getBuiltInBase();
775
776 length.applyReference(other.getLength());
777 pattern.applyReference(other.getPattern());
778 enumeration.applyReference(other.getEnumeration());
779 whitespace.applyReference(other.getWhitespace());
780 value.applyReference(other.getValue());
781 }
782
783 void ComplexType::nameConversion(NameConversionMode conversion_mode, const List<NamespaceType> & ns) {
784 if(!visible) return;
785 switch (conversion_mode) {
786 case nameMode:
787 nameConversion_names(ns);
788 break;
789 case typeMode:
790 nameConversion_types(ns);
791 break;
792 case fieldMode:
793 nameConversion_fields(ns);
794 break;
795 }
796 }
797
798 void ComplexType::nameConversion_names(const List<NamespaceType> &) {
799 Mstring res, var(module->getTargetNamespace());
800 XSDName2TTCN3Name(name.convertedValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_name, res, var);
801 name.convertedValue = res;
802 bool found = false;
803 for (List<Mstring>::iterator vari = variant.begin(); vari; vari = vari->Next) {
804 if (vari->Data == "\"untagged\"") {
805 found = true;
806 break;
807 }
808 }
809 if (!found) {
810 addVariant(V_onlyValue, var);
811 }
812 for (List<SimpleType*>::iterator dep = nameDepList.begin(); dep; dep = dep->Next) {
813 dep->Data->setTypeValue(res);
814 }
815 }
816
817 void ComplexType::nameConversion_types(const List<NamespaceType> & ns) {
818 attribfields.sort(compareAttributeNameSpaces);
819 attribfields.sort(compareAttributeTypes);
820 for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
821 field->Data->nameConversion(typeMode, ns);
822 }
823
824 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
825 field->Data->nameConversion_types(ns);
826 }
827
828 Mstring prefix, uri, typeValue;
829
830 if (type.convertedValue == "record" ||
831 type.convertedValue == "set" ||
832 type.convertedValue == "union" ||
833 type.convertedValue == "enumerated") {
834 return;
835 }
836
837 prefix = type.convertedValue.getPrefix(':');
838 typeValue = type.convertedValue.getValueWithoutPrefix(':');
839
840 for (List<NamespaceType>::iterator namesp = ns.begin(); namesp; namesp = namesp->Next) {
841 if (prefix == namesp->Data.prefix) {
842 uri = namesp->Data.uri;
843 break;
844 }
845 }
846
847 QualifiedName in(uri, typeValue); // ns uri + original name
848
849 // Check all known types
850 QualifiedNames::iterator origTN = TTCN3ModuleInventory::getInstance().getTypenames().begin();
851 for (; origTN; origTN = origTN->Next) {
852 if (origTN->Data == in) {
853 QualifiedName tmp_name(module->getTargetNamespace(), name.convertedValue);
854 if (origTN->Data != tmp_name){
855 break;
856 }
857 }
858 }
859
860 if (origTN != NULL) {
861 setTypeValue(origTN->Data.name);
862 } else {
863 Mstring res, var;
864 XSDName2TTCN3Name(typeValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var, type.no_replace);
865 setTypeValue(res);
866 }
867 }
868
869 void ComplexType::nameConversion_fields(const List<NamespaceType> & ns) {
870 QualifiedNames used_field_names;
871
872 for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
873 field->Data->nameConversion_names(used_field_names);
874 }
875
876 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
877 if (field->Data->getMinOccurs() == 0 && field->Data->getMaxOccurs() == 0) {
878 continue;
879 }
880 if (!field->Data->isVisible()) {
881 continue;
882 }
883
884 field->Data->nameConversion_fields(ns);
885
886 Mstring prefix = field->Data->getType().convertedValue.getPrefix(':');
887 Mstring typeValue = field->Data->getType().convertedValue.getValueWithoutPrefix(':');
888
889 Mstring res, var;
890 var = getModule()->getTargetNamespace();
891 XSDName2TTCN3Name(typeValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var);
892
893 field->Data->addVariant(V_onlyValue, var);
894 var = getModule()->getTargetNamespace();
895
896 if (field->Data->getName().list_extension) {
897 field->Data->useNameListProperty();
898 XSDName2TTCN3Name(field->Data->getName().convertedValue,
899 used_field_names, field_name, res, var);
900 field->Data->setNameValue(res);
901 bool found_in_variant = false;
902 for (List<Mstring>::iterator vari = field->Data->getVariant().begin(); vari; vari = vari->Next) {
903 if (vari->Data == Mstring("\"untagged\"")) {
904 found_in_variant = true;
905 break;
906 }
907 }
908 if (!field->Data->getName().originalValueWoPrefix.empty() &&
909 field->Data->getName().originalValueWoPrefix != "sequence" &&
910 field->Data->getName().originalValueWoPrefix != "choice" &&
911 field->Data->getName().originalValueWoPrefix != "elem" &&
912 !found_in_variant) {
913 field->Data->addVariant(V_nameAs, field->Data->getName().originalValueWoPrefix);
914 }
915
916
917 if (!found_in_variant) {
918 field->Data->addVariant(V_untagged, empty_string, true);
919 }
920 } else {
921 XSDName2TTCN3Name(field->Data->getName().convertedValue,
922 used_field_names, field_name, res, var);
923 field->Data->setNameValue(res);
924 field->Data->addVariant(V_onlyValue, var);
925 }
926
927 }
928 }
929
930 void ComplexType::setFieldPaths(Mstring path) {
931 if (path.empty()) {
932 if (!top) {
933 Mstring field_prefix = empty_string;
934 if(parent->getMinOccurs() == 0 && parent->getMaxOccurs() == ULLONG_MAX){
935 field_prefix = "[-].";
936 }
937 path = field_prefix + getName().convertedValue;
938 actualPath = field_prefix + getName().convertedValue;
939 }else {
940 actualPath = getName().convertedValue;
941 }
942 } else if (parent != NULL && (parent->getMinOccurs() != 1 || parent->getMaxOccurs() != 1) &&
943 (parent->getName().list_extension || parent->mode == listMode)) {
944 path = path + Mstring("[-].") + getName().convertedValue;
945 actualPath = path;
946 } else {
947 path = path + Mstring(".") + getName().convertedValue;
948 actualPath = path;
949 }
950
951 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
952 field->Data->setFieldPaths(path);
953 }
954 for (List<AttributeType*>::iterator attr = attribfields.begin(); attr; attr = attr->Next) {
955 attr->Data->setFieldPath(path);
956 }
957 }
958
959 void ComplexType::finalModification2() {
960 //Call SimpleType finalModification
961 SimpleType::finalModification();
962
963 //Set isOptional field
964 isOptional = isOptional || (getMinOccurs() == 0 && getMaxOccurs() == 1);
965
966 //
967 List<Mstring> enumNames;
968 for (List<ComplexType*>::iterator field = complexfields.begin(), nextField; field; field = nextField) {
969 nextField = field->Next;
970 //Remove invisible fields
971 if ((field->Data->getMinOccurs() == 0 && field->Data->getMaxOccurs() == 0) || !field->Data->isVisible()) {
972 delete field->Data;
973 field->Data = NULL;
974 complexfields.remove(field);
975 } else {
976 //Recursive call
977 field->Data->finalModification2();
978 //collect <xsd:all> elements
979 if (field->Data->fromAll) {
980 enumNames.push_back(field->Data->getName().convertedValue);
981 }
982 }
983 }
984
985 ComplexType * embedField = NULL;
986 ComplexType * enumField = NULL;
987
988 //Find the embed and order fields, and remove them
989 for (List<ComplexType*>::iterator field = complexfields.begin(), nextField; field; field = nextField) {
990 nextField = field->Next;
991 if (field->Data->embed) {
992 embedField = new ComplexType(*field->Data);
993 embedField->parent = this;
994 delete field->Data;
995 field->Data = NULL;
996 complexfields.remove(field);
997 } else if (field->Data->enumerated) {
998 enumField = new ComplexType(*field->Data);
999 enumField->parent = this;
1000 delete field->Data;
1001 field->Data = NULL;
1002 complexfields.remove(field);
1003 }
1004 }
1005
1006 if (enumField != NULL) {
1007 //Insert the order field in the front
1008 complexfields.push_front(enumField);
1009 //Push the field names into the order field
1010 for (List<Mstring>::iterator field = enumNames.begin(); field; field = field->Next) {
1011 enumField->enumfields.push_back(field->Data);
1012 }
1013 }
1014
1015 if (embedField != NULL) {
1016 //Insert the embed field to the front
1017 complexfields.push_front(embedField);
1018 }
1019
1020 if (with_union) {
1021 unsigned number = 0;
1022 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
1023 if (field->Data->name.convertedValue.foundAt("alt_") == field->Data->name.convertedValue.c_str()) {
1024 if (number == 0) {
1025 field->Data->name.upload(Mstring("alt_"));
1026 } else {
1027 field->Data->name.upload(Mstring(mprintf("alt_%d", number)));
1028 }
1029 number++;
1030 }
1031 }
1032 }
1033
1034 AttributeType * anyAttr = NULL;
1035 for (List<AttributeType*>::iterator field = attribfields.begin(), nextField; field; field = nextField) {
1036 nextField = field->Next;
1037 field->Data->applyUseAttribute();
1038 //Find anyattribute, and remove it
1039 if (field->Data->isAnyAttribute()) {
1040 anyAttr = new AttributeType(*field->Data);
1041 setParent(this, anyAttr);
1042 delete field->Data;
1043 field->Data = NULL;
1044 attribfields.remove(field);
1045 } else if (field->Data->getUseVal() == prohibited || !field->Data->isVisible()) {
1046 //Not visible attribute removed
1047 delete field->Data;
1048 field->Data = NULL;
1049 attribfields.remove(field);
1050 } else {
1051 field->Data->SimpleType::finalModification();
1052 }
1053 }
1054
1055 //Push anyattribute to the front
1056 if (anyAttr != NULL) {
1057 anyAttr->applyNamespaceAttribute(V_anyAttributes);
1058 attribfields.push_back(anyAttr);
1059 }
1060
1061 //Substitution group ordering
1062 if(subsGroup == this || typeSubsGroup == this){ //We are a generated substitution group
1063 //Substitution group never empty
1064 ComplexType * front = complexfields.front();
1065 List<ComplexType*>::iterator it = complexfields.begin();
1066 complexfields.remove(it);
1067 complexfields.sort(compareComplexTypeNameSpaces);
1068 complexfields.sort(compareTypes);
1069 complexfields.push_front(front);
1070 }
1071 }
1072
1073 void ComplexType::finalModification() {
1074 finalModification2();
1075 setFieldPaths(empty_string);
1076 List<Mstring> container;
1077 collectVariants(container);
1078 variant.clear();
1079 variant = container;
1080 }
1081
1082 void ComplexType::printToFile(FILE * file) {
1083 printToFile(file, 0, false);
1084 }
1085
1086 void ComplexType::printToFile(FILE * file, const unsigned level, const bool is_union) {
1087 if (!isVisible()) {
1088 return;
1089 }
1090 printComment(file, level);
1091 if (top) {
1092 fprintf(file, "type ");
1093 if(mode == listMode){
1094 printMinOccursMaxOccurs(file, is_union);
1095 fprintf(file, "%s", type.convertedValue.c_str());
1096 }else {
1097 fprintf(file, "%s %s", type.convertedValue.c_str(), name.convertedValue.c_str());
1098 }
1099 fprintf(file, "\n{\n");
1100
1101 if (attribfields.empty() && complexfields.empty()) {
1102 fprintf(file, "\n");
1103 }
1104
1105 for (List<ComplexType*>::iterator c = complexfields.begin(), nextField; c; c = nextField) {
1106 nextField = c->Next;
1107 if (c->Data->embed || c->Data->enumerated) {
1108 c->Data->printToFile(file, level + 1, is_union);
1109 if (c->Next != NULL || !attribfields.empty()) {
1110 fprintf(file, ",\n");
1111 } else {
1112 fprintf(file, "\n");
1113 }
1114 delete c->Data;
1115 c->Data = NULL;
1116 complexfields.remove(c);
1117 }
1118 }
1119
1120 for (List<AttributeType*>::iterator f = attribfields.begin(); f; f = f->Next) {
1121 f->Data->printToFile(file, level + 1);
1122 if (f->Next != NULL || !complexfields.empty()) {
1123 fprintf(file, ",\n");
1124 } else {
1125 fprintf(file, "\n");
1126 }
1127 }
1128
1129 for (List<ComplexType*>::iterator c = complexfields.begin(); c; c = c->Next) {
1130 c->Data->printToFile(file, level + 1, is_union);
1131 if (c->Next != NULL) {
1132 fprintf(file, ",\n");
1133 } else {
1134 fprintf(file, "\n");
1135 }
1136 }
1137 } else {
1138 const bool field_is_record = getType().convertedValue == Mstring("record");
1139 const bool field_is_union = getType().convertedValue == "union";
1140 if (complexfields.empty() && attribfields.empty() && (field_is_record || field_is_union)) {
1141 if (field_is_record) {
1142 indent(file, level);
1143 printMinOccursMaxOccurs(file, is_union);
1144 fprintf(file, "%s {\n", getType().convertedValue.c_str());
1145 indent(file, level);
1146 fprintf(file, "} %s", getName().convertedValue.c_str());
1147 if (isOptional) {
1148 fprintf(file, " optional");
1149 }
1150 } else if (field_is_union) {
1151 indent(file, level);
1152 printMinOccursMaxOccurs(file, is_union);
1153 fprintf(file, "%s {\n", getType().convertedValue.c_str());
1154 indent(file, level + 1);
1155 fprintf(file, "record length(0 .. 1) of enumerated { NULL_ } choice\n");
1156 indent(file, level);
1157 fprintf(file, "} %s", getName().convertedValue.c_str());
1158 if (isOptional) {
1159 fprintf(file, " optional");
1160 }
1161 }
1162 } else {
1163 indent(file, level);
1164 if (getEnumeration().modified) {
1165 if (isFloatType(getBuiltInBase())) {
1166 fprintf(file, "%s (", type.convertedValue.c_str());
1167 getEnumeration().sortFacets();
1168 getEnumeration().printToFile(file);
1169 fprintf(file, ")");
1170 } else {
1171 printMinOccursMaxOccurs(file, with_union);
1172 fprintf(file, "enumerated {\n");
1173 //getEnumeration().sortFacets();
1174 getEnumeration().printToFile(file, level);
1175 fprintf(file, "\n");
1176 indent(file, level);
1177 fprintf(file, "} ");
1178 }
1179 } else {
1180 int multiplicity = multi(module, getReference(), this);
1181 if ((multiplicity > 1) && getReference().get_ref()) {
1182 fprintf(file, "%s.", getReference().get_ref()->getModule()->getModulename().c_str());
1183 }
1184 if (field_is_record || field_is_union) {
1185 printMinOccursMaxOccurs(file, with_union, !first_child || parent->getXsdtype() != n_choice);
1186 fprintf(file, "%s {\n", getType().convertedValue.c_str());
1187 for (List<AttributeType*>::iterator f = attribfields.begin(); f; f = f->Next) {
1188 f->Data->printToFile(file, level + 1);
1189 if (f->Next != NULL || !complexfields.empty()) {
1190 fprintf(file, ",\n");
1191 } else {
1192 fprintf(file, "\n");
1193 }
1194 }
1195
1196 for (List<ComplexType*>::iterator c = complexfields.begin(); c; c = c->Next) {
1197 c->Data->printToFile(file, level + 1, is_union);
1198 if (c->Next != NULL) {
1199 fprintf(file, ",\n");
1200 } else {
1201 fprintf(file, "\n");
1202 }
1203 }
1204 } else {
1205 printMinOccursMaxOccurs(file, with_union, !first_child);
1206 fprintf(file, "%s ", getType().convertedValue.c_str());
1207 if (getName().convertedValue == Mstring("order") && getType().convertedValue == Mstring("enumerated")) {
1208 fprintf(file, "{\n");
1209 for (List<Mstring>::iterator e = enumfields.begin(); e; e = e->Next) {
1210 indent(file, level + 1);
1211 fprintf(file, "%s", e->Data.c_str());
1212 if (e->Next != NULL) {
1213 fprintf(file, ",\n");
1214 } else {
1215 fprintf(file, "\n");
1216 }
1217 }
1218 indent(file, level);
1219 fprintf(file, "} ");
1220 }
1221 }
1222 }
1223 if (field_is_record || field_is_union) {
1224 indent(file, level);
1225 fprintf(file, "} ");
1226 }
1227
1228 fprintf(file, "%s", getName().convertedValue.c_str());
1229 getPattern().printToFile(file);
1230 getValue().printToFile(file);
1231 getLength().printToFile(file);
1232 if (!with_union && isOptional) {
1233 fprintf(file, " optional");
1234 }
1235 }
1236 }
1237
1238 if (top) {
1239 fprintf(file, "}");
1240 if(mode == listMode){
1241 fprintf(file, " %s", name.convertedValue.c_str());
1242 }
1243 printVariant(file);
1244 fprintf(file, ";\n\n\n");
1245 }
1246 }
1247
1248 void ComplexType::collectVariants(List<Mstring>& container) {
1249
1250 if (e_flag_used || !isVisible()) {
1251 return;
1252 }
1253
1254 if (top) {
1255 bool useUnionVariantWhenMainTypeIsRecordOf = false;
1256 for (List<Mstring>::iterator var = variant.end(); var; var = var->Prev) {
1257 if ((getMinOccurs() != 1 || getMaxOccurs() != 1) && (var->Data == "\"useUnion\"")) { // main type is a record of
1258 useUnionVariantWhenMainTypeIsRecordOf = true; // TR HL15893
1259 } else {
1260 container.push_back(Mstring("variant ") + Mstring(var->Data.c_str()) + Mstring(";\n"));
1261 }
1262 }
1263 if (useUnionVariantWhenMainTypeIsRecordOf) {
1264 container.push_back(Mstring("variant ([-]) \"useUnion\";\n"));
1265 }
1266 for (List<Mstring>::iterator var = hidden_variant.end(); var; var = var->Prev) {
1267 container.push_back(Mstring("//variant ") + Mstring(var->Data.c_str()) + Mstring(";\n"));
1268 }
1269 }
1270
1271 //Collect variants of attributes
1272 for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
1273 field->Data->collectVariants(container);
1274 }
1275
1276 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
1277
1278 if (!field->Data->isVisible()) {
1279 continue;
1280 }
1281
1282 if (field->Data->getVariant().empty() && field->Data->getHiddenVariant().empty() &&
1283 field->Data->complexfields.empty() && field->Data->attribfields.empty() &&
1284 field->Data->enumeration.variants.empty()) {
1285 continue;
1286 }
1287
1288 bool already_used = false;
1289
1290 for (List<Mstring>::iterator var2 = field->Data->getVariant().end(); var2; var2 = var2->Prev) {
1291 if (var2->Data == "\"untagged\"" && !already_used) {
1292 container.push_back(Mstring("variant (") + field->Data->actualPath + Mstring(") ") + Mstring(var2->Data.c_str()) + Mstring(";\n"));
1293 already_used = true;
1294 } else {
1295 if ((field->Data->getMinOccurs() != 1 || field->Data->getMaxOccurs() != 1) &&
1296 (field->Data->getName().list_extension || var2->Data == "\"useUnion\"")) {
1297 container.push_back(Mstring("variant (") + field->Data->actualPath + Mstring("[-]) ") + Mstring(var2->Data.c_str()) + Mstring(";\n"));
1298 } else if (var2->Data != "\"untagged\"") {
1299 container.push_back(Mstring("variant (") + field->Data->actualPath + Mstring(") ") + Mstring(var2->Data.c_str()) + Mstring(";\n"));
1300 }
1301 }
1302 }
1303 for (List<Mstring>::iterator hidden_var = field->Data->getHiddenVariant().end();
1304 hidden_var; hidden_var = hidden_var->Prev) {
1305 if ((field->Data->getMinOccurs() != 1 || field->Data->getMaxOccurs() != 1) &&
1306 field->Data->getName().list_extension) {
1307 container.push_back(Mstring("//variant (") + field->Data->actualPath + Mstring("[-]) ") + Mstring(hidden_var->Data.c_str()) + Mstring(";\n"));
1308 } else {
1309 container.push_back(Mstring("//variant (") + field->Data->actualPath + Mstring(") ") + Mstring(hidden_var->Data.c_str()) + Mstring(";\n"));
1310 }
1311 }
1312
1313 if(field->Data->enumeration.modified){
1314 Mstring path = empty_string;
1315 if(field->Data->getMinOccurs() != 1 && field->Data->getMaxOccurs() != 1){
1316 path = field->Data->actualPath + Mstring("[-]");
1317 }else {
1318 path = field->Data->actualPath;
1319 }
1320 for(List<Mstring>::iterator var = field->Data->enumeration.variants.end(); var; var = var->Prev){
1321 if(var->Data.empty()) continue;
1322 container.push_back("variant (" + path + ") " + var->Data + ";\n");
1323 }
1324 }
1325 //Recursive call
1326 field->Data->collectVariants(container);
1327 }
1328 }
1329
1330 void ComplexType::printVariant(FILE * file) {
1331 if (e_flag_used) {
1332 return;
1333 }
1334
1335 bool foundAtLeastOneVariant = false;
1336 bool foundAtLeastOneHiddenVariant = false;
1337
1338 if (!variant.empty()) {
1339 for (List<Mstring>::iterator var = variant.begin(); var; var = var->Next) {
1340 if (foundAtLeastOneVariant && foundAtLeastOneHiddenVariant) {
1341 break;
1342 }
1343 if (var->Data[0] != '/') {
1344 foundAtLeastOneVariant = true;
1345 } else {
1346 foundAtLeastOneHiddenVariant = true;
1347 }
1348 }
1349 }
1350
1351 if (!foundAtLeastOneVariant && !foundAtLeastOneHiddenVariant) {
1352 return;
1353 }
1354
1355 if (!foundAtLeastOneVariant) {
1356 //No other variants, only commented, so the 'with' must be commented also.
1357 fprintf(file, ";\n//with {\n");
1358 } else {
1359 fprintf(file, "\nwith {\n");
1360 }
1361
1362 for (List<Mstring>::iterator var = variant.begin(); var; var = var->Next) {
1363 fprintf(file, " %s", var->Data.c_str());
1364 }
1365
1366 if (!foundAtLeastOneVariant) {
1367 fprintf(file, "//");
1368 }
1369 fprintf(file, "}");
1370 }
1371
1372 void ComplexType::dump(unsigned int depth) const {
1373 fprintf(stderr, "%*s %sComplexType at %p | Top:%s\n", depth * 2, "", isVisible() ? "" : "(hidden)", (const void*) this, top ? "true" : "false");
1374 if (parent != NULL) {
1375 fprintf(stderr, "%*s parent: %p | parent xsdtype: %i | my xsdtype: %i\n", depth * 2, "", (const void*) parent, parent->getXsdtype(), xsdtype);
1376 } else {
1377 fprintf(stderr, "%*s parent: %p | parent xsdtype: %s | my xsdtype: %i\n", depth * 2, "", "NULL", "NULL", xsdtype);
1378 }
1379 fprintf(stderr, "%*s name='%s' -> '%s', type='%s' %d complexfields | %s | %s | %s\n", depth * 2, "",
1380 name.originalValueWoPrefix.c_str(), name.convertedValue.c_str(), type.convertedValue.c_str(), (int) complexfields.size(),
1381 outside_reference.empty() ? "" : outside_reference.get_val().c_str(), mode == restrictionMode ? "restriction" : "",
1382 mode == extensionMode ? "extension" : "");
1383 for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
1384 field->Data->dump(depth + 1);
1385 }
1386 fprintf(stderr, "%*s %d attribields\n", depth * 2, "", (int) attribfields.size());
1387 for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
1388 field->Data->dump(depth + 1);
1389 }
1390 fprintf(stderr, "%*s %d enumfields\n", depth * 2, "", (int) enumfields.size());
1391 for (List<Mstring>::iterator field = enumfields.begin(); field; field = field->Next) {
1392 fprintf(stderr, "%*s enum: %s\n", depth * 2 + depth, "", field->Data.c_str());
1393 }
1394 fprintf(stderr, "%*s (%llu .. %llu) | Optional:%s | List:%s\n", (depth + 1) * 2, "", getMinOccurs(), getMaxOccurs(), isOptional ? "true" : "false", name.list_extension ? "true" : "false");
1395 fprintf(stderr, "%*s %d variants: ", (depth + 1) * 2, "", (int) variant.size());
1396 for (List<Mstring>::iterator var = variant.begin(); var; var = var->Next) {
1397 fprintf(stderr, "%s, ", var->Data.c_str());
1398 }
1399 fprintf(stderr, "%*s pattern:%s | length:%i \n ", (depth + 1) * 2, "", this->pattern.facet.c_str(), (int) (this->length.facet_maxLength));
1400 fprintf(stderr, "%*s enum: %i \n", (depth + 1)*2, "", (int) this->enumeration.facets.size());
1401 fprintf(stderr, "\n");
1402 }
1403
1404 void ComplexType::setMinMaxOccurs(const unsigned long long min, const unsigned long long max, const bool generate_list_postfix) {
1405
1406 if (min != 1 || max != 1) {
1407 if (xsdtype == n_choice) {
1408 setMinOccurs(min);
1409 setMaxOccurs(max);
1410 addVariant(V_untagged);
1411 first_child = false;
1412 } else if (xsdtype == n_sequence) {
1413 ComplexType * rec = new ComplexType(this);
1414 rec->type.upload(Mstring("record"));
1415 rec->name.upload(Mstring("sequence"));
1416 rec->setXsdtype(n_sequence);
1417 rec->addVariant(V_untagged);
1418 rec->addVariant(V_untagged);
1419 rec->setMinOccurs(min);
1420 rec->setMaxOccurs(max);
1421 complexfields.push_back(rec);
1422 actfield = rec;
1423 if ((rec->getMinOccurs() == 0 && rec->getMaxOccurs() > 1) || rec->getMinOccurs() > 0) {
1424 rec->name.list_extension = true;
1425 }
1426 } else {
1427 setMinOccurs(min);
1428 setMaxOccurs(max);
1429 if ((getMinOccurs() == 0 && getMaxOccurs() > 1) || getMinOccurs() > 0) {
1430 if (generate_list_postfix) {
1431 name.list_extension = true;
1432 }
1433 }
1434 if (parent != NULL && parent->getXsdtype() == n_choice) {
1435 name.list_extension = true;
1436 if ((parent != NULL && parent->getXsdtype() == n_choice)) {
1437 if (parent->first_child == false && getMinOccurs() == 0) {
1438 parent->first_child = true;
1439 with_union = true;
1440 first_child = false;
1441 } else {
1442 with_union = true;
1443 first_child = true;
1444 }
1445 }
1446 }
1447 }
1448 }
1449
1450 if (getMaxOccurs() > 1 && generate_list_postfix) {
1451 name.list_extension = true;
1452 }
1453 }
1454
1455 void ComplexType::applyNamespaceAttribute(VariantMode varLabel, const Mstring& ns_list) {
1456 List<Mstring> namespaces;
1457 if (!ns_list.empty()) {
1458 expstring_t valueToSplitIntoTokens = mcopystr(ns_list.c_str());
1459 char * token;
1460 token = strtok(valueToSplitIntoTokens, " ");
1461 while (token != NULL) {
1462 namespaces.push_back(Mstring(token));
1463 token = strtok(NULL, " ");
1464 }
1465 Free(valueToSplitIntoTokens);
1466 }
1467
1468 Mstring any_ns;
1469 bool first = true;
1470 // Note: libxml2 will verify the namespace list according to the schema
1471 // of XML Schema. It is either ##any, ##other, ##local, ##targetNamespace,
1472 // or a list of (namespace reference | ##local | ##targetNamespace).
1473 for (List<Mstring>::iterator ns = namespaces.begin(); ns; ns = ns->Next) {
1474 static const Mstring xxany("##any"), xxother("##other"), xxlocal("##local"),
1475 xxtargetNamespace("##targetNamespace");
1476 if (!first) any_ns += ',';
1477
1478 if (ns->Data == xxany) {
1479 }// this must be the only element, nothing to add
1480 else if (ns->Data == xxother) { // this must be the only element
1481 any_ns += " except unqualified";
1482 if (module->getTargetNamespace() != "NoTargetNamespace") {
1483 any_ns += ", \'";
1484 any_ns += parent->getModule()->getTargetNamespace();
1485 any_ns += '\'';
1486 }
1487 }// The three cases below can happen multiple times
1488 else {
1489 if (first) any_ns += " from ";
1490 // else a comma was already added
1491 if (ns->Data == xxtargetNamespace) {
1492 any_ns += '\'';
1493 any_ns += parent->getModule()->getTargetNamespace();
1494 any_ns += '\'';
1495 } else if (ns->Data == xxlocal) {
1496 any_ns += "unqualified";
1497 } else {
1498 any_ns += '\'';
1499 any_ns += ns->Data;
1500 any_ns += '\'';
1501 }
1502 }
1503
1504 first = false;
1505 }
1506
1507 addVariant(varLabel, any_ns, true);
1508 }
1509
1510 void ComplexType::addComment(const Mstring& text) {
1511 if (this == actfield) {
1512 if (lastType == n_attribute) { // ez nem teljesen jo, stb, tobb lehetoseg, es rossy sorrend
1513 if (!attribfields.empty()) {
1514 attribfields.back()->addComment(text);
1515 }
1516 } else {
1517 if (actfield->getName().convertedValue == Mstring("base") && parent != NULL) {
1518 parent->getComment().push_back(Mstring("/* " + text + " */\n"));
1519 } else {
1520 comment.push_back(Mstring("/* " + text + " */\n"));
1521 }
1522 }
1523 } else {
1524 actfield->addComment(text);
1525 return;
1526 }
1527 }
1528
1529 //Attribute extension logic when extending complextypes
1530 void ComplexType::applyAttributeExtension(ComplexType * found_CT, AttributeType * anyAttrib /* = NULL */) {
1531 for (List<AttributeType*>::iterator attr = found_CT->attribfields.begin(); attr; attr = attr->Next) {
1532 bool l = false;
1533 if (anyAttrib != NULL && attr->Data->isAnyAttribute()) {
1534 anyAttrib->addNameSpaceAttribute(attr->Data->getNameSpaceAttribute());
1535 l = true;
1536 } else {
1537 for (List<AttributeType*>::iterator attr2 = attribfields.begin(); attr2; attr2 = attr2->Next) {
1538 if (attr->Data->getName().convertedValue == attr2->Data->getName().convertedValue &&
1539 attr->Data->getType().convertedValue == attr2->Data->getType().convertedValue) {
1540 if (attr->Data->getUseVal() == optional) {
1541 attr2->Data->setUseVal(optional);
1542 }
1543 l = true;
1544 break;
1545 }
1546 }
1547 }
1548 if (!l) {
1549 AttributeType * newAttrib = new AttributeType(*attr->Data);
1550 attribfields.push_back(newAttrib);
1551 setParent(this, newAttrib);
1552 }
1553 }
1554 }
1555
1556 //Attribute restriction logic when restricting complextypes
1557 void ComplexType::applyAttributeRestriction(ComplexType * found_CT) {
1558 for (List<AttributeType*>::iterator attr = attribfields.begin(), nextAttr; attr; attr = nextAttr) {
1559 nextAttr = attr->Next;
1560 bool l = false;
1561 for (List<AttributeType*>::iterator attr2 = found_CT->attribfields.begin(); attr2; attr2 = attr2->Next) {
1562 if (attr->Data->getName().convertedValue == attr2->Data->getName().convertedValue &&
1563 attr->Data->getType().convertedValue == attr2->Data->getType().convertedValue) {
1564 l = true;
1565 break;
1566 }
1567 }
1568 if (!l) {
1569 delete attr->Data;
1570 attr->Data = NULL;
1571 attribfields.remove(attr);
1572 }
1573 }
1574 size_t size = found_CT->attribfields.size();
1575 size_t size2 = attribfields.size();
1576 size_t i = 0;
1577 List<AttributeType*>::iterator attr = found_CT->attribfields.begin();
1578 for (; i < size; attr = attr->Next, i = i + 1) {
1579 bool l = false;
1580 size_t j = 0;
1581 List<AttributeType*>::iterator attr2 = attribfields.begin();
1582 for (; j < size2; attr2 = attr2->Next, j = j + 1) {
1583 if (attr->Data->getName().convertedValue == attr2->Data->getName().convertedValue &&
1584 attr->Data->getType().convertedValue == attr2->Data->getType().convertedValue && !attr2->Data->getUsed()) {
1585 l = true;
1586 attr2->Data->setUsed(true);
1587 break;
1588 }
1589 }
1590 if (!l) {
1591 AttributeType * newAttrib = new AttributeType(*attr->Data);
1592 attribfields.push_back(newAttrib);
1593 setParent(this, newAttrib);
1594 }
1595 }
1596 }
1597
1598 void ComplexType::addNameSpaceAsVariant(RootType * root, RootType * other) {
1599 if (other->getModule()->getTargetNamespace() != root->getModule()->getTargetNamespace() &&
1600 other->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1601 root->addVariant(V_namespaceAs, other->getModule()->getTargetNamespace());
1602 }
1603 }
1604
1605 void ComplexType::resolveAttribute(AttributeType* attr) {
1606 if (attr->getXsdtype() == n_attribute && !attr->getReference().empty()) {
1607 SimpleType * st = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(attr, want_BOTH);
1608 if (st != NULL) {
1609 if (attr->isFromRef()) {
1610 addNameSpaceAsVariant(attr, st);
1611 attr->setTypeOfField(st->getName().convertedValue);
1612 attr->setNameOfField(st->getName().originalValueWoPrefix);
1613 attr->setOrigModule(st->getModule());
1614 } else {
1615 attr->setTypeOfField(st->getName().convertedValue);
1616 if (st->getType().convertedValue == "record" || st->getType().convertedValue == "union") {
1617 st->addToNameDepList(attr);
1618 }
1619 }
1620 } else {
1621 printError(module->getSchemaname(), name.convertedValue,
1622 "Reference for a non-defined type: " + attr->getReference().repr());
1623 TTCN3ModuleInventory::getInstance().incrNumErrors();
1624 }
1625 }
1626 }
1627
1628 void ComplexType::resolveAttributeGroup(SimpleType * st) {
1629 if (xsdtype == n_attributeGroup && !outside_reference.empty()) {
1630 ComplexType * ct = (ComplexType*) st;
1631 if(ct->resolved == No){
1632 ct->referenceResolving();
1633 }
1634 outside_reference.set_resolved(ct);
1635 setInvisible();
1636 bool addNameSpaceas = false;
1637 if (ct->getModule()->getTargetNamespace() != module->getTargetNamespace() &&
1638 ct->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1639 addNameSpaceas = true;
1640 }
1641 ComplexType * par;
1642 if(parent->nillable && parent->parent != NULL){
1643 par = parent->parent;
1644 }else {
1645 par = parent;
1646 }
1647 List<AttributeType*>::iterator anyAttrib = par->attribfields.begin();
1648 for (; anyAttrib; anyAttrib = anyAttrib->Next) {
1649 if (anyAttrib->Data->isAnyAttribute()) {
1650 break;
1651 }
1652 }
1653 for (List<AttributeType*>::iterator attr = ct->attribfields.begin(); attr; attr = attr->Next) {
1654 AttributeType * attrib = new AttributeType(*attr->Data);
1655 attr->Data->setOrigModule(ct->getModule());
1656 if (addNameSpaceas) {
1657 attrib->addVariant(V_namespaceAs, ct->getModule()->getTargetNamespace());
1658 }
1659 if (anyAttrib != NULL && attr->Data->isAnyAttribute()) {
1660 anyAttrib->Data->addNameSpaceAttribute(attr->Data->getNameSpaceAttribute());
1661 } else {
1662 //Nillable attribute placement is hard...
1663 if (parent->nillable && parent->parent != NULL) {
1664 parent->parent->attribfields.push_back(attrib);
1665 attrib->parent = parent->parent;
1666 setParent(parent->parent, attrib);
1667 } else if (parent->nillable && !parent->complexfields.empty()) {
1668 parent->complexfields.back()->attribfields.push_back(attrib);
1669 attrib->parent = parent->complexfields.back();
1670 } else if (parent->parent != NULL && (parent->parent->mode == extensionMode || parent->parent->mode == restrictionMode)) {
1671 parent->parent->attribfields.push_back(attrib);
1672 setParent(parent->parent, attrib);
1673 } else {
1674 parent->attribfields.push_back(attrib);
1675 setParent(parent, attrib);
1676 }
1677 }
1678 }
1679 }
1680 }
1681
1682 void ComplexType::resolveGroup(SimpleType *st) {
1683 if (xsdtype == n_group && !outside_reference.empty()) {
1684 ComplexType * ct = (ComplexType*) st;
1685 outside_reference.set_resolved(ct);
1686 setInvisible();
1687 if(ct->resolved == No){
1688 ct->referenceResolving();
1689 }
1690 //Decide if namespaceas variant needs to be added
1691 bool addNameSpaceas = false;
1692 if (ct->getModule()->getTargetNamespace() != module->getTargetNamespace() &&
1693 ct->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1694 addNameSpaceas = true;
1695 }
1696 if (ct->getXsdtype() == n_sequence && getMinOccurs() == 1 && getMaxOccurs() == 1 && (parent->getXsdtype() == n_complexType || parent->getXsdtype() == n_sequence)) {
1697 for (List<ComplexType*>::iterator c = ct->complexfields.begin(); c; c = c->Next) {
1698 ComplexType * newField = new ComplexType(*c->Data);
1699 parent->complexfields.push_back(newField);
1700 setParent(parent, newField);
1701 parent->complexfields.back()->setModule(getModule());
1702 if (addNameSpaceas) {
1703 parent->complexfields.back()->addVariant(V_namespaceAs, ct->getModule()->getTargetNamespace());
1704 }
1705 }
1706 } else if (ct->getXsdtype() == n_all) {
1707 //If the parent optional, then every field is optional
1708 for (List<ComplexType*>::iterator c = ct->complexfields.begin(); c; c = c->Next) {
1709 ComplexType* f = new ComplexType(*c->Data);
1710 if (getMinOccurs() == 0 && !f->enumerated) {
1711 f->isOptional = true;
1712 }
1713 ((ComplexType*) parent)->complexfields.push_back(f);
1714 setParent(parent, f);
1715 f->setModule(getModule());
1716 if (addNameSpaceas) {
1717 f->addVariant(V_namespaceAs, ct->getModule()->getTargetNamespace());
1718 }
1719 }
1720 parent->addVariant(V_useOrder);
1721 } else {
1722 if (name.list_extension) {
1723 addVariant(V_untagged);
1724 }
1725 type.upload(ct->getName().convertedValue);
1726 name.upload(ct->getName().convertedValue);
1727 ct->addToNameDepList(this);
1728 nameDep = ct;
1729 visible = true;
1730 if (addNameSpaceas) {
1731 addVariant(V_namespaceAs, ct->getModule()->getTargetNamespace());
1732 }
1733 }
1734 }
1735 }
1736
1737 void ComplexType::resolveElement(SimpleType *st) {
1738 if (xsdtype == n_element && !outside_reference.empty()) {
1739 outside_reference.set_resolved(st);
1740 type.upload(st->getModule()->getTargetNamespaceConnector() + Mstring(":") + st->getName().convertedValue);
1741 if (name.originalValueWoPrefix.empty()) {
1742 name.upload(st->getName().convertedValue);
1743 }
1744 if (fromRef) {
1745 addNameSpaceAsVariant(this, st);
1746 }
1747
1748 collectElementTypes(st, NULL);
1749
1750 //Namedep is added to the substitutions, if any
1751 if(st->getSubstitution() != NULL){
1752 st->getSubstitution()->addToNameDepList(this);
1753 nameDep = st->getSubstitution();
1754 }if(st->getTypeSubstitution() != NULL){
1755 st->getTypeSubstitution()->addToNameDepList(this);
1756 nameDep = st->getTypeSubstitution();
1757 }else {
1758 st->addToNameDepList(this);
1759 nameDep = st;
1760 }
1761 }
1762 }
1763
1764 void ComplexType::resolveSimpleTypeExtension() {
1765 if (mode == extensionMode && cmode == CT_simpletype_mode && basefield != NULL) {
1766 SimpleType * st = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(basefield, want_BOTH);
1767 if (st != NULL) {
1768 if (st->getXsdtype() != n_NOTSET && ((ComplexType*) st)->basefield != NULL) { // if the xsdtype != simpletype
1769 ComplexType * ct = (ComplexType*) st;
1770 if (ct->resolved == No) {
1771 ct->referenceResolving();
1772 }
1773 basefield->outside_reference.set_resolved(ct);
1774 ct->basefield->addToNameDepList(basefield);
1775 basefield->nameDep = ct->basefield;
1776 basefield->mode = extensionMode;
1777 basefield->applyReference(*ct->basefield, true);
1778 addNameSpaceAsVariant(basefield, ct->basefield);
1779 applyAttributeExtension(ct);
1780 } else {
1781 if (!st->getReference().empty() && !st->getReference().is_resolved()) {
1782 st->referenceResolving();
1783 }
1784 st->addToNameDepList(basefield);
1785 basefield->nameDep = st;
1786 addNameSpaceAsVariant(basefield, st);
1787 const Mstring old_type = basefield->getType().originalValueWoPrefix;
1788 basefield->applyReference(*st);
1789 // If st has enumeration then the type is restored to the original value
1790 // because enumerations cannot be extended here and this way we just
1791 // create an alias.
1792 if (st->getEnumeration().modified) {
1793 basefield->setTypeValue(old_type);
1794 basefield->getEnumeration().modified = false;
1795 }
1796 }
1797 } else if(!isBuiltInType(basefield->getType().convertedValue)){
1798 printError(module->getSchemaname(), name.convertedValue,
1799 "Reference for a non-defined type: " + basefield->getReference().repr());
1800 TTCN3ModuleInventory::getInstance().incrNumErrors();
1801 return;
1802 }
1803
1804 }
1805 }
1806
1807 void ComplexType::resolveSimpleTypeRestriction() {
1808 if (mode == restrictionMode && cmode == CT_simpletype_mode && basefield != NULL && !basefield->outside_reference.empty()) {
1809 SimpleType * st = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(basefield, want_BOTH);
1810 if (st == NULL) {
1811 printError(module->getSchemaname(), name.convertedValue,
1812 "Reference for a non-defined type: " + basefield->getReference().repr());
1813 TTCN3ModuleInventory::getInstance().incrNumErrors();
1814 return;
1815 }
1816 basefield->outside_reference.set_resolved(st);
1817 if (st->getXsdtype() != n_NOTSET) {
1818 ComplexType * ct = (ComplexType*) st;
1819 if (ct->resolved == No) {
1820 ct->referenceResolving();
1821 }
1822 applyAttributeRestriction(ct);
1823 basefield->mode = restrictionMode;
1824 if (ct->cmode == CT_complextype_mode) {
1825 applyReference(*ct, true);
1826 type.upload(ct->getName().convertedValue);
1827 basefield->setInvisible();
1828 } else if (ct->basefield != NULL) {
1829 basefield->applyReference(*ct->basefield);
1830 addNameSpaceAsVariant(basefield, ct->basefield);
1831 } else if (ct->basefield == NULL) {
1832 basefield->applyReference(*ct);
1833 addNameSpaceAsVariant(basefield, ct);
1834 }
1835 } else {
1836 if (!st->getReference().empty() && !st->getReference().is_resolved()) {
1837 st->referenceResolving();
1838 }
1839 if(xsdtype == n_simpleContent){
1840 basefield->applyReference(*st, true);
1841 addNameSpaceAsVariant(basefield, st);
1842 basefield->mode = restrictionMode;
1843 }else if(xsdtype == n_simpleType){
1844 basefield->setInvisible();
1845 applyReference(*basefield, true);
1846 applyReference(*st, true);
1847 addNameSpaceAsVariant(this, st);
1848 basefield->mode = restrictionMode;
1849 }
1850 }
1851 } else if (mode == restrictionMode && cmode == CT_simpletype_mode && basefield != NULL) {
1852 ComplexType * ct = (ComplexType*) TTCN3ModuleInventory::getInstance().lookup(basefield, want_CT);
1853 if (ct == NULL && !isBuiltInType(basefield->getType().convertedValue)) {
1854 printError(module->getSchemaname(), name.convertedValue,
1855 "Reference for a non-defined type: " + basefield->getReference().repr());
1856 TTCN3ModuleInventory::getInstance().incrNumErrors();
1857 return;
1858 }
1859
1860 basefield->outside_reference.set_resolved(ct);
1861 if (ct != NULL) {
1862 if (ct->resolved == No) {
1863 ct->referenceResolving();
1864 }
1865 for (List<AttributeType*>::iterator f = ct->attribfields.begin(); f; f = f->Next) {
1866 AttributeType * attr = new AttributeType(*f->Data);
1867 attribfields.push_back(attr);
1868 setParent(this, attr);
1869 }
1870 addNameSpaceAsVariant(this, ct);
1871 }
1872 if(!basefield->parent->top){
1873 // This is the case of restriction -> list -> simpletype -> restriction
1874 // we have to apply the reference to the parent's parent.
1875 if(basefield->parent->parent != NULL && !basefield->parent->isVisible()) {
1876 basefield->parent->parent->applyReference(*basefield, true);
1877 } else {
1878 applyReference(*basefield, true);
1879 }
1880 basefield->setInvisible();
1881 }
1882 }
1883 }
1884
1885 void ComplexType::resolveComplexTypeExtension() {
1886 if (mode == extensionMode && cmode == CT_complextype_mode && !outside_reference.empty()) {
1887 ComplexType * ct = (ComplexType*) TTCN3ModuleInventory::getInstance().lookup(this, want_CT);
1888 if (ct == NULL) {
1889 printError(module->getSchemaname(), name.convertedValue,
1890 "Reference for a non-defined type: " + getReference().repr());
1891 TTCN3ModuleInventory::getInstance().incrNumErrors();
1892 return;
1893 }
1894 if(ct->getXsdtype() != n_NOTSET){
1895 outside_reference.set_resolved(ct);
1896 if (ct->resolved == No) {
1897 ct->referenceResolving();
1898 }
1899 List<AttributeType*>::iterator anyAttr = attribfields.begin();
1900 for (; anyAttr; anyAttr = anyAttr->Next) {
1901 if (anyAttr->Data->isAnyAttribute()) {
1902 break;
1903 }
1904 }
1905
1906 if (anyAttr != NULL) {
1907 applyAttributeExtension(ct, anyAttr->Data);
1908 } else {
1909 applyAttributeExtension(ct);
1910 }
1911
1912 if (ct->getName().convertedValue == outside_reference.get_val() && ct->getModule()->getTargetNamespace() == outside_reference.get_uri()) {
1913 //Self recursion
1914 outside_reference.set_resolved(ct);
1915 for (List<ComplexType*>::iterator f = ct->complexfields.end(); f; f = f->Prev) {
1916 if (f->Data != this) { //not a self recursive field
1917 ComplexType * newField = new ComplexType(*f->Data);
1918 complexfields.push_front(newField);
1919 setParent(this, newField);
1920 } else {
1921 //Self recursive field
1922 ComplexType * field = new ComplexType(this);
1923 field->name.upload(f->Data->getName().convertedValue);
1924 field->applyReference(*f->Data);
1925 field->type.upload(ct->getName().convertedValue + Mstring(".") + f->Data->getName().convertedValue);
1926 field->type.no_replace = true;
1927 field->setMinOccurs(f->Data->getMinOccurs());
1928 field->setMaxOccurs(f->Data->getMaxOccurs());
1929 complexfields.push_front(field);
1930 setParent(this, field);
1931 }
1932 }
1933 } else {
1934 //Normal extension
1935 for (List<ComplexType*>::iterator f = ct->complexfields.end(); f; f = f->Prev) {
1936 ComplexType * newField = new ComplexType(*f->Data);
1937 complexfields.push_front(newField);
1938 setParent(this, newField);
1939 }
1940 }
1941 }
1942 }
1943 }
1944
1945 void ComplexType::resolveComplexTypeRestriction() {
1946 if (mode == restrictionMode && cmode == CT_complextype_mode && !outside_reference.empty()) {
1947 ComplexType * ct = (ComplexType*) TTCN3ModuleInventory::getInstance().lookup(this, want_CT);
1948 if(ct->getXsdtype() != n_NOTSET){
1949 if (ct->resolved == No) {
1950 ct->referenceResolving();
1951 }
1952 outside_reference.set_resolved(ct);
1953 applyAttributeRestriction(ct);
1954
1955 size_t size = complexfields.size();
1956 size_t i = 0;
1957 List<ComplexType*>::iterator field = complexfields.begin();
1958 for (; i < size; field = field->Next, i = i + 1){
1959 List<ComplexType*>::iterator field2 = ct->complexfields.begin();
1960 for (; field2; field2 = field2->Next) {
1961 if (field->Data->getName().convertedValue == field2->Data->getName().convertedValue &&
1962 field->Data->getType().convertedValue == field2->Data->getType().convertedValue &&
1963 field->Data->complexfields.size() <= field2->Data->complexfields.size() &&
1964 hasMatchingFields(field->Data->complexfields, field2->Data->complexfields)) {
1965 // TODO: better algorithm to find matching fields
1966 field->Data->applyReference(*field2->Data, false);
1967 break;
1968 }
1969 }
1970 if(field2 == NULL){
1971 field->Data->setInvisible();
1972 }
1973 }
1974 }
1975 }
1976 }
1977
1978 bool ComplexType::hasMatchingFields(const List<ComplexType*>& mainList, const List<ComplexType*>& subList) const {
1979 List<ComplexType*>::iterator field = mainList.begin();
1980 for (; field; field = field->Next){
1981 List<ComplexType*>::iterator field2 = subList.begin();
1982 bool found = false;
1983 for (; field2; field2 = field2->Next) {
1984 if(field->Data->getName().convertedValue == field2->Data->getName().convertedValue &&
1985 field->Data->getType().convertedValue == field2->Data->getType().convertedValue) {
1986 found = true;
1987 break;
1988 }
1989 }
1990 if(!found) {
1991 return false;
1992 }
1993 }
1994 return true;
1995 }
1996
1997 void ComplexType::resolveUnion(SimpleType *st) {
1998 if (parent != NULL && parent->with_union && xsdtype == n_simpleType && !outside_reference.empty()) {
1999 if (st->getXsdtype() != n_NOTSET) {
2000 ComplexType * ct = (ComplexType*) st;
2001 outside_reference.set_resolved(ct);
2002 for (List<ComplexType*>::iterator field = ct->complexfields.begin(); field; field = field->Next) {
2003 ComplexType * newField = new ComplexType(*field->Data);
2004 parent->complexfields.push_back(newField);
2005 setParent(parent, newField);
2006 }
2007 setInvisible();
2008 }
2009 }
2010 }
2011
2012 void ComplexType::modifyAttributeParent() {
2013 if (nillable_field != NULL) {
2014 ((ComplexType*) nillable_field)->actfield = nillable_field;
2015 } else {
2016 actfield = this;
2017 }
2018 }
2019
2020 //Element substitution
2021 void ComplexType::addSubstitution(SimpleType * st){
2022 ComplexType * element;
2023 if(st->getXsdtype() == n_NOTSET || !complexfields.empty()){
2024 element = new ComplexType(*st, fromTagSubstitution);
2025 }else {
2026 element = new ComplexType(*(ComplexType*)st);
2027 element->variant.clear();
2028 }
2029 element->subsGroup = this;
2030 element->parent = this;
2031 if(complexfields.empty()){ //The first element(head) is the st
2032 element->setTypeValue(st->getType().convertedValue);
2033 if(st->hasVariant(Mstring("\"abstract\""))){
2034 element->addVariant(V_abstract);
2035 }
2036 if(st->getReference().get_ref() != NULL){
2037 ((SimpleType*)st->getReference().get_ref())->addToNameDepList(element);
2038 nameDep = ((SimpleType*)st->getReference().get_ref());
2039 }
2040 module->addElementType(element->getType().convertedValue, element);
2041 element->addVariant(V_formAs, Mstring("qualified"));
2042 }else {
2043 Mstring newType;
2044 if(st->getType().convertedValue == "anyType"){
2045 newType = complexfields.front()->getType().convertedValue;
2046 }else {
2047 newType = st->getName().convertedValue;
2048 st->addToNameDepList(element);
2049 element->nameDep = st;
2050 }
2051 element->setTypeValue(newType);
2052 BlockValue front_block = complexfields.front()->getBlock();
2053 if(front_block == all || front_block == substitution){
2054 element->addVariant(V_block);
2055 }else if(front_block == restriction || front_block == extension){
2056 const Mstring& head_type = complexfields.front()->getType().convertedValue.getValueWithoutPrefix(':');
2057 //To decide if they came from a common ancestor
2058 Mstring elem_type = findRoot(front_block, st, head_type, true);
2059 if(head_type == elem_type){
2060 element->addVariant(V_block);
2061 }
2062 }
2063 }
2064
2065 element->setNameValue(st->getName().convertedValue);
2066 element->top = false;
2067 complexfields.push_back(element);
2068 }
2069
2070 void ComplexType::addTypeSubstitution(SimpleType * st){
2071 ComplexType * element;
2072 if(st->getXsdtype() == n_NOTSET || !complexfields.empty()){
2073 element = new ComplexType(*st, fromTypeSubstitution);
2074 }else {
2075 //Only need a plain complextype
2076 //Head element
2077 element = new ComplexType(this);
2078 //Just the block needed from st
2079 element->block = st->getBlock();
2080 }
2081 st->addToNameDepList(element);
2082 element->nameDep = st;
2083 element->typeSubsGroup = this;
2084 element->parent = this;
2085 if(complexfields.empty()){ //The first element(head) is the st
2086 if(st->hasVariant(Mstring("\"abstract\""))){
2087 element->addVariant(V_abstract);
2088 }
2089 }else {
2090 BlockValue front_block = complexfields.front()->getBlock();
2091 if(front_block == all){
2092 element->addVariant(V_block);
2093 }else if(front_block == restriction || front_block == extension){
2094 const Mstring& head_type = complexfields.front()->getType().convertedValue.getValueWithoutPrefix(':');
2095 //To decide if they came from a common ancestor
2096 Mstring elem_type = findRoot(front_block, st, head_type, true);
2097 if(head_type == elem_type){
2098 element->addVariant(V_block);
2099 }
2100 }
2101 }
2102 //Cascading to parent type substitution
2103 if(parentTypeSubsGroup != NULL && !complexfields.empty()){
2104 parentTypeSubsGroup->addTypeSubstitution(st);
2105 }
2106 element->top = false;
2107 complexfields.push_back(element);
2108 element->setTypeValue(st->getName().convertedValue.getValueWithoutPrefix(':'));
2109 element->setNameValue(st->getName().convertedValue.getValueWithoutPrefix(':'));
2110 }
2111
2112 Mstring ComplexType::findRoot(const BlockValue block_value, SimpleType* elem, const Mstring& head_type, const bool first){
2113 const Mstring elemName = elem->getName().convertedValue.getValueWithoutPrefix(':');
2114 const Mstring elemType = elem->getType().convertedValue.getValueWithoutPrefix(':');
2115
2116 if(!first && !isFromRef() && elemType == head_type){
2117 return elemType;
2118 }else if((isFromRef() &&
2119 ((elem->getMode() == restrictionMode && block_value == restriction) ||
2120 (elem->getMode() == extensionMode && block_value == extension))) && elemType == head_type){
2121 return elemType;
2122 }else if(!first && elemName == head_type){
2123 return elemName;
2124 }else {
2125 SimpleType * st = NULL;
2126 if((elem->getMode() == restrictionMode && block_value == restriction) ||
2127 (elem->getMode() == extensionMode && block_value == extension)){
2128 if(!elem->getReference().is_resolved()){
2129 elem->referenceResolving();
2130 }
2131 if(elem->getXsdtype() != n_NOTSET){
2132 ComplexType * ct = (ComplexType*)elem;
2133 if(ct->basefield != NULL && ct->basefield->getType().convertedValue.getValueWithoutPrefix(':') == head_type){
2134 return head_type;
2135 }else if(ct->basefield != NULL){
2136 st = (SimpleType*)TTCN3ModuleInventory::getInstance().lookup(ct->basefield, want_BOTH);
2137 }
2138 }
2139 if(st == NULL){
2140 st = (SimpleType*)(elem->getReference().get_ref());
2141 }
2142 }else if(elem->getMode() == noMode && (block_value == restriction || block_value == extension)){
2143 st = (SimpleType*)TTCN3ModuleInventory::getInstance().lookup(this, elem->getType().convertedValue, want_BOTH);
2144 }
2145 if(st != NULL && elem != st){
2146 return findRoot(block_value, st, head_type, false);
2147 }
2148 }
2149 if(elem->getMode() == noMode && !first){
2150 return elemType;
2151 }else {
2152 return empty_string;
2153 }
2154 }
2155
This page took 0.10519 seconds and 5 git commands to generate.