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
16 ******************************************************************************/
17 #include "ComplexType.hh"
19 #include "GeneralFunctions.hh"
20 #include "XMLParser.hh"
21 #include "TTCN3Module.hh"
22 #include "TTCN3ModuleInventory.hh"
23 #include "Annotation.hh"
27 ComplexType::ComplexType(XMLParser
* a_parser
, TTCN3Module
* a_module
, ConstructType a_construct
)
28 : SimpleType(a_parser
, a_module
, a_construct
)
40 , actualPath(empty_string
)
43 , nillable_field(NULL
)
45 , cmode(CT_undefined_mode
)
47 , parentTypeSubsGroup(NULL
)
52 xsdtype
= n_complexType
;
55 ComplexType::ComplexType(ComplexType
& other
)
58 , nillable(other
.nillable
)
59 , enumerated(other
.enumerated
)
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
)
67 , lastType(other
.lastType
)
68 , actualPath(other
.actualPath
)
70 , nameDep(other
.nameDep
)
71 , nillable_field(NULL
)
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;
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();
92 if (other
.nameDep
!= NULL
) {
93 SimpleType
* dep
= other
.nameDep
;
94 if(dep
->getSubstitution() != NULL
){
95 dep
->getSubstitution()->addToNameDepList(this);
96 nameDep
= dep
->getSubstitution();
98 other
.nameDep
->addToNameDepList(this);
103 ComplexType::ComplexType(ComplexType
* other
)
104 : SimpleType(other
->getParser(), other
->getModule(), c_unknown
)
116 , actualPath(empty_string
)
119 , nillable_field(NULL
)
121 , cmode(CT_undefined_mode
)
123 , parentTypeSubsGroup(NULL
)
128 xsdtype
= n_complexType
;
130 outside_reference
= ReferenceData();
133 ComplexType::ComplexType(const SimpleType
& other
, CT_fromST c
)
146 , actualPath(empty_string
)
149 , nillable_field(NULL
)
151 , cmode(CT_simpletype_mode
)
153 , parentTypeSubsGroup(NULL
)
159 if(c
!= fromTagSubstitution
&& c
!= fromTypeSubstitution
){
160 module
->replaceLastMainType(this);
161 module
->setActualXsdConstruct(c_complexType
);
163 construct
= c_complexType
;
167 type
.upload(Mstring("union"));
171 case fromTagNillable
:
172 addVariant(V_useNil
);
173 type
.upload(Mstring("record"));
175 case fromTagComplexType
:
176 type
.upload(Mstring("record"));
177 xsdtype
= n_complexType
;
179 case fromTagSubstitution
:
180 type
.upload(Mstring("union"));
181 name
.upload(getName().originalValueWoPrefix
+ Mstring("_group"));
185 hidden_variant
.clear();
186 enumeration
.modified
= false;
187 value
.modified
= false;
188 pattern
.modified
= false;
189 length
.modified
= false;
190 whitespace
.modified
= false;
192 case fromTypeSubstitution
:
193 type
.upload(Mstring("union"));
194 name
.upload(getName().originalValueWoPrefix
+ Mstring("_derivations"));
196 substitutionGroup
= empty_string
;
197 typeSubsGroup
= this;
199 hidden_variant
.clear();
200 enumeration
.modified
= false;
201 value
.modified
= false;
202 pattern
.modified
= false;
203 length
.modified
= false;
204 whitespace
.modified
= false;
208 ComplexType::~ComplexType() {
209 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
213 complexfields
.clear();
215 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
219 attribfields
.clear();
222 void ComplexType::loadWithValues() {
223 //Find the last field where the tag is found
224 if (this != actfield
) {
225 actfield
->loadWithValues();
229 const XMLParser::TagAttributes
& atts
= parser
->getActualTagAttributes();
231 switch (parser
->getActualTagName()) {
233 if (!top
&& xsdtype
!= n_sequence
&& xsdtype
!= n_complexType
&& xsdtype
!= n_extension
&& xsdtype
!= n_restriction
&& xsdtype
!= n_element
) {
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
);
244 //Do not create new record, it is an embedded sequence
245 if (xsdtype
== n_sequence
&& atts
.minOccurs
== 1 && atts
.maxOccurs
== 1) {
248 type
.upload(Mstring("record"));
249 xsdtype
= n_sequence
;
250 setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
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
);
263 complexfields
.push_back(choice
);
266 type
.upload(Mstring("union"));
271 //Create the record of enumerated field
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) {
288 mode
= restrictionMode
;
289 //If it is an xsd:union then call SimpleType::loadWithValues
290 if (parent
!= NULL
&& parent
->with_union
) {
291 SimpleType::loadWithValues();
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
);
304 } else if (cmode
== CT_complextype_mode
) {
305 setReference(atts
.base
);
306 xsdtype
= n_restriction
;
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
);
321 } else if (cmode
== CT_complextype_mode
) {
322 setReference(atts
.base
);
323 xsdtype
= n_extension
;
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"));
335 nilrec
->type
.upload(atts
.type
);
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
);
345 nillable_field
= nilrec
;
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"));
353 nilrec
->type
.upload(atts
.type
);
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
);
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
);
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
);
383 c
->applyRefAttribute(atts
.ref
);
384 c
->name
.upload(atts
.ref
.getValueWithoutPrefix(':'));
385 c
->type
.upload(atts
.ref
);
387 c
->applySubstitionGroupAttribute(atts
.substitionGroup
);
388 c
->applyBlockAttribute(atts
.block
);
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();
398 if (atts
.maxOccurs
!= 1) {
399 printError(getModule()->getSchemaname(), name
.convertedValue
,
400 Mstring("Inside <all>, maxOccurs must be 1"));
401 TTCN3ModuleInventory::incrNumErrors();
404 complexfields
.push_back(c
);
406 c
->isOptional
= true;
409 complexfields
.push_back(c
);
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);
430 attribute
->applyRefAttribute(atts
.ref
);
432 actfield
= attribute
;
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
;
444 attribfields
.push_back(attribute
);
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
);
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_
);
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
;
480 attribfields
.push_back(anyattr
);
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
);
492 xsdtype
= n_attributeGroup
;
493 name
.upload(Mstring(atts
.name
));
498 if (atts
.ref
.empty()) {
501 name
.upload(atts
.name
);
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
);
517 type
.upload(Mstring("union"));
518 addVariant(V_useUnion
);
519 if (!atts
.memberTypes
.empty()) {
521 //Get the union values
522 expstring_t valueToSplitIntoTokens
= mcopystr(atts
.memberTypes
.c_str());
524 token
= strtok(valueToSplitIntoTokens
, " ");
525 while (token
!= NULL
) {
526 types
.push_back(Mstring(token
));
527 token
= strtok(NULL
, " ");
529 Free(valueToSplitIntoTokens
);
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
);
545 case n_simpleContent
:
547 xsdtype
= parser
->getActualTagName();
548 cmode
= CT_simpletype_mode
;
552 fieldname
= Mstring("alt_");
554 fieldname
= mprintf("alt_%d", 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
);
567 name
.upload(atts
.name
);
568 type
.upload(Mstring("record"));
569 applyAbstractAttribute(atts
.abstract
);
570 applySubstitionGroupAttribute(atts
.substitionGroup
);
571 applyBlockAttribute(atts
.block
);
573 case n_complexContent
:
574 tagNames
.push_back(parser
->getActualTagName());
575 cmode
= CT_complextype_mode
;
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);
582 complexfields
.push_back(mixed
);
583 addVariant(V_embedValues
);
587 if (parent
!= NULL
&& parent
->basefield
== this) {
589 parent
->SimpleType::loadWithValues();
590 parent
->basefield
= NULL
;
605 case n_fractionDigits
:
606 SimpleType::loadWithValues();
609 addComment(Mstring("LABEL:"));
612 addComment(Mstring("DEFINITION:"));
619 // called from endelementHandler
620 void ComplexType::modifyValues() {
621 if (this != actfield
) {
622 actfield
->modifyValues();
625 if (xsdtype
== n_sequence
) {
626 skipback
= skipback
- 1;
629 //embedded simpletype with list in element
630 if(xsdtype
== n_simpleType
&& list
) {
636 if ( parent
!= NULL
&&
637 (xsdtype
== n_element
||
638 xsdtype
== n_complexType
||
639 xsdtype
== n_complexContent
||
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)
652 if (!tagNames
.empty() && tagNames
.back() == parser
->getParentTagName()) {
653 if (nillable
&& tagNames
.back() == n_element
) {
654 parent
->modifyValues();
657 } else if (tagNames
.empty()) {
658 parent
->actfield
= parent
;
659 parent
->lastType
= xsdtype
;
664 void ComplexType::referenceResolving() {
665 if (resolved
!= No
) return; // nothing to do
666 if(this == subsGroup
){
670 resolved
= InProgress
;
671 for (List
<ComplexType
*>::iterator ct
= complexfields
.begin(); ct
; ct
= ct
->Next
) {
672 // Referenece resolving of ComplexTypes
673 ct
->Data
->referenceResolving();
675 for (List
<AttributeType
*>::iterator attr
= attribfields
.begin(); attr
; attr
= attr
->Next
) {
676 //Reference resolving for Attributes
677 resolveAttribute(attr
->Data
);
680 reference_resolving_funtion();
682 if(!substitutionGroup
.empty()){
683 addToSubstitutions();
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
);
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
);
708 resolveAttributeGroup(st
);
714 resolveSimpleTypeExtension();
716 resolveSimpleTypeRestriction();
718 resolveComplexTypeExtension();
720 resolveComplexTypeRestriction();
724 addToTypeSubstitutions();
728 void ComplexType::setParent(ComplexType
* par
, SimpleType
* child
) {
732 void ComplexType::applyReference(const SimpleType
& other
, const bool on_attributes
) {
733 type
.convertedValue
= other
.getType().convertedValue
;
734 type
.originalValueWoPrefix
= other
.getType().convertedValue
.getValueWithoutPrefix(':');
736 if (other
.getMinOccurs() > getMinOccurs() ||
737 other
.getMaxOccurs() < getMaxOccurs()) {
738 if (!on_attributes
) {
739 expstring_t temp
= memptystr();
742 "The occurrence range (%llu .. %llu) of the element (%s) is not compatible "
743 "with the occurrence range (%llu .. %llu) of the referenced element.",
746 name
.originalValueWoPrefix
.c_str(),
747 other
.getMinOccurs(),
748 other
.getMaxOccurs());
749 printError(module
->getSchemaname(), parent
->getName().originalValueWoPrefix
,
752 TTCN3ModuleInventory::getInstance().incrNumErrors();
755 setMinOccurs(llmax(getMinOccurs(), other
.getMinOccurs()));
756 setMaxOccurs(llmin(getMaxOccurs(), other
.getMaxOccurs()));
759 for (List
<Mstring
>::iterator var
= other
.getVariantRef().begin(); var
; var
= var
->Next
) {
761 for (List
<Mstring
>::iterator var1
= variant
.begin(); var1
; var1
= var1
->Next
) {
762 if (var
->Data
== var1
->Data
) {
768 variant
.push_back(var
->Data
);
769 variant_ref
.push_back(var
->Data
);
773 builtInBase
= other
.getBuiltInBase();
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());
782 void ComplexType::nameConversion(NameConversionMode conversion_mode
, const List
<NamespaceType
> & ns
) {
784 switch (conversion_mode
) {
786 nameConversion_names(ns
);
789 nameConversion_types(ns
);
792 nameConversion_fields(ns
);
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
;
802 for (List
<Mstring
>::iterator vari
= variant
.begin(); vari
; vari
= vari
->Next
) {
803 if (vari
->Data
== "\"untagged\"") {
809 addVariant(V_onlyValue
, var
);
811 for (List
<SimpleType
*>::iterator dep
= nameDepList
.begin(); dep
; dep
= dep
->Next
) {
812 dep
->Data
->setTypeValue(res
);
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
);
823 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
824 field
->Data
->nameConversion_types(ns
);
827 Mstring prefix
, uri
, typeValue
;
829 if (type
.convertedValue
== "record" ||
830 type
.convertedValue
== "set" ||
831 type
.convertedValue
== "union" ||
832 type
.convertedValue
== "enumerated") {
836 prefix
= type
.convertedValue
.getPrefix(':');
837 typeValue
= type
.convertedValue
.getValueWithoutPrefix(':');
839 for (List
<NamespaceType
>::iterator namesp
= ns
.begin(); namesp
; namesp
= namesp
->Next
) {
840 if (prefix
== namesp
->Data
.prefix
) {
841 uri
= namesp
->Data
.uri
;
846 QualifiedName
in(uri
, typeValue
); // ns uri + original name
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
){
859 if (origTN
!= NULL
) {
860 setTypeValue(origTN
->Data
.name
);
863 XSDName2TTCN3Name(typeValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
, type
.no_replace
);
868 void ComplexType::nameConversion_fields(const List
<NamespaceType
> & ns
) {
869 QualifiedNames used_field_names
;
871 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
872 field
->Data
->nameConversion_names(used_field_names
);
875 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
876 if (field
->Data
->getMinOccurs() == 0 && field
->Data
->getMaxOccurs() == 0) {
879 if (!field
->Data
->isVisible()) {
883 field
->Data
->nameConversion_fields(ns
);
885 Mstring prefix
= field
->Data
->getType().convertedValue
.getPrefix(':');
886 Mstring typeValue
= field
->Data
->getType().convertedValue
.getValueWithoutPrefix(':');
889 var
= getModule()->getTargetNamespace();
890 XSDName2TTCN3Name(typeValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
);
892 field
->Data
->addVariant(V_onlyValue
, var
);
893 var
= getModule()->getTargetNamespace();
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;
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" &&
912 field
->Data
->addVariant(V_nameAs
, field
->Data
->getName().originalValueWoPrefix
);
916 if (!found_in_variant
) {
917 field
->Data
->addVariant(V_untagged
, empty_string
, true);
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
);
929 void ComplexType::setFieldPaths(Mstring path
) {
932 Mstring field_prefix
= empty_string
;
933 if(parent
->getMinOccurs() == 0 && parent
->getMaxOccurs() == ULLONG_MAX
){
934 field_prefix
= "[-].";
936 path
= field_prefix
+ getName().convertedValue
;
937 actualPath
= field_prefix
+ getName().convertedValue
;
939 actualPath
= getName().convertedValue
;
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
;
946 path
= path
+ Mstring(".") + getName().convertedValue
;
950 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
951 field
->Data
->setFieldPaths(path
);
953 for (List
<AttributeType
*>::iterator attr
= attribfields
.begin(); attr
; attr
= attr
->Next
) {
954 attr
->Data
->setFieldPath(path
);
958 void ComplexType::finalModification2() {
959 //Call SimpleType finalModification
960 SimpleType::finalModification();
962 //Set isOptional field
963 isOptional
= isOptional
|| (getMinOccurs() == 0 && getMaxOccurs() == 1);
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()) {
973 complexfields
.remove(field
);
976 field
->Data
->finalModification2();
977 //collect <xsd:all> elements
978 if (field
->Data
->fromAll
) {
979 enumNames
.push_back(field
->Data
->getName().convertedValue
);
984 ComplexType
* embedField
= NULL
;
985 ComplexType
* enumField
= NULL
;
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;
995 complexfields
.remove(field
);
996 } else if (field
->Data
->enumerated
) {
997 enumField
= new ComplexType(*field
->Data
);
998 enumField
->parent
= this;
1001 complexfields
.remove(field
);
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
);
1014 if (embedField
!= NULL
) {
1015 //Insert the embed field to the front
1016 complexfields
.push_front(embedField
);
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()) {
1024 field
->Data
->name
.upload(Mstring("alt_"));
1026 field
->Data
->name
.upload(Mstring(mprintf("alt_%d", number
)));
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
);
1043 attribfields
.remove(field
);
1044 } else if (field
->Data
->getUseVal() == prohibited
|| !field
->Data
->isVisible()) {
1045 //Not visible attribute removed
1048 attribfields
.remove(field
);
1050 field
->Data
->SimpleType::finalModification();
1054 //Push anyattribute to the front
1055 if (anyAttr
!= NULL
) {
1056 anyAttr
->applyNamespaceAttribute(V_anyAttributes
);
1057 attribfields
.push_back(anyAttr
);
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
);
1072 void ComplexType::finalModification() {
1073 finalModification2();
1074 setFieldPaths(empty_string
);
1075 List
<Mstring
> container
;
1076 collectVariants(container
);
1078 variant
= container
;
1081 void ComplexType::printToFile(FILE * file
) {
1082 printToFile(file
, 0, false);
1085 void ComplexType::printToFile(FILE * file
, const unsigned level
, const bool is_union
) {
1089 printComment(file
, level
);
1091 fprintf(file
, "type ");
1092 if(mode
== listMode
){
1093 printMinOccursMaxOccurs(file
, is_union
);
1094 fprintf(file
, "%s", type
.convertedValue
.c_str());
1096 fprintf(file
, "%s %s", type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
1098 fprintf(file
, "\n{\n");
1100 if (attribfields
.empty() && complexfields
.empty()) {
1101 fprintf(file
, "\n");
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");
1111 fprintf(file
, "\n");
1115 complexfields
.remove(c
);
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");
1124 fprintf(file
, "\n");
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");
1133 fprintf(file
, "\n");
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());
1147 fprintf(file
, " optional");
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());
1158 fprintf(file
, " optional");
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
);
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
, "} ");
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());
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");
1191 fprintf(file
, "\n");
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");
1200 fprintf(file
, "\n");
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");
1214 fprintf(file
, "\n");
1217 indent(file
, level
);
1218 fprintf(file
, "} ");
1222 if (field_is_record
|| field_is_union
) {
1223 indent(file
, level
);
1224 fprintf(file
, "} ");
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");
1239 if(mode
== listMode
){
1240 fprintf(file
, " %s", name
.convertedValue
.c_str());
1243 fprintf(file
, ";\n\n\n");
1247 void ComplexType::collectVariants(List
<Mstring
>& container
) {
1249 if (e_flag_used
|| !isVisible()) {
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
1259 container
.push_back(Mstring("variant ") + Mstring(var
->Data
.c_str()) + Mstring(";\n"));
1262 if (useUnionVariantWhenMainTypeIsRecordOf
) {
1263 container
.push_back(Mstring("variant ([-]) \"useUnion\";\n"));
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"));
1270 //Collect variants of attributes
1271 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
1272 field
->Data
->collectVariants(container
);
1275 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
1277 if (!field
->Data
->isVisible()) {
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()) {
1287 bool already_used
= false;
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;
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"));
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"));
1308 container
.push_back(Mstring("//variant (") + field
->Data
->actualPath
+ Mstring(") ") + Mstring(hidden_var
->Data
.c_str()) + Mstring(";\n"));
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("[-]");
1317 path
= field
->Data
->actualPath
;
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");
1325 field
->Data
->collectVariants(container
);
1329 void ComplexType::printVariant(FILE * file
) {
1334 bool foundAtLeastOneVariant
= false;
1335 bool foundAtLeastOneHiddenVariant
= false;
1337 if (!variant
.empty()) {
1338 for (List
<Mstring
>::iterator var
= variant
.begin(); var
; var
= var
->Next
) {
1339 if (foundAtLeastOneVariant
&& foundAtLeastOneHiddenVariant
) {
1342 if (var
->Data
[0] != '/') {
1343 foundAtLeastOneVariant
= true;
1345 foundAtLeastOneHiddenVariant
= true;
1350 if (!foundAtLeastOneVariant
&& !foundAtLeastOneHiddenVariant
) {
1354 if (!foundAtLeastOneVariant
) {
1355 //No other variants, only commented, so the 'with' must be commented also.
1356 fprintf(file
, ";\n//with {\n");
1358 fprintf(file
, "\nwith {\n");
1361 for (List
<Mstring
>::iterator var
= variant
.begin(); var
; var
= var
->Next
) {
1362 fprintf(file
, " %s", var
->Data
.c_str());
1365 if (!foundAtLeastOneVariant
) {
1366 fprintf(file
, "//");
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
);
1376 fprintf(stderr
, "%*s parent: %p | parent xsdtype: %s | my xsdtype: %i\n", depth
* 2, "", "NULL", "NULL", xsdtype
);
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);
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);
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());
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());
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");
1403 void ComplexType::setMinMaxOccurs(const unsigned long long min
, const unsigned long long max
, const bool generate_list_postfix
) {
1405 if (min
!= 1 || max
!= 1) {
1406 if (xsdtype
== n_choice
) {
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
);
1422 if ((rec
->getMinOccurs() == 0 && rec
->getMaxOccurs() > 1) || rec
->getMinOccurs() > 0) {
1423 rec
->name
.list_extension
= true;
1428 if ((getMinOccurs() == 0 && getMaxOccurs() > 1) || getMinOccurs() > 0) {
1429 if (generate_list_postfix
) {
1430 name
.list_extension
= true;
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;
1439 first_child
= false;
1449 if (getMaxOccurs() > 1 && generate_list_postfix
) {
1450 name
.list_extension
= true;
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());
1459 token
= strtok(valueToSplitIntoTokens
, " ");
1460 while (token
!= NULL
) {
1461 namespaces
.push_back(Mstring(token
));
1462 token
= strtok(NULL
, " ");
1464 Free(valueToSplitIntoTokens
);
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
+= ',';
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") {
1483 any_ns
+= parent
->getModule()->getTargetNamespace();
1486 }// The three cases below can happen multiple times
1488 if (first
) any_ns
+= " from ";
1489 // else a comma was already added
1490 if (ns
->Data
== xxtargetNamespace
) {
1492 any_ns
+= parent
->getModule()->getTargetNamespace();
1494 } else if (ns
->Data
== xxlocal
) {
1495 any_ns
+= "unqualified";
1506 addVariant(varLabel
, any_ns
, true);
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
);
1516 if (actfield
->getName().convertedValue
== Mstring("base") && parent
!= NULL
) {
1517 parent
->getComment().push_back(Mstring("/* " + text
+ " */\n"));
1519 comment
.push_back(Mstring("/* " + text
+ " */\n"));
1523 actfield
->addComment(text
);
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
) {
1532 if (anyAttrib
!= NULL
&& attr
->Data
->isAnyAttribute()) {
1533 anyAttrib
->addNameSpaceAttribute(attr
->Data
->getNameSpaceAttribute());
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
);
1548 AttributeType
* newAttrib
= new AttributeType(*attr
->Data
);
1549 attribfields
.push_back(newAttrib
);
1550 setParent(this, newAttrib
);
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
;
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
) {
1570 attribfields
.remove(attr
);
1573 size_t size
= found_CT
->attribfields
.size();
1574 size_t size2
= attribfields
.size();
1576 List
<AttributeType
*>::iterator attr
= found_CT
->attribfields
.begin();
1577 for (; i
< size
; attr
= attr
->Next
, i
= i
+ 1) {
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()) {
1585 attr2
->Data
->setUsed(true);
1590 AttributeType
* newAttrib
= new AttributeType(*attr
->Data
);
1591 attribfields
.push_back(newAttrib
);
1592 setParent(this, newAttrib
);
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());
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
);
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());
1614 attr
->setTypeOfField(st
->getName().convertedValue
);
1615 if (st
->getType().convertedValue
== "record" || st
->getType().convertedValue
== "union") {
1616 st
->addToNameDepList(attr
);
1620 printError(module
->getSchemaname(), name
.convertedValue
,
1621 "Reference for a non-defined type: " + attr
->getReference().repr());
1622 TTCN3ModuleInventory::getInstance().incrNumErrors();
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();
1633 outside_reference
.set_resolved(ct
);
1635 bool addNameSpaceas
= false;
1636 if (ct
->getModule()->getTargetNamespace() != module
->getTargetNamespace() &&
1637 ct
->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1638 addNameSpaceas
= true;
1641 if(parent
->nillable
&& parent
->parent
!= NULL
){
1642 par
= parent
->parent
;
1646 List
<AttributeType
*>::iterator anyAttrib
= par
->attribfields
.begin();
1647 for (; anyAttrib
; anyAttrib
= anyAttrib
->Next
) {
1648 if (anyAttrib
->Data
->isAnyAttribute()) {
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());
1658 if (anyAttrib
!= NULL
&& attr
->Data
->isAnyAttribute()) {
1659 anyAttrib
->Data
->addNameSpaceAttribute(attr
->Data
->getNameSpaceAttribute());
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
);
1673 parent
->attribfields
.push_back(attrib
);
1674 setParent(parent
, attrib
);
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
);
1686 if(ct
->resolved
== No
){
1687 ct
->referenceResolving();
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;
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());
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;
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());
1719 parent
->addVariant(V_useOrder
);
1721 if (name
.list_extension
) {
1722 addVariant(V_untagged
);
1724 type
.upload(ct
->getName().convertedValue
);
1725 name
.upload(ct
->getName().convertedValue
);
1726 ct
->addToNameDepList(this);
1729 if (addNameSpaceas
) {
1730 addVariant(V_namespaceAs
, ct
->getModule()->getTargetNamespace());
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
);
1744 addNameSpaceAsVariant(this, st
);
1747 collectElementTypes(st
, NULL
);
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();
1757 st
->addToNameDepList(this);
1763 void ComplexType::resolveSimpleTypeExtension() {
1764 if (mode
== extensionMode
&& cmode
== CT_simpletype_mode
&& basefield
!= NULL
) {
1765 SimpleType
* st
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(basefield
, want_BOTH
);
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();
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
);
1780 if (!st
->getReference().empty() && !st
->getReference().is_resolved()) {
1781 st
->referenceResolving();
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
1791 if (st
->getEnumeration().modified
) {
1792 basefield
->setTypeValue(old_type
);
1793 basefield
->getEnumeration().modified
= false;
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();
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
);
1810 printError(module
->getSchemaname(), name
.convertedValue
,
1811 "Reference for a non-defined type: " + basefield
->getReference().repr());
1812 TTCN3ModuleInventory::getInstance().incrNumErrors();
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();
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
);
1835 if (!st
->getReference().empty() && !st
->getReference().is_resolved()) {
1836 st
->referenceResolving();
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
;
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();
1859 basefield
->outside_reference
.set_resolved(ct
);
1861 if (ct
->resolved
== No
) {
1862 ct
->referenceResolving();
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
);
1869 addNameSpaceAsVariant(this, ct
);
1871 if(!basefield
->parent
->top
){
1872 applyReference(*basefield
, true);
1873 basefield
->setInvisible();
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
);
1882 printError(module
->getSchemaname(), name
.convertedValue
,
1883 "Reference for a non-defined type: " + getReference().repr());
1884 TTCN3ModuleInventory::getInstance().incrNumErrors();
1887 if(ct
->getXsdtype() != n_NOTSET
){
1888 outside_reference
.set_resolved(ct
);
1889 if (ct
->resolved
== No
) {
1890 ct
->referenceResolving();
1892 List
<AttributeType
*>::iterator anyAttr
= attribfields
.begin();
1893 for (; anyAttr
; anyAttr
= anyAttr
->Next
) {
1894 if (anyAttr
->Data
->isAnyAttribute()) {
1899 if (anyAttr
!= NULL
) {
1900 applyAttributeExtension(ct
, anyAttr
->Data
);
1902 applyAttributeExtension(ct
);
1905 if (ct
->getName().convertedValue
== outside_reference
.get_val() && ct
->getModule()->getTargetNamespace() == outside_reference
.get_uri()) {
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
);
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
);
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
);
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();
1945 outside_reference
.set_resolved(ct
);
1946 applyAttributeRestriction(ct
);
1948 size_t size
= complexfields
.size();
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);
1964 field
->Data
->setInvisible();
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();
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
) {
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
);
2005 void ComplexType::modifyAttributeParent() {
2006 if (nillable_field
!= NULL
) {
2007 ((ComplexType
*) nillable_field
)->actfield
= nillable_field
;
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
);
2019 element
= new ComplexType(*(ComplexType
*)st
);
2020 element
->variant
.clear();
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
);
2029 if(st
->getReference().get_ref() != NULL
){
2030 ((SimpleType
*)st
->getReference().get_ref())->addToNameDepList(element
);
2031 nameDep
= ((SimpleType
*)st
->getReference().get_ref());
2033 module
->addElementType(element
->getType().convertedValue
, element
);
2034 element
->addVariant(V_formAs
, Mstring("qualified"));
2037 if(st
->getType().convertedValue
== "anyType"){
2038 newType
= complexfields
.front()->getType().convertedValue
;
2040 newType
= st
->getName().convertedValue
;
2041 st
->addToNameDepList(element
);
2042 element
->nameDep
= st
;
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
);
2058 element
->setNameValue(st
->getName().convertedValue
);
2059 element
->top
= false;
2060 complexfields
.push_back(element
);
2063 void ComplexType::addTypeSubstitution(SimpleType
* st
){
2064 ComplexType
* element
;
2065 if(st
->getXsdtype() == n_NOTSET
|| !complexfields
.empty()){
2066 element
= new ComplexType(*st
, fromTypeSubstitution
);
2068 //Only need a plain complextype
2070 element
= new ComplexType(this);
2071 //Just the block needed from st
2072 element
->block
= st
->getBlock();
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
);
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
);
2095 //Cascading to parent type substitution
2096 if(parentTypeSubsGroup
!= NULL
&& !complexfields
.empty()){
2097 parentTypeSubsGroup
->addTypeSubstitution(st
);
2099 element
->top
= false;
2100 complexfields
.push_back(element
);
2101 element
->setTypeValue(st
->getName().convertedValue
.getValueWithoutPrefix(':'));
2102 element
->setNameValue(st
->getName().convertedValue
.getValueWithoutPrefix(':'));
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(':');
2109 if(!first
&& !isFromRef() && elemType
== head_type
){
2111 }else if((isFromRef() &&
2112 ((elem
->getMode() == restrictionMode
&& block_value
== restriction
) ||
2113 (elem
->getMode() == extensionMode
&& block_value
== extension
))) && elemType
== head_type
){
2115 }else if(!first
&& elemName
== head_type
){
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();
2124 if(elem
->getXsdtype() != n_NOTSET
){
2125 ComplexType
* ct
= (ComplexType
*)elem
;
2126 if(ct
->basefield
!= NULL
&& ct
->basefield
->getType().convertedValue
.getValueWithoutPrefix(':') == head_type
){
2128 }else if(ct
->basefield
!= NULL
){
2129 st
= (SimpleType
*)TTCN3ModuleInventory::getInstance().lookup(ct
->basefield
, want_BOTH
);
2133 st
= (SimpleType
*)(elem
->getReference().get_ref());
2135 }else if(elem
->getMode() == noMode
&& (block_value
== restriction
|| block_value
== extension
)){
2136 st
= (SimpleType
*)TTCN3ModuleInventory::getInstance().lookup(this, elem
->getType().convertedValue
, want_BOTH
);
2138 if(st
!= NULL
&& elem
!= st
){
2139 return findRoot(block_value
, st
, head_type
, false);
2142 if(elem
->getMode() == noMode
&& !first
){
2145 return empty_string
;