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