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
)
39 , actualPath(empty_string
)
42 , nillable_field(NULL
)
44 , cmode(CT_undefined_mode
)
46 , parentTypeSubsGroup(NULL
)
51 xsdtype
= n_complexType
;
54 ComplexType::ComplexType(ComplexType
& other
)
57 , nillable(other
.nillable
)
58 , enumerated(other
.enumerated
)
60 , with_union(other
.with_union
)
61 , first_child(other
.first_child
)
62 , fromAll(other
.fromAll
)
63 , max_alt(other
.max_alt
)
64 , skipback(other
.skipback
)
65 , lastType(other
.lastType
)
66 , actualPath(other
.actualPath
)
68 , nameDep(other
.nameDep
)
69 , nillable_field(NULL
)
72 , resolved(other
.resolved
)
73 , parentTypeSubsGroup(other
.parentTypeSubsGroup
) {
74 type
.originalValueWoPrefix
= other
.type
.originalValueWoPrefix
;
75 for (List
<AttributeType
*>::iterator attr
= other
.attribfields
.begin(); attr
; attr
= attr
->Next
) {
76 attribfields
.push_back(new AttributeType(*attr
->Data
));
77 attribfields
.back()->parent
= this;
80 for (List
<ComplexType
*>::iterator field
= other
.complexfields
.begin(); field
; field
= field
->Next
) {
81 complexfields
.push_back(new ComplexType(*field
->Data
));
82 complexfields
.back()->parent
= this;
83 if(field
->Data
== other
.basefield
){
84 basefield
= complexfields
.back();
85 }else if(field
->Data
== other
.nillable_field
){
86 nillable_field
= complexfields
.back();
90 if (other
.nameDep
!= NULL
) {
91 SimpleType
* dep
= other
.nameDep
;
92 if(dep
->getSubstitution() != NULL
){
93 dep
->getSubstitution()->addToNameDepList(this);
94 nameDep
= dep
->getSubstitution();
96 other
.nameDep
->addToNameDepList(this);
101 ComplexType::ComplexType(ComplexType
* other
)
102 : SimpleType(other
->getParser(), other
->getModule(), c_unknown
)
113 , actualPath(empty_string
)
116 , nillable_field(NULL
)
118 , cmode(CT_undefined_mode
)
120 , parentTypeSubsGroup(NULL
)
125 xsdtype
= n_complexType
;
127 outside_reference
= ReferenceData();
130 ComplexType::ComplexType(const SimpleType
& other
, CT_fromST c
)
142 , actualPath(empty_string
)
145 , nillable_field(NULL
)
147 , cmode(CT_simpletype_mode
)
149 , parentTypeSubsGroup(NULL
)
155 if(c
!= fromTagSubstitution
&& c
!= fromTypeSubstitution
){
156 module
->replaceLastMainType(this);
157 module
->setActualXsdConstruct(c_complexType
);
159 construct
= c_complexType
;
163 type
.upload(Mstring("union"));
167 case fromTagNillable
:
168 addVariant(V_useNil
);
169 type
.upload(Mstring("record"));
171 case fromTagComplexType
:
172 type
.upload(Mstring("record"));
173 xsdtype
= n_complexType
;
175 case fromTagSubstitution
:
176 type
.upload(Mstring("union"));
177 name
.upload(getName().originalValueWoPrefix
+ Mstring("_group"));
181 hidden_variant
.clear();
182 enumeration
.modified
= false;
183 value
.modified
= false;
184 pattern
.modified
= false;
185 length
.modified
= false;
186 whitespace
.modified
= false;
188 case fromTypeSubstitution
:
189 type
.upload(Mstring("union"));
190 name
.upload(getName().originalValueWoPrefix
+ Mstring("_derivations"));
192 substitutionGroup
= empty_string
;
193 typeSubsGroup
= this;
195 hidden_variant
.clear();
196 enumeration
.modified
= false;
197 value
.modified
= false;
198 pattern
.modified
= false;
199 length
.modified
= false;
200 whitespace
.modified
= false;
204 ComplexType::~ComplexType() {
205 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
209 complexfields
.clear();
211 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
215 attribfields
.clear();
218 void ComplexType::loadWithValues() {
219 //Find the last field where the tag is found
220 if (this != actfield
) {
221 actfield
->loadWithValues();
225 const XMLParser::TagAttributes
& atts
= parser
->getActualTagAttributes();
227 switch (parser
->getActualTagName()) {
229 if (!top
&& xsdtype
!= n_sequence
&& xsdtype
!= n_complexType
&& xsdtype
!= n_extension
&& xsdtype
!= n_restriction
&& xsdtype
!= n_element
) {
231 ComplexType
* rec
= new ComplexType(this);
232 rec
->type
.upload(Mstring("record"));
233 rec
->name
.upload(Mstring("sequence"));
234 rec
->addVariant(V_untagged
);
235 rec
->setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
236 rec
->setXsdtype(n_sequence
);
237 complexfields
.push_back(rec
);
240 //Do not create new record, it is an embedded sequence
241 if (xsdtype
== n_sequence
&& atts
.minOccurs
== 1 && atts
.maxOccurs
== 1) {
244 type
.upload(Mstring("record"));
245 xsdtype
= n_sequence
;
246 setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
250 if (!top
|| xsdtype
!= n_group
) {
251 //Create new union field
252 ComplexType
* choice
= new ComplexType(this);
253 choice
->type
.upload(Mstring("union"));
254 choice
->name
.upload(Mstring("choice"));
255 choice
->setXsdtype(n_choice
);
256 choice
->addVariant(V_untagged
);
257 choice
->setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
259 complexfields
.push_back(choice
);
262 type
.upload(Mstring("union"));
267 //Create the record of enumerated field
269 ComplexType
* enumField
= new ComplexType(this);
270 enumField
->setTypeValue(Mstring("enumerated"));
271 enumField
->setNameValue(Mstring("order"));
272 enumField
->setBuiltInBase(Mstring("string"));
273 enumField
->enumerated
= true;
274 enumField
->setMinMaxOccurs(0, ULLONG_MAX
, false);
275 setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
276 addVariant(V_useOrder
);
277 complexfields
.push_back(enumField
);
278 if (atts
.minOccurs
== 0) {
284 mode
= restrictionMode
;
285 //If it is an xsd:union then call SimpleType::loadWithValues
286 if (parent
!= NULL
&& parent
->with_union
) {
287 SimpleType::loadWithValues();
290 if (cmode
== CT_simpletype_mode
) {
291 //if it is from a SimpleType, then create a base field
292 ComplexType
* f
= new ComplexType(this);
293 f
->name
.upload(Mstring("base"));
294 f
->type
.upload(atts
.base
);
295 f
->setReference(atts
.base
);
296 f
->addVariant(V_untagged
);
297 complexfields
.push_back(f
);
301 // If it is a restriction of a list, then no new basefield will be
302 // present, to we apply the references to the parent.
303 if(parent
!= NULL
&& parent
->inList
) {
304 parent
->applyReference(*f
, true);
306 } else if (cmode
== CT_complextype_mode
) {
307 setReference(atts
.base
);
308 xsdtype
= n_restriction
;
312 mode
= extensionMode
;
313 if (cmode
== CT_simpletype_mode
) {
314 //if it is from a SimpleType, then create a base field
315 ComplexType
* f
= new ComplexType(this);
316 f
->name
.upload(Mstring("base"));
317 f
->type
.upload(atts
.base
);
318 f
->setReference(atts
.base
);
319 f
->addVariant(V_untagged
);
320 complexfields
.push_back(f
);
323 } else if (cmode
== CT_complextype_mode
) {
324 setReference(atts
.base
);
325 xsdtype
= n_extension
;
331 if(cmode
== CT_simpletype_mode
){
332 //If a simple top level element is nillable
333 ComplexType
* nilrec
= new ComplexType(this);
334 if (atts
.type
.empty()) {
335 nilrec
->type
.upload(Mstring("record"));
337 nilrec
->type
.upload(atts
.type
);
339 nilrec
->name
.upload(Mstring("content"));
340 nilrec
->isOptional
= true;
341 nilrec
->nillable
= true;
342 setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
343 complexfields
.push_back(nilrec
);
344 type
.upload(Mstring("record"));
345 name
.upload(atts
.name
);
347 nillable_field
= nilrec
;
349 //From a complexType element is nillable
350 ComplexType
* record
= new ComplexType(this);
351 ComplexType
* nilrec
= new ComplexType(record
);
352 if (atts
.type
.empty()) {
353 nilrec
->type
.upload(Mstring("record"));
355 nilrec
->type
.upload(atts
.type
);
357 record
->name
.upload(atts
.name
);
358 record
->type
.upload(Mstring("record"));
359 record
->complexfields
.push_back(nilrec
);
360 record
->addVariant(V_useNil
);
361 record
->nillable_field
= nilrec
;
362 record
->setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
364 nilrec
->name
.upload(Mstring("content"));
365 nilrec
->nillable
= true;
366 nilrec
->isOptional
= true;
367 nilrec
->tagNames
.push_back(parser
->getActualTagName());
368 complexfields
.push_back(record
);
372 //It is a simple element
373 ComplexType
* c
= new ComplexType(this);
374 c
->setXsdtype(n_element
);
375 c
->type
.upload(atts
.type
);
376 c
->name
.upload(atts
.name
);
377 c
->setReference(atts
.type
);
378 c
->setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
379 c
->applyDefaultAttribute(atts
.default_
);
380 c
->applyFixedAttribute(atts
.fixed
);
381 c
->setElementFormAs(atts
.form
);
382 if (atts
.ref
.empty()) {
383 c
->setReference(atts
.type
);
385 c
->applyRefAttribute(atts
.ref
);
386 c
->name
.upload(atts
.ref
.getValueWithoutPrefix(':'));
387 c
->type
.upload(atts
.ref
);
389 c
->applySubstitionGroupAttribute(atts
.substitionGroup
);
390 c
->applyBlockAttribute(atts
.block
);
393 //Inside all have some special conditions
394 if (xsdtype
== n_all
) {
395 if (atts
.minOccurs
> 1) {
396 printError(getModule()->getSchemaname(), name
.convertedValue
,
397 Mstring("Inside <all>, minOccurs must be 0 or 1"));
398 TTCN3ModuleInventory::incrNumErrors();
400 if (atts
.maxOccurs
!= 1) {
401 printError(getModule()->getSchemaname(), name
.convertedValue
,
402 Mstring("Inside <all>, maxOccurs must be 1"));
403 TTCN3ModuleInventory::incrNumErrors();
406 complexfields
.push_back(c
);
408 c
->isOptional
= true;
411 complexfields
.push_back(c
);
418 AttributeType
* attribute
= new AttributeType(this);
419 attribute
->addVariant(V_attribute
);
420 attribute
->applyMinMaxOccursAttribute(0, 1);
421 attribute
->setXsdtype(n_attribute
);
422 attribute
->applyDefaultAttribute(atts
.default_
);
423 attribute
->applyFixedAttribute(atts
.fixed
);
424 attribute
->setUseVal(atts
.use
);
425 attribute
->setAttributeFormAs(atts
.form
);
426 lastType
= n_attribute
;
427 if (atts
.ref
.empty()) {
428 attribute
->setNameOfField(atts
.name
);
429 attribute
->setTypeOfField(atts
.type
);
430 attribute
->setReference(atts
.type
, true);
432 attribute
->applyRefAttribute(atts
.ref
);
434 actfield
= attribute
;
436 //In case of nillable parent it is difficult...
437 if (nillable
&& parent
!= NULL
) {
438 parent
->attribfields
.push_back(attribute
);
439 attribute
->parent
= parent
;
440 } else if (nillable
&& !complexfields
.empty() && parent
== NULL
) {
441 complexfields
.back()->attribfields
.push_back(attribute
);
442 } else if (parent
!= NULL
&& (parent
->mode
== extensionMode
|| parent
->mode
== restrictionMode
) && name
.convertedValue
== Mstring("base")) {
443 parent
->attribfields
.push_back(attribute
);
444 attribute
->parent
= parent
;
446 attribfields
.push_back(attribute
);
452 ComplexType
* any
= new ComplexType(this);
453 any
->name
.upload(Mstring("elem"));
454 any
->type
.upload(Mstring("xsd:string"));
455 any
->applyNamespaceAttribute(V_anyElement
, atts
.namespace_
);
456 any
->setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
457 any
->setXsdtype(n_any
);
458 complexfields
.push_back(any
);
463 AttributeType
* anyattr
= new AttributeType(this);
464 anyattr
->setXsdtype(n_anyAttribute
);
465 anyattr
->setNameOfField(Mstring("attr"));
466 anyattr
->setTypeValue(Mstring("xsd:string"));
467 anyattr
->setToAnyAttribute();
468 anyattr
->applyMinMaxOccursAttribute(0, ULLONG_MAX
);
469 anyattr
->addNameSpaceAttribute(atts
.namespace_
);
472 //In case of nillable parent it is difficult...
473 if (nillable
&& parent
!= NULL
) {
474 parent
->attribfields
.push_back(anyattr
);
475 anyattr
->parent
= parent
;
476 } else if (nillable
&& !complexfields
.empty() && parent
== NULL
) {
477 complexfields
.back()->attribfields
.push_back(anyattr
);
478 } else if (parent
!= NULL
&& (parent
->mode
== extensionMode
|| parent
->mode
== restrictionMode
) && name
.convertedValue
== Mstring("base")) {
479 parent
->attribfields
.push_back(anyattr
);
480 anyattr
->parent
= parent
;
482 attribfields
.push_back(anyattr
);
486 case n_attributeGroup
:
487 if (!atts
.ref
.empty()) {
488 ComplexType
* g
= new ComplexType(this);
489 g
->setXsdtype(n_attributeGroup
);
490 g
->setReference(atts
.ref
);
491 complexfields
.push_back(g
);
494 xsdtype
= n_attributeGroup
;
495 name
.upload(Mstring(atts
.name
));
500 if (atts
.ref
.empty()) {
503 name
.upload(atts
.name
);
506 ComplexType
* group
= new ComplexType(this);
507 group
->setXsdtype(n_group
);
508 group
->name
.upload(atts
.name
);
509 group
->setReference(Mstring(atts
.ref
));
510 group
->setMinMaxOccurs(atts
.minOccurs
, atts
.maxOccurs
);
511 complexfields
.push_back(group
);
519 type
.upload(Mstring("union"));
520 addVariant(V_useUnion
);
521 if (!atts
.memberTypes
.empty()) {
523 //Get the union values
524 expstring_t valueToSplitIntoTokens
= mcopystr(atts
.memberTypes
.c_str());
526 token
= strtok(valueToSplitIntoTokens
, " ");
527 while (token
!= NULL
) {
528 types
.push_back(Mstring(token
));
529 token
= strtok(NULL
, " ");
531 Free(valueToSplitIntoTokens
);
533 //Create the union elements and push into the container
534 for (List
<Mstring
>::iterator memberType
= types
.begin(); memberType
; memberType
= memberType
->Next
) {
535 Mstring tmp_name
= memberType
->Data
.getValueWithoutPrefix(':');
536 ComplexType
* f
= new ComplexType(this);
537 f
->name
.upload(tmp_name
);
538 f
->type
.upload(memberType
->Data
);
539 f
->setXsdtype(n_simpleType
);
540 f
->setReference(memberType
->Data
);
541 complexfields
.push_back(f
);
547 case n_simpleContent
:
549 xsdtype
= parser
->getActualTagName();
550 cmode
= CT_simpletype_mode
;
554 fieldname
= Mstring("alt_");
556 fieldname
= mprintf("alt_%d", max_alt
);
559 ComplexType
* field
= new ComplexType(this);
560 field
->name
.upload(fieldname
);
561 field
->setXsdtype(n_simpleType
);
562 field
->addVariant(V_nameAs
, empty_string
, true);
563 complexfields
.push_back(field
);
569 name
.upload(atts
.name
);
570 type
.upload(Mstring("record"));
571 applyAbstractAttribute(atts
.abstract
);
572 applySubstitionGroupAttribute(atts
.substitionGroup
);
573 applyBlockAttribute(atts
.block
);
575 case n_complexContent
:
576 tagNames
.push_back(parser
->getActualTagName());
577 cmode
= CT_complextype_mode
;
579 ComplexType
* mixed
= new ComplexType(this);
580 mixed
->name
.upload(Mstring("embed_values"));
581 mixed
->type
.upload(Mstring("xsd:string"));
582 mixed
->setMinMaxOccurs(0, ULLONG_MAX
, false);
584 complexfields
.push_back(mixed
);
585 addVariant(V_embedValues
);
589 if (parent
!= NULL
&& parent
->basefield
== this) {
590 parent
->inList
= true;
591 parent
->SimpleType::loadWithValues();
592 parent
->basefield
= NULL
;
594 } else if(parent
!= NULL
) {
595 SimpleType::loadWithValues();
609 case n_fractionDigits
:
610 SimpleType::loadWithValues();
613 addComment(Mstring("LABEL:"));
616 addComment(Mstring("DEFINITION:"));
623 // called from endelementHandler
624 void ComplexType::modifyValues() {
625 if (this != actfield
) {
626 actfield
->modifyValues();
629 if (xsdtype
== n_sequence
) {
630 skipback
= skipback
- 1;
634 if ( parent
!= NULL
&&
635 (xsdtype
== n_element
||
636 xsdtype
== n_complexType
||
637 xsdtype
== n_complexContent
||
639 xsdtype
== n_attribute
||
640 xsdtype
== n_anyAttribute
||
641 xsdtype
== n_choice
||
642 xsdtype
== n_group
||
643 xsdtype
== n_attributeGroup
||
644 xsdtype
== n_extension
||
645 xsdtype
== n_restriction
||
646 (xsdtype
== n_simpleType
&& !inList
) ||
647 xsdtype
== n_simpleContent
||
648 (xsdtype
== n_sequence
&& skipback
< 0)
650 if (!tagNames
.empty() && tagNames
.back() == parser
->getParentTagName()) {
651 if (nillable
&& tagNames
.back() == n_element
) {
652 parent
->modifyValues();
655 } else if (tagNames
.empty()) {
656 parent
->actfield
= parent
;
657 parent
->lastType
= xsdtype
;
660 if (xsdtype
== n_simpleType
) {
665 void ComplexType::referenceResolving() {
666 if (resolved
!= No
) return; // nothing to do
667 if(this == subsGroup
){
671 resolved
= InProgress
;
672 for (List
<ComplexType
*>::iterator ct
= complexfields
.begin(); ct
; ct
= ct
->Next
) {
673 // Referenece resolving of ComplexTypes
674 ct
->Data
->referenceResolving();
676 for (List
<AttributeType
*>::iterator attr
= attribfields
.begin(); attr
; attr
= attr
->Next
) {
677 //Reference resolving for Attributes
678 resolveAttribute(attr
->Data
);
681 reference_resolving_funtion();
683 if(!substitutionGroup
.empty()){
684 addToSubstitutions();
689 void ComplexType::reference_resolving_funtion() {
690 //Every child element references are resolved here.
691 if (outside_reference
.empty() && basefield
== NULL
) {
692 //Its not in the resolveElement function because we need the built in type
693 //reference too, and then the outside_reference is empty.
694 if(xsdtype
== n_element
){
695 collectElementTypes(NULL
, NULL
);
700 SimpleType
* st
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(this, want_BOTH
);
701 if (st
== NULL
&& basefield
== NULL
) {
702 printError(module
->getSchemaname(), name
.convertedValue
,
703 "Reference for a non-defined type: " + getReference().repr());
704 TTCN3ModuleInventory::getInstance().incrNumErrors();
705 outside_reference
.set_resolved(NULL
);
709 resolveAttributeGroup(st
);
715 resolveSimpleTypeExtension();
717 resolveSimpleTypeRestriction();
719 resolveComplexTypeExtension();
721 resolveComplexTypeRestriction();
725 addToTypeSubstitutions();
729 void ComplexType::setParent(ComplexType
* par
, SimpleType
* child
) {
733 void ComplexType::applyReference(const SimpleType
& other
, const bool on_attributes
) {
734 type
.convertedValue
= other
.getType().convertedValue
;
735 type
.originalValueWoPrefix
= other
.getType().convertedValue
.getValueWithoutPrefix(':');
737 if (other
.getMinOccurs() > getMinOccurs() ||
738 other
.getMaxOccurs() < getMaxOccurs()) {
739 if (!on_attributes
) {
740 expstring_t temp
= memptystr();
743 "The occurrence range (%llu .. %llu) of the element (%s) is not compatible "
744 "with the occurrence range (%llu .. %llu) of the referenced element.",
747 name
.originalValueWoPrefix
.c_str(),
748 other
.getMinOccurs(),
749 other
.getMaxOccurs());
750 printError(module
->getSchemaname(), parent
->getName().originalValueWoPrefix
,
753 TTCN3ModuleInventory::getInstance().incrNumErrors();
756 setMinOccurs(llmax(getMinOccurs(), other
.getMinOccurs()));
757 setMaxOccurs(llmin(getMaxOccurs(), other
.getMaxOccurs()));
760 for (List
<Mstring
>::iterator var
= other
.getVariantRef().begin(); var
; var
= var
->Next
) {
762 for (List
<Mstring
>::iterator var1
= variant
.begin(); var1
; var1
= var1
->Next
) {
763 if (var
->Data
== var1
->Data
) {
769 variant
.push_back(var
->Data
);
770 variant_ref
.push_back(var
->Data
);
774 builtInBase
= other
.getBuiltInBase();
776 length
.applyReference(other
.getLength());
777 pattern
.applyReference(other
.getPattern());
778 enumeration
.applyReference(other
.getEnumeration());
779 whitespace
.applyReference(other
.getWhitespace());
780 value
.applyReference(other
.getValue());
783 void ComplexType::nameConversion(NameConversionMode conversion_mode
, const List
<NamespaceType
> & ns
) {
785 switch (conversion_mode
) {
787 nameConversion_names(ns
);
790 nameConversion_types(ns
);
793 nameConversion_fields(ns
);
798 void ComplexType::nameConversion_names(const List
<NamespaceType
> &) {
799 Mstring res
, var(module
->getTargetNamespace());
800 XSDName2TTCN3Name(name
.convertedValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_name
, res
, var
);
801 name
.convertedValue
= res
;
803 for (List
<Mstring
>::iterator vari
= variant
.begin(); vari
; vari
= vari
->Next
) {
804 if (vari
->Data
== "\"untagged\"") {
810 addVariant(V_onlyValue
, var
);
812 for (List
<SimpleType
*>::iterator dep
= nameDepList
.begin(); dep
; dep
= dep
->Next
) {
813 dep
->Data
->setTypeValue(res
);
817 void ComplexType::nameConversion_types(const List
<NamespaceType
> & ns
) {
818 attribfields
.sort(compareAttributeNameSpaces
);
819 attribfields
.sort(compareAttributeTypes
);
820 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
821 field
->Data
->nameConversion(typeMode
, ns
);
824 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
825 field
->Data
->nameConversion_types(ns
);
828 Mstring prefix
, uri
, typeValue
;
830 if (type
.convertedValue
== "record" ||
831 type
.convertedValue
== "set" ||
832 type
.convertedValue
== "union" ||
833 type
.convertedValue
== "enumerated") {
837 prefix
= type
.convertedValue
.getPrefix(':');
838 typeValue
= type
.convertedValue
.getValueWithoutPrefix(':');
840 for (List
<NamespaceType
>::iterator namesp
= ns
.begin(); namesp
; namesp
= namesp
->Next
) {
841 if (prefix
== namesp
->Data
.prefix
) {
842 uri
= namesp
->Data
.uri
;
847 QualifiedName
in(uri
, typeValue
); // ns uri + original name
849 // Check all known types
850 QualifiedNames::iterator origTN
= TTCN3ModuleInventory::getInstance().getTypenames().begin();
851 for (; origTN
; origTN
= origTN
->Next
) {
852 if (origTN
->Data
== in
) {
853 QualifiedName
tmp_name(module
->getTargetNamespace(), name
.convertedValue
);
854 if (origTN
->Data
!= tmp_name
){
860 if (origTN
!= NULL
) {
861 setTypeValue(origTN
->Data
.name
);
864 XSDName2TTCN3Name(typeValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
, type
.no_replace
);
869 void ComplexType::nameConversion_fields(const List
<NamespaceType
> & ns
) {
870 QualifiedNames used_field_names
;
872 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
873 field
->Data
->nameConversion_names(used_field_names
);
876 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
877 if (field
->Data
->getMinOccurs() == 0 && field
->Data
->getMaxOccurs() == 0) {
880 if (!field
->Data
->isVisible()) {
884 field
->Data
->nameConversion_fields(ns
);
886 Mstring prefix
= field
->Data
->getType().convertedValue
.getPrefix(':');
887 Mstring typeValue
= field
->Data
->getType().convertedValue
.getValueWithoutPrefix(':');
890 var
= getModule()->getTargetNamespace();
891 XSDName2TTCN3Name(typeValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
);
893 field
->Data
->addVariant(V_onlyValue
, var
);
894 var
= getModule()->getTargetNamespace();
896 if (field
->Data
->getName().list_extension
) {
897 field
->Data
->useNameListProperty();
898 XSDName2TTCN3Name(field
->Data
->getName().convertedValue
,
899 used_field_names
, field_name
, res
, var
);
900 field
->Data
->setNameValue(res
);
901 bool found_in_variant
= false;
902 for (List
<Mstring
>::iterator vari
= field
->Data
->getVariant().begin(); vari
; vari
= vari
->Next
) {
903 if (vari
->Data
== Mstring("\"untagged\"")) {
904 found_in_variant
= true;
908 if (!field
->Data
->getName().originalValueWoPrefix
.empty() &&
909 field
->Data
->getName().originalValueWoPrefix
!= "sequence" &&
910 field
->Data
->getName().originalValueWoPrefix
!= "choice" &&
911 field
->Data
->getName().originalValueWoPrefix
!= "elem" &&
913 field
->Data
->addVariant(V_nameAs
, field
->Data
->getName().originalValueWoPrefix
);
917 if (!found_in_variant
) {
918 field
->Data
->addVariant(V_untagged
, empty_string
, true);
921 XSDName2TTCN3Name(field
->Data
->getName().convertedValue
,
922 used_field_names
, field_name
, res
, var
);
923 field
->Data
->setNameValue(res
);
924 field
->Data
->addVariant(V_onlyValue
, var
);
930 void ComplexType::setFieldPaths(Mstring path
) {
933 Mstring field_prefix
= empty_string
;
934 if(parent
->getMinOccurs() == 0 && parent
->getMaxOccurs() == ULLONG_MAX
){
935 field_prefix
= "[-].";
937 path
= field_prefix
+ getName().convertedValue
;
938 actualPath
= field_prefix
+ getName().convertedValue
;
940 actualPath
= getName().convertedValue
;
942 } else if (parent
!= NULL
&& (parent
->getMinOccurs() != 1 || parent
->getMaxOccurs() != 1) &&
943 (parent
->getName().list_extension
|| parent
->mode
== listMode
)) {
944 path
= path
+ Mstring("[-].") + getName().convertedValue
;
947 path
= path
+ Mstring(".") + getName().convertedValue
;
951 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
952 field
->Data
->setFieldPaths(path
);
954 for (List
<AttributeType
*>::iterator attr
= attribfields
.begin(); attr
; attr
= attr
->Next
) {
955 attr
->Data
->setFieldPath(path
);
959 void ComplexType::finalModification2() {
960 //Call SimpleType finalModification
961 SimpleType::finalModification();
963 //Set isOptional field
964 isOptional
= isOptional
|| (getMinOccurs() == 0 && getMaxOccurs() == 1);
967 List
<Mstring
> enumNames
;
968 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(), nextField
; field
; field
= nextField
) {
969 nextField
= field
->Next
;
970 //Remove invisible fields
971 if ((field
->Data
->getMinOccurs() == 0 && field
->Data
->getMaxOccurs() == 0) || !field
->Data
->isVisible()) {
974 complexfields
.remove(field
);
977 field
->Data
->finalModification2();
978 //collect <xsd:all> elements
979 if (field
->Data
->fromAll
) {
980 enumNames
.push_back(field
->Data
->getName().convertedValue
);
985 ComplexType
* embedField
= NULL
;
986 ComplexType
* enumField
= NULL
;
988 //Find the embed and order fields, and remove them
989 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(), nextField
; field
; field
= nextField
) {
990 nextField
= field
->Next
;
991 if (field
->Data
->embed
) {
992 embedField
= new ComplexType(*field
->Data
);
993 embedField
->parent
= this;
996 complexfields
.remove(field
);
997 } else if (field
->Data
->enumerated
) {
998 enumField
= new ComplexType(*field
->Data
);
999 enumField
->parent
= this;
1002 complexfields
.remove(field
);
1006 if (enumField
!= NULL
) {
1007 //Insert the order field in the front
1008 complexfields
.push_front(enumField
);
1009 //Push the field names into the order field
1010 for (List
<Mstring
>::iterator field
= enumNames
.begin(); field
; field
= field
->Next
) {
1011 enumField
->enumfields
.push_back(field
->Data
);
1015 if (embedField
!= NULL
) {
1016 //Insert the embed field to the front
1017 complexfields
.push_front(embedField
);
1021 unsigned number
= 0;
1022 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
1023 if (field
->Data
->name
.convertedValue
.foundAt("alt_") == field
->Data
->name
.convertedValue
.c_str()) {
1025 field
->Data
->name
.upload(Mstring("alt_"));
1027 field
->Data
->name
.upload(Mstring(mprintf("alt_%d", number
)));
1034 AttributeType
* anyAttr
= NULL
;
1035 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(), nextField
; field
; field
= nextField
) {
1036 nextField
= field
->Next
;
1037 field
->Data
->applyUseAttribute();
1038 //Find anyattribute, and remove it
1039 if (field
->Data
->isAnyAttribute()) {
1040 anyAttr
= new AttributeType(*field
->Data
);
1041 setParent(this, anyAttr
);
1044 attribfields
.remove(field
);
1045 } else if (field
->Data
->getUseVal() == prohibited
|| !field
->Data
->isVisible()) {
1046 //Not visible attribute removed
1049 attribfields
.remove(field
);
1051 field
->Data
->SimpleType::finalModification();
1055 //Push anyattribute to the front
1056 if (anyAttr
!= NULL
) {
1057 anyAttr
->applyNamespaceAttribute(V_anyAttributes
);
1058 attribfields
.push_back(anyAttr
);
1061 //Substitution group ordering
1062 if(subsGroup
== this || typeSubsGroup
== this){ //We are a generated substitution group
1063 //Substitution group never empty
1064 ComplexType
* front
= complexfields
.front();
1065 List
<ComplexType
*>::iterator it
= complexfields
.begin();
1066 complexfields
.remove(it
);
1067 complexfields
.sort(compareComplexTypeNameSpaces
);
1068 complexfields
.sort(compareTypes
);
1069 complexfields
.push_front(front
);
1073 void ComplexType::finalModification() {
1074 finalModification2();
1075 setFieldPaths(empty_string
);
1076 List
<Mstring
> container
;
1077 collectVariants(container
);
1079 variant
= container
;
1082 void ComplexType::printToFile(FILE * file
) {
1083 printToFile(file
, 0, false);
1086 void ComplexType::printToFile(FILE * file
, const unsigned level
, const bool is_union
) {
1090 printComment(file
, level
);
1092 fprintf(file
, "type ");
1093 if(mode
== listMode
){
1094 printMinOccursMaxOccurs(file
, is_union
);
1095 fprintf(file
, "%s", type
.convertedValue
.c_str());
1097 fprintf(file
, "%s %s", type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
1099 fprintf(file
, "\n{\n");
1101 if (attribfields
.empty() && complexfields
.empty()) {
1102 fprintf(file
, "\n");
1105 for (List
<ComplexType
*>::iterator c
= complexfields
.begin(), nextField
; c
; c
= nextField
) {
1106 nextField
= c
->Next
;
1107 if (c
->Data
->embed
|| c
->Data
->enumerated
) {
1108 c
->Data
->printToFile(file
, level
+ 1, is_union
);
1109 if (c
->Next
!= NULL
|| !attribfields
.empty()) {
1110 fprintf(file
, ",\n");
1112 fprintf(file
, "\n");
1116 complexfields
.remove(c
);
1120 for (List
<AttributeType
*>::iterator f
= attribfields
.begin(); f
; f
= f
->Next
) {
1121 f
->Data
->printToFile(file
, level
+ 1);
1122 if (f
->Next
!= NULL
|| !complexfields
.empty()) {
1123 fprintf(file
, ",\n");
1125 fprintf(file
, "\n");
1129 for (List
<ComplexType
*>::iterator c
= complexfields
.begin(); c
; c
= c
->Next
) {
1130 c
->Data
->printToFile(file
, level
+ 1, is_union
);
1131 if (c
->Next
!= NULL
) {
1132 fprintf(file
, ",\n");
1134 fprintf(file
, "\n");
1138 const bool field_is_record
= getType().convertedValue
== Mstring("record");
1139 const bool field_is_union
= getType().convertedValue
== "union";
1140 if (complexfields
.empty() && attribfields
.empty() && (field_is_record
|| field_is_union
)) {
1141 if (field_is_record
) {
1142 indent(file
, level
);
1143 printMinOccursMaxOccurs(file
, is_union
);
1144 fprintf(file
, "%s {\n", getType().convertedValue
.c_str());
1145 indent(file
, level
);
1146 fprintf(file
, "} %s", getName().convertedValue
.c_str());
1148 fprintf(file
, " optional");
1150 } else if (field_is_union
) {
1151 indent(file
, level
);
1152 printMinOccursMaxOccurs(file
, is_union
);
1153 fprintf(file
, "%s {\n", getType().convertedValue
.c_str());
1154 indent(file
, level
+ 1);
1155 fprintf(file
, "record length(0 .. 1) of enumerated { NULL_ } choice\n");
1156 indent(file
, level
);
1157 fprintf(file
, "} %s", getName().convertedValue
.c_str());
1159 fprintf(file
, " optional");
1163 indent(file
, level
);
1164 if (getEnumeration().modified
) {
1165 if (isFloatType(getBuiltInBase())) {
1166 fprintf(file
, "%s (", type
.convertedValue
.c_str());
1167 getEnumeration().sortFacets();
1168 getEnumeration().printToFile(file
);
1171 printMinOccursMaxOccurs(file
, with_union
);
1172 fprintf(file
, "enumerated {\n");
1173 //getEnumeration().sortFacets();
1174 getEnumeration().printToFile(file
, level
);
1175 fprintf(file
, "\n");
1176 indent(file
, level
);
1177 fprintf(file
, "} ");
1180 int multiplicity
= multi(module
, getReference(), this);
1181 if ((multiplicity
> 1) && getReference().get_ref()) {
1182 fprintf(file
, "%s.", getReference().get_ref()->getModule()->getModulename().c_str());
1184 if (field_is_record
|| field_is_union
) {
1185 printMinOccursMaxOccurs(file
, with_union
, !first_child
|| parent
->getXsdtype() != n_choice
);
1186 fprintf(file
, "%s {\n", getType().convertedValue
.c_str());
1187 for (List
<AttributeType
*>::iterator f
= attribfields
.begin(); f
; f
= f
->Next
) {
1188 f
->Data
->printToFile(file
, level
+ 1);
1189 if (f
->Next
!= NULL
|| !complexfields
.empty()) {
1190 fprintf(file
, ",\n");
1192 fprintf(file
, "\n");
1196 for (List
<ComplexType
*>::iterator c
= complexfields
.begin(); c
; c
= c
->Next
) {
1197 c
->Data
->printToFile(file
, level
+ 1, is_union
);
1198 if (c
->Next
!= NULL
) {
1199 fprintf(file
, ",\n");
1201 fprintf(file
, "\n");
1205 printMinOccursMaxOccurs(file
, with_union
, !first_child
);
1206 fprintf(file
, "%s ", getType().convertedValue
.c_str());
1207 if (getName().convertedValue
== Mstring("order") && getType().convertedValue
== Mstring("enumerated")) {
1208 fprintf(file
, "{\n");
1209 for (List
<Mstring
>::iterator e
= enumfields
.begin(); e
; e
= e
->Next
) {
1210 indent(file
, level
+ 1);
1211 fprintf(file
, "%s", e
->Data
.c_str());
1212 if (e
->Next
!= NULL
) {
1213 fprintf(file
, ",\n");
1215 fprintf(file
, "\n");
1218 indent(file
, level
);
1219 fprintf(file
, "} ");
1223 if (field_is_record
|| field_is_union
) {
1224 indent(file
, level
);
1225 fprintf(file
, "} ");
1228 fprintf(file
, "%s", getName().convertedValue
.c_str());
1229 getPattern().printToFile(file
);
1230 getValue().printToFile(file
);
1231 getLength().printToFile(file
);
1232 if (!with_union
&& isOptional
) {
1233 fprintf(file
, " optional");
1240 if(mode
== listMode
){
1241 fprintf(file
, " %s", name
.convertedValue
.c_str());
1244 fprintf(file
, ";\n\n\n");
1248 void ComplexType::collectVariants(List
<Mstring
>& container
) {
1250 if (e_flag_used
|| !isVisible()) {
1255 bool useUnionVariantWhenMainTypeIsRecordOf
= false;
1256 for (List
<Mstring
>::iterator var
= variant
.end(); var
; var
= var
->Prev
) {
1257 if ((getMinOccurs() != 1 || getMaxOccurs() != 1) && (var
->Data
== "\"useUnion\"")) { // main type is a record of
1258 useUnionVariantWhenMainTypeIsRecordOf
= true; // TR HL15893
1260 container
.push_back(Mstring("variant ") + Mstring(var
->Data
.c_str()) + Mstring(";\n"));
1263 if (useUnionVariantWhenMainTypeIsRecordOf
) {
1264 container
.push_back(Mstring("variant ([-]) \"useUnion\";\n"));
1266 for (List
<Mstring
>::iterator var
= hidden_variant
.end(); var
; var
= var
->Prev
) {
1267 container
.push_back(Mstring("//variant ") + Mstring(var
->Data
.c_str()) + Mstring(";\n"));
1271 //Collect variants of attributes
1272 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
1273 field
->Data
->collectVariants(container
);
1276 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
1278 if (!field
->Data
->isVisible()) {
1282 if (field
->Data
->getVariant().empty() && field
->Data
->getHiddenVariant().empty() &&
1283 field
->Data
->complexfields
.empty() && field
->Data
->attribfields
.empty() &&
1284 field
->Data
->enumeration
.variants
.empty()) {
1288 bool already_used
= false;
1290 for (List
<Mstring
>::iterator var2
= field
->Data
->getVariant().end(); var2
; var2
= var2
->Prev
) {
1291 if (var2
->Data
== "\"untagged\"" && !already_used
) {
1292 container
.push_back(Mstring("variant (") + field
->Data
->actualPath
+ Mstring(") ") + Mstring(var2
->Data
.c_str()) + Mstring(";\n"));
1293 already_used
= true;
1295 if ((field
->Data
->getMinOccurs() != 1 || field
->Data
->getMaxOccurs() != 1) &&
1296 (field
->Data
->getName().list_extension
|| var2
->Data
== "\"useUnion\"")) {
1297 container
.push_back(Mstring("variant (") + field
->Data
->actualPath
+ Mstring("[-]) ") + Mstring(var2
->Data
.c_str()) + Mstring(";\n"));
1298 } else if (var2
->Data
!= "\"untagged\"") {
1299 container
.push_back(Mstring("variant (") + field
->Data
->actualPath
+ Mstring(") ") + Mstring(var2
->Data
.c_str()) + Mstring(";\n"));
1303 for (List
<Mstring
>::iterator hidden_var
= field
->Data
->getHiddenVariant().end();
1304 hidden_var
; hidden_var
= hidden_var
->Prev
) {
1305 if ((field
->Data
->getMinOccurs() != 1 || field
->Data
->getMaxOccurs() != 1) &&
1306 field
->Data
->getName().list_extension
) {
1307 container
.push_back(Mstring("//variant (") + field
->Data
->actualPath
+ Mstring("[-]) ") + Mstring(hidden_var
->Data
.c_str()) + Mstring(";\n"));
1309 container
.push_back(Mstring("//variant (") + field
->Data
->actualPath
+ Mstring(") ") + Mstring(hidden_var
->Data
.c_str()) + Mstring(";\n"));
1313 if(field
->Data
->enumeration
.modified
){
1314 Mstring path
= empty_string
;
1315 if(field
->Data
->getMinOccurs() != 1 && field
->Data
->getMaxOccurs() != 1){
1316 path
= field
->Data
->actualPath
+ Mstring("[-]");
1318 path
= field
->Data
->actualPath
;
1320 for(List
<Mstring
>::iterator var
= field
->Data
->enumeration
.variants
.end(); var
; var
= var
->Prev
){
1321 if(var
->Data
.empty()) continue;
1322 container
.push_back("variant (" + path
+ ") " + var
->Data
+ ";\n");
1326 field
->Data
->collectVariants(container
);
1330 void ComplexType::printVariant(FILE * file
) {
1335 bool foundAtLeastOneVariant
= false;
1336 bool foundAtLeastOneHiddenVariant
= false;
1338 if (!variant
.empty()) {
1339 for (List
<Mstring
>::iterator var
= variant
.begin(); var
; var
= var
->Next
) {
1340 if (foundAtLeastOneVariant
&& foundAtLeastOneHiddenVariant
) {
1343 if (var
->Data
[0] != '/') {
1344 foundAtLeastOneVariant
= true;
1346 foundAtLeastOneHiddenVariant
= true;
1351 if (!foundAtLeastOneVariant
&& !foundAtLeastOneHiddenVariant
) {
1355 if (!foundAtLeastOneVariant
) {
1356 //No other variants, only commented, so the 'with' must be commented also.
1357 fprintf(file
, ";\n//with {\n");
1359 fprintf(file
, "\nwith {\n");
1362 for (List
<Mstring
>::iterator var
= variant
.begin(); var
; var
= var
->Next
) {
1363 fprintf(file
, " %s", var
->Data
.c_str());
1366 if (!foundAtLeastOneVariant
) {
1367 fprintf(file
, "//");
1372 void ComplexType::dump(unsigned int depth
) const {
1373 fprintf(stderr
, "%*s %sComplexType at %p | Top:%s\n", depth
* 2, "", isVisible() ? "" : "(hidden)", (const void*) this, top
? "true" : "false");
1374 if (parent
!= NULL
) {
1375 fprintf(stderr
, "%*s parent: %p | parent xsdtype: %i | my xsdtype: %i\n", depth
* 2, "", (const void*) parent
, parent
->getXsdtype(), xsdtype
);
1377 fprintf(stderr
, "%*s parent: %p | parent xsdtype: %s | my xsdtype: %i\n", depth
* 2, "", "NULL", "NULL", xsdtype
);
1379 fprintf(stderr
, "%*s name='%s' -> '%s', type='%s' %d complexfields | %s | %s | %s\n", depth
* 2, "",
1380 name
.originalValueWoPrefix
.c_str(), name
.convertedValue
.c_str(), type
.convertedValue
.c_str(), (int) complexfields
.size(),
1381 outside_reference
.empty() ? "" : outside_reference
.get_val().c_str(), mode
== restrictionMode
? "restriction" : "",
1382 mode
== extensionMode
? "extension" : "");
1383 for (List
<ComplexType
*>::iterator field
= complexfields
.begin(); field
; field
= field
->Next
) {
1384 field
->Data
->dump(depth
+ 1);
1386 fprintf(stderr
, "%*s %d attribields\n", depth
* 2, "", (int) attribfields
.size());
1387 for (List
<AttributeType
*>::iterator field
= attribfields
.begin(); field
; field
= field
->Next
) {
1388 field
->Data
->dump(depth
+ 1);
1390 fprintf(stderr
, "%*s %d enumfields\n", depth
* 2, "", (int) enumfields
.size());
1391 for (List
<Mstring
>::iterator field
= enumfields
.begin(); field
; field
= field
->Next
) {
1392 fprintf(stderr
, "%*s enum: %s\n", depth
* 2 + depth
, "", field
->Data
.c_str());
1394 fprintf(stderr
, "%*s (%llu .. %llu) | Optional:%s | List:%s\n", (depth
+ 1) * 2, "", getMinOccurs(), getMaxOccurs(), isOptional
? "true" : "false", name
.list_extension
? "true" : "false");
1395 fprintf(stderr
, "%*s %d variants: ", (depth
+ 1) * 2, "", (int) variant
.size());
1396 for (List
<Mstring
>::iterator var
= variant
.begin(); var
; var
= var
->Next
) {
1397 fprintf(stderr
, "%s, ", var
->Data
.c_str());
1399 fprintf(stderr
, "%*s pattern:%s | length:%i \n ", (depth
+ 1) * 2, "", this->pattern
.facet
.c_str(), (int) (this->length
.facet_maxLength
));
1400 fprintf(stderr
, "%*s enum: %i \n", (depth
+ 1)*2, "", (int) this->enumeration
.facets
.size());
1401 fprintf(stderr
, "\n");
1404 void ComplexType::setMinMaxOccurs(const unsigned long long min
, const unsigned long long max
, const bool generate_list_postfix
) {
1406 if (min
!= 1 || max
!= 1) {
1407 if (xsdtype
== n_choice
) {
1410 addVariant(V_untagged
);
1411 first_child
= false;
1412 } else if (xsdtype
== n_sequence
) {
1413 ComplexType
* rec
= new ComplexType(this);
1414 rec
->type
.upload(Mstring("record"));
1415 rec
->name
.upload(Mstring("sequence"));
1416 rec
->setXsdtype(n_sequence
);
1417 rec
->addVariant(V_untagged
);
1418 rec
->addVariant(V_untagged
);
1419 rec
->setMinOccurs(min
);
1420 rec
->setMaxOccurs(max
);
1421 complexfields
.push_back(rec
);
1423 if ((rec
->getMinOccurs() == 0 && rec
->getMaxOccurs() > 1) || rec
->getMinOccurs() > 0) {
1424 rec
->name
.list_extension
= true;
1429 if ((getMinOccurs() == 0 && getMaxOccurs() > 1) || getMinOccurs() > 0) {
1430 if (generate_list_postfix
) {
1431 name
.list_extension
= true;
1434 if (parent
!= NULL
&& parent
->getXsdtype() == n_choice
) {
1435 name
.list_extension
= true;
1436 if ((parent
!= NULL
&& parent
->getXsdtype() == n_choice
)) {
1437 if (parent
->first_child
== false && getMinOccurs() == 0) {
1438 parent
->first_child
= true;
1440 first_child
= false;
1450 if (getMaxOccurs() > 1 && generate_list_postfix
) {
1451 name
.list_extension
= true;
1455 void ComplexType::applyNamespaceAttribute(VariantMode varLabel
, const Mstring
& ns_list
) {
1456 List
<Mstring
> namespaces
;
1457 if (!ns_list
.empty()) {
1458 expstring_t valueToSplitIntoTokens
= mcopystr(ns_list
.c_str());
1460 token
= strtok(valueToSplitIntoTokens
, " ");
1461 while (token
!= NULL
) {
1462 namespaces
.push_back(Mstring(token
));
1463 token
= strtok(NULL
, " ");
1465 Free(valueToSplitIntoTokens
);
1470 // Note: libxml2 will verify the namespace list according to the schema
1471 // of XML Schema. It is either ##any, ##other, ##local, ##targetNamespace,
1472 // or a list of (namespace reference | ##local | ##targetNamespace).
1473 for (List
<Mstring
>::iterator ns
= namespaces
.begin(); ns
; ns
= ns
->Next
) {
1474 static const Mstring
xxany("##any"), xxother("##other"), xxlocal("##local"),
1475 xxtargetNamespace("##targetNamespace");
1476 if (!first
) any_ns
+= ',';
1478 if (ns
->Data
== xxany
) {
1479 }// this must be the only element, nothing to add
1480 else if (ns
->Data
== xxother
) { // this must be the only element
1481 any_ns
+= " except unqualified";
1482 if (module
->getTargetNamespace() != "NoTargetNamespace") {
1484 any_ns
+= parent
->getModule()->getTargetNamespace();
1487 }// The three cases below can happen multiple times
1489 if (first
) any_ns
+= " from ";
1490 // else a comma was already added
1491 if (ns
->Data
== xxtargetNamespace
) {
1493 any_ns
+= parent
->getModule()->getTargetNamespace();
1495 } else if (ns
->Data
== xxlocal
) {
1496 any_ns
+= "unqualified";
1507 addVariant(varLabel
, any_ns
, true);
1510 void ComplexType::addComment(const Mstring
& text
) {
1511 if (this == actfield
) {
1512 if (lastType
== n_attribute
) { // ez nem teljesen jo, stb, tobb lehetoseg, es rossy sorrend
1513 if (!attribfields
.empty()) {
1514 attribfields
.back()->addComment(text
);
1517 if (actfield
->getName().convertedValue
== Mstring("base") && parent
!= NULL
) {
1518 parent
->getComment().push_back(Mstring("/* " + text
+ " */\n"));
1520 comment
.push_back(Mstring("/* " + text
+ " */\n"));
1524 actfield
->addComment(text
);
1529 //Attribute extension logic when extending complextypes
1530 void ComplexType::applyAttributeExtension(ComplexType
* found_CT
, AttributeType
* anyAttrib
/* = NULL */) {
1531 for (List
<AttributeType
*>::iterator attr
= found_CT
->attribfields
.begin(); attr
; attr
= attr
->Next
) {
1533 if (anyAttrib
!= NULL
&& attr
->Data
->isAnyAttribute()) {
1534 anyAttrib
->addNameSpaceAttribute(attr
->Data
->getNameSpaceAttribute());
1537 for (List
<AttributeType
*>::iterator attr2
= attribfields
.begin(); attr2
; attr2
= attr2
->Next
) {
1538 if (attr
->Data
->getName().convertedValue
== attr2
->Data
->getName().convertedValue
&&
1539 attr
->Data
->getType().convertedValue
== attr2
->Data
->getType().convertedValue
) {
1540 if (attr
->Data
->getUseVal() == optional
) {
1541 attr2
->Data
->setUseVal(optional
);
1549 AttributeType
* newAttrib
= new AttributeType(*attr
->Data
);
1550 attribfields
.push_back(newAttrib
);
1551 setParent(this, newAttrib
);
1556 //Attribute restriction logic when restricting complextypes
1557 void ComplexType::applyAttributeRestriction(ComplexType
* found_CT
) {
1558 for (List
<AttributeType
*>::iterator attr
= attribfields
.begin(), nextAttr
; attr
; attr
= nextAttr
) {
1559 nextAttr
= attr
->Next
;
1561 for (List
<AttributeType
*>::iterator attr2
= found_CT
->attribfields
.begin(); attr2
; attr2
= attr2
->Next
) {
1562 if (attr
->Data
->getName().convertedValue
== attr2
->Data
->getName().convertedValue
&&
1563 attr
->Data
->getType().convertedValue
== attr2
->Data
->getType().convertedValue
) {
1571 attribfields
.remove(attr
);
1574 size_t size
= found_CT
->attribfields
.size();
1575 size_t size2
= attribfields
.size();
1577 List
<AttributeType
*>::iterator attr
= found_CT
->attribfields
.begin();
1578 for (; i
< size
; attr
= attr
->Next
, i
= i
+ 1) {
1581 List
<AttributeType
*>::iterator attr2
= attribfields
.begin();
1582 for (; j
< size2
; attr2
= attr2
->Next
, j
= j
+ 1) {
1583 if (attr
->Data
->getName().convertedValue
== attr2
->Data
->getName().convertedValue
&&
1584 attr
->Data
->getType().convertedValue
== attr2
->Data
->getType().convertedValue
&& !attr2
->Data
->getUsed()) {
1586 attr2
->Data
->setUsed(true);
1591 AttributeType
* newAttrib
= new AttributeType(*attr
->Data
);
1592 attribfields
.push_back(newAttrib
);
1593 setParent(this, newAttrib
);
1598 void ComplexType::addNameSpaceAsVariant(RootType
* root
, RootType
* other
) {
1599 if (other
->getModule()->getTargetNamespace() != root
->getModule()->getTargetNamespace() &&
1600 other
->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1601 root
->addVariant(V_namespaceAs
, other
->getModule()->getTargetNamespace());
1605 void ComplexType::resolveAttribute(AttributeType
* attr
) {
1606 if (attr
->getXsdtype() == n_attribute
&& !attr
->getReference().empty()) {
1607 SimpleType
* st
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(attr
, want_BOTH
);
1609 if (attr
->isFromRef()) {
1610 addNameSpaceAsVariant(attr
, st
);
1611 attr
->setTypeOfField(st
->getName().convertedValue
);
1612 attr
->setNameOfField(st
->getName().originalValueWoPrefix
);
1613 attr
->setOrigModule(st
->getModule());
1615 attr
->setTypeOfField(st
->getName().convertedValue
);
1616 if (st
->getType().convertedValue
== "record" || st
->getType().convertedValue
== "union") {
1617 st
->addToNameDepList(attr
);
1621 printError(module
->getSchemaname(), name
.convertedValue
,
1622 "Reference for a non-defined type: " + attr
->getReference().repr());
1623 TTCN3ModuleInventory::getInstance().incrNumErrors();
1628 void ComplexType::resolveAttributeGroup(SimpleType
* st
) {
1629 if (xsdtype
== n_attributeGroup
&& !outside_reference
.empty()) {
1630 ComplexType
* ct
= (ComplexType
*) st
;
1631 if(ct
->resolved
== No
){
1632 ct
->referenceResolving();
1634 outside_reference
.set_resolved(ct
);
1636 bool addNameSpaceas
= false;
1637 if (ct
->getModule()->getTargetNamespace() != module
->getTargetNamespace() &&
1638 ct
->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1639 addNameSpaceas
= true;
1642 if(parent
->nillable
&& parent
->parent
!= NULL
){
1643 par
= parent
->parent
;
1647 List
<AttributeType
*>::iterator anyAttrib
= par
->attribfields
.begin();
1648 for (; anyAttrib
; anyAttrib
= anyAttrib
->Next
) {
1649 if (anyAttrib
->Data
->isAnyAttribute()) {
1653 for (List
<AttributeType
*>::iterator attr
= ct
->attribfields
.begin(); attr
; attr
= attr
->Next
) {
1654 AttributeType
* attrib
= new AttributeType(*attr
->Data
);
1655 attr
->Data
->setOrigModule(ct
->getModule());
1656 if (addNameSpaceas
) {
1657 attrib
->addVariant(V_namespaceAs
, ct
->getModule()->getTargetNamespace());
1659 if (anyAttrib
!= NULL
&& attr
->Data
->isAnyAttribute()) {
1660 anyAttrib
->Data
->addNameSpaceAttribute(attr
->Data
->getNameSpaceAttribute());
1662 //Nillable attribute placement is hard...
1663 if (parent
->nillable
&& parent
->parent
!= NULL
) {
1664 parent
->parent
->attribfields
.push_back(attrib
);
1665 attrib
->parent
= parent
->parent
;
1666 setParent(parent
->parent
, attrib
);
1667 } else if (parent
->nillable
&& !parent
->complexfields
.empty()) {
1668 parent
->complexfields
.back()->attribfields
.push_back(attrib
);
1669 attrib
->parent
= parent
->complexfields
.back();
1670 } else if (parent
->parent
!= NULL
&& (parent
->parent
->mode
== extensionMode
|| parent
->parent
->mode
== restrictionMode
)) {
1671 parent
->parent
->attribfields
.push_back(attrib
);
1672 setParent(parent
->parent
, attrib
);
1674 parent
->attribfields
.push_back(attrib
);
1675 setParent(parent
, attrib
);
1682 void ComplexType::resolveGroup(SimpleType
*st
) {
1683 if (xsdtype
== n_group
&& !outside_reference
.empty()) {
1684 ComplexType
* ct
= (ComplexType
*) st
;
1685 outside_reference
.set_resolved(ct
);
1687 if(ct
->resolved
== No
){
1688 ct
->referenceResolving();
1690 //Decide if namespaceas variant needs to be added
1691 bool addNameSpaceas
= false;
1692 if (ct
->getModule()->getTargetNamespace() != module
->getTargetNamespace() &&
1693 ct
->getModule()->getTargetNamespace() != "NoTargetNamespace") {
1694 addNameSpaceas
= true;
1696 if (ct
->getXsdtype() == n_sequence
&& getMinOccurs() == 1 && getMaxOccurs() == 1 && (parent
->getXsdtype() == n_complexType
|| parent
->getXsdtype() == n_sequence
)) {
1697 for (List
<ComplexType
*>::iterator c
= ct
->complexfields
.begin(); c
; c
= c
->Next
) {
1698 ComplexType
* newField
= new ComplexType(*c
->Data
);
1699 parent
->complexfields
.push_back(newField
);
1700 setParent(parent
, newField
);
1701 parent
->complexfields
.back()->setModule(getModule());
1702 if (addNameSpaceas
) {
1703 parent
->complexfields
.back()->addVariant(V_namespaceAs
, ct
->getModule()->getTargetNamespace());
1706 } else if (ct
->getXsdtype() == n_all
) {
1707 //If the parent optional, then every field is optional
1708 for (List
<ComplexType
*>::iterator c
= ct
->complexfields
.begin(); c
; c
= c
->Next
) {
1709 ComplexType
* f
= new ComplexType(*c
->Data
);
1710 if (getMinOccurs() == 0 && !f
->enumerated
) {
1711 f
->isOptional
= true;
1713 ((ComplexType
*) parent
)->complexfields
.push_back(f
);
1714 setParent(parent
, f
);
1715 f
->setModule(getModule());
1716 if (addNameSpaceas
) {
1717 f
->addVariant(V_namespaceAs
, ct
->getModule()->getTargetNamespace());
1720 parent
->addVariant(V_useOrder
);
1722 if (name
.list_extension
) {
1723 addVariant(V_untagged
);
1725 type
.upload(ct
->getName().convertedValue
);
1726 name
.upload(ct
->getName().convertedValue
);
1727 ct
->addToNameDepList(this);
1730 if (addNameSpaceas
) {
1731 addVariant(V_namespaceAs
, ct
->getModule()->getTargetNamespace());
1737 void ComplexType::resolveElement(SimpleType
*st
) {
1738 if (xsdtype
== n_element
&& !outside_reference
.empty()) {
1739 outside_reference
.set_resolved(st
);
1740 type
.upload(st
->getModule()->getTargetNamespaceConnector() + Mstring(":") + st
->getName().convertedValue
);
1741 if (name
.originalValueWoPrefix
.empty()) {
1742 name
.upload(st
->getName().convertedValue
);
1745 addNameSpaceAsVariant(this, st
);
1748 collectElementTypes(st
, NULL
);
1750 //Namedep is added to the substitutions, if any
1751 if(st
->getSubstitution() != NULL
){
1752 st
->getSubstitution()->addToNameDepList(this);
1753 nameDep
= st
->getSubstitution();
1754 }if(st
->getTypeSubstitution() != NULL
){
1755 st
->getTypeSubstitution()->addToNameDepList(this);
1756 nameDep
= st
->getTypeSubstitution();
1758 st
->addToNameDepList(this);
1764 void ComplexType::resolveSimpleTypeExtension() {
1765 if (mode
== extensionMode
&& cmode
== CT_simpletype_mode
&& basefield
!= NULL
) {
1766 SimpleType
* st
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(basefield
, want_BOTH
);
1768 if (st
->getXsdtype() != n_NOTSET
&& ((ComplexType
*) st
)->basefield
!= NULL
) { // if the xsdtype != simpletype
1769 ComplexType
* ct
= (ComplexType
*) st
;
1770 if (ct
->resolved
== No
) {
1771 ct
->referenceResolving();
1773 basefield
->outside_reference
.set_resolved(ct
);
1774 ct
->basefield
->addToNameDepList(basefield
);
1775 basefield
->nameDep
= ct
->basefield
;
1776 basefield
->mode
= extensionMode
;
1777 basefield
->applyReference(*ct
->basefield
, true);
1778 addNameSpaceAsVariant(basefield
, ct
->basefield
);
1779 applyAttributeExtension(ct
);
1781 if (!st
->getReference().empty() && !st
->getReference().is_resolved()) {
1782 st
->referenceResolving();
1784 st
->addToNameDepList(basefield
);
1785 basefield
->nameDep
= st
;
1786 addNameSpaceAsVariant(basefield
, st
);
1787 const Mstring old_type
= basefield
->getType().originalValueWoPrefix
;
1788 basefield
->applyReference(*st
);
1789 // If st has enumeration then the type is restored to the original value
1790 // because enumerations cannot be extended here and this way we just
1792 if (st
->getEnumeration().modified
) {
1793 basefield
->setTypeValue(old_type
);
1794 basefield
->getEnumeration().modified
= false;
1797 } else if(!isBuiltInType(basefield
->getType().convertedValue
)){
1798 printError(module
->getSchemaname(), name
.convertedValue
,
1799 "Reference for a non-defined type: " + basefield
->getReference().repr());
1800 TTCN3ModuleInventory::getInstance().incrNumErrors();
1807 void ComplexType::resolveSimpleTypeRestriction() {
1808 if (mode
== restrictionMode
&& cmode
== CT_simpletype_mode
&& basefield
!= NULL
&& !basefield
->outside_reference
.empty()) {
1809 SimpleType
* st
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(basefield
, want_BOTH
);
1811 printError(module
->getSchemaname(), name
.convertedValue
,
1812 "Reference for a non-defined type: " + basefield
->getReference().repr());
1813 TTCN3ModuleInventory::getInstance().incrNumErrors();
1816 basefield
->outside_reference
.set_resolved(st
);
1817 if (st
->getXsdtype() != n_NOTSET
) {
1818 ComplexType
* ct
= (ComplexType
*) st
;
1819 if (ct
->resolved
== No
) {
1820 ct
->referenceResolving();
1822 applyAttributeRestriction(ct
);
1823 basefield
->mode
= restrictionMode
;
1824 if (ct
->cmode
== CT_complextype_mode
) {
1825 applyReference(*ct
, true);
1826 type
.upload(ct
->getName().convertedValue
);
1827 basefield
->setInvisible();
1828 } else if (ct
->basefield
!= NULL
) {
1829 basefield
->applyReference(*ct
->basefield
);
1830 addNameSpaceAsVariant(basefield
, ct
->basefield
);
1831 } else if (ct
->basefield
== NULL
) {
1832 basefield
->applyReference(*ct
);
1833 addNameSpaceAsVariant(basefield
, ct
);
1836 if (!st
->getReference().empty() && !st
->getReference().is_resolved()) {
1837 st
->referenceResolving();
1839 if(xsdtype
== n_simpleContent
){
1840 basefield
->applyReference(*st
, true);
1841 addNameSpaceAsVariant(basefield
, st
);
1842 basefield
->mode
= restrictionMode
;
1843 }else if(xsdtype
== n_simpleType
){
1844 basefield
->setInvisible();
1845 applyReference(*basefield
, true);
1846 applyReference(*st
, true);
1847 addNameSpaceAsVariant(this, st
);
1848 basefield
->mode
= restrictionMode
;
1851 } else if (mode
== restrictionMode
&& cmode
== CT_simpletype_mode
&& basefield
!= NULL
) {
1852 ComplexType
* ct
= (ComplexType
*) TTCN3ModuleInventory::getInstance().lookup(basefield
, want_CT
);
1853 if (ct
== NULL
&& !isBuiltInType(basefield
->getType().convertedValue
)) {
1854 printError(module
->getSchemaname(), name
.convertedValue
,
1855 "Reference for a non-defined type: " + basefield
->getReference().repr());
1856 TTCN3ModuleInventory::getInstance().incrNumErrors();
1860 basefield
->outside_reference
.set_resolved(ct
);
1862 if (ct
->resolved
== No
) {
1863 ct
->referenceResolving();
1865 for (List
<AttributeType
*>::iterator f
= ct
->attribfields
.begin(); f
; f
= f
->Next
) {
1866 AttributeType
* attr
= new AttributeType(*f
->Data
);
1867 attribfields
.push_back(attr
);
1868 setParent(this, attr
);
1870 addNameSpaceAsVariant(this, ct
);
1872 if(!basefield
->parent
->top
){
1873 // This is the case of restriction -> list -> simpletype -> restriction
1874 // we have to apply the reference to the parent's parent.
1875 if(basefield
->parent
->parent
!= NULL
&& !basefield
->parent
->isVisible()) {
1876 basefield
->parent
->parent
->applyReference(*basefield
, true);
1878 applyReference(*basefield
, true);
1880 basefield
->setInvisible();
1885 void ComplexType::resolveComplexTypeExtension() {
1886 if (mode
== extensionMode
&& cmode
== CT_complextype_mode
&& !outside_reference
.empty()) {
1887 ComplexType
* ct
= (ComplexType
*) TTCN3ModuleInventory::getInstance().lookup(this, want_CT
);
1889 printError(module
->getSchemaname(), name
.convertedValue
,
1890 "Reference for a non-defined type: " + getReference().repr());
1891 TTCN3ModuleInventory::getInstance().incrNumErrors();
1894 if(ct
->getXsdtype() != n_NOTSET
){
1895 outside_reference
.set_resolved(ct
);
1896 if (ct
->resolved
== No
) {
1897 ct
->referenceResolving();
1899 List
<AttributeType
*>::iterator anyAttr
= attribfields
.begin();
1900 for (; anyAttr
; anyAttr
= anyAttr
->Next
) {
1901 if (anyAttr
->Data
->isAnyAttribute()) {
1906 if (anyAttr
!= NULL
) {
1907 applyAttributeExtension(ct
, anyAttr
->Data
);
1909 applyAttributeExtension(ct
);
1912 if (ct
->getName().convertedValue
== outside_reference
.get_val() && ct
->getModule()->getTargetNamespace() == outside_reference
.get_uri()) {
1914 outside_reference
.set_resolved(ct
);
1915 for (List
<ComplexType
*>::iterator f
= ct
->complexfields
.end(); f
; f
= f
->Prev
) {
1916 if (f
->Data
!= this) { //not a self recursive field
1917 ComplexType
* newField
= new ComplexType(*f
->Data
);
1918 complexfields
.push_front(newField
);
1919 setParent(this, newField
);
1921 //Self recursive field
1922 ComplexType
* field
= new ComplexType(this);
1923 field
->name
.upload(f
->Data
->getName().convertedValue
);
1924 field
->applyReference(*f
->Data
);
1925 field
->type
.upload(ct
->getName().convertedValue
+ Mstring(".") + f
->Data
->getName().convertedValue
);
1926 field
->type
.no_replace
= true;
1927 field
->setMinOccurs(f
->Data
->getMinOccurs());
1928 field
->setMaxOccurs(f
->Data
->getMaxOccurs());
1929 complexfields
.push_front(field
);
1930 setParent(this, field
);
1935 for (List
<ComplexType
*>::iterator f
= ct
->complexfields
.end(); f
; f
= f
->Prev
) {
1936 ComplexType
* newField
= new ComplexType(*f
->Data
);
1937 complexfields
.push_front(newField
);
1938 setParent(this, newField
);
1945 void ComplexType::resolveComplexTypeRestriction() {
1946 if (mode
== restrictionMode
&& cmode
== CT_complextype_mode
&& !outside_reference
.empty()) {
1947 ComplexType
* ct
= (ComplexType
*) TTCN3ModuleInventory::getInstance().lookup(this, want_CT
);
1948 if(ct
->getXsdtype() != n_NOTSET
){
1949 if (ct
->resolved
== No
) {
1950 ct
->referenceResolving();
1952 outside_reference
.set_resolved(ct
);
1953 applyAttributeRestriction(ct
);
1955 size_t size
= complexfields
.size();
1957 List
<ComplexType
*>::iterator field
= complexfields
.begin();
1958 for (; i
< size
; field
= field
->Next
, i
= i
+ 1){
1959 List
<ComplexType
*>::iterator field2
= ct
->complexfields
.begin();
1960 for (; field2
; field2
= field2
->Next
) {
1961 if (field
->Data
->getName().convertedValue
== field2
->Data
->getName().convertedValue
&&
1962 field
->Data
->getType().convertedValue
== field2
->Data
->getType().convertedValue
&&
1963 field
->Data
->complexfields
.size() <= field2
->Data
->complexfields
.size() &&
1964 hasMatchingFields(field
->Data
->complexfields
, field2
->Data
->complexfields
)) {
1965 // TODO: better algorithm to find matching fields
1966 field
->Data
->applyReference(*field2
->Data
, false);
1971 field
->Data
->setInvisible();
1978 bool ComplexType::hasMatchingFields(const List
<ComplexType
*>& mainList
, const List
<ComplexType
*>& subList
) const {
1979 List
<ComplexType
*>::iterator field
= mainList
.begin();
1980 for (; field
; field
= field
->Next
){
1981 List
<ComplexType
*>::iterator field2
= subList
.begin();
1983 for (; field2
; field2
= field2
->Next
) {
1984 if(field
->Data
->getName().convertedValue
== field2
->Data
->getName().convertedValue
&&
1985 field
->Data
->getType().convertedValue
== field2
->Data
->getType().convertedValue
) {
1997 void ComplexType::resolveUnion(SimpleType
*st
) {
1998 if (parent
!= NULL
&& parent
->with_union
&& xsdtype
== n_simpleType
&& !outside_reference
.empty()) {
1999 if (st
->getXsdtype() != n_NOTSET
) {
2000 ComplexType
* ct
= (ComplexType
*) st
;
2001 outside_reference
.set_resolved(ct
);
2002 for (List
<ComplexType
*>::iterator field
= ct
->complexfields
.begin(); field
; field
= field
->Next
) {
2003 ComplexType
* newField
= new ComplexType(*field
->Data
);
2004 parent
->complexfields
.push_back(newField
);
2005 setParent(parent
, newField
);
2012 void ComplexType::modifyAttributeParent() {
2013 if (nillable_field
!= NULL
) {
2014 ((ComplexType
*) nillable_field
)->actfield
= nillable_field
;
2020 //Element substitution
2021 void ComplexType::addSubstitution(SimpleType
* st
){
2022 ComplexType
* element
;
2023 if(st
->getXsdtype() == n_NOTSET
|| !complexfields
.empty()){
2024 element
= new ComplexType(*st
, fromTagSubstitution
);
2026 element
= new ComplexType(*(ComplexType
*)st
);
2027 element
->variant
.clear();
2029 element
->subsGroup
= this;
2030 element
->parent
= this;
2031 if(complexfields
.empty()){ //The first element(head) is the st
2032 element
->setTypeValue(st
->getType().convertedValue
);
2033 if(st
->hasVariant(Mstring("\"abstract\""))){
2034 element
->addVariant(V_abstract
);
2036 if(st
->getReference().get_ref() != NULL
){
2037 ((SimpleType
*)st
->getReference().get_ref())->addToNameDepList(element
);
2038 nameDep
= ((SimpleType
*)st
->getReference().get_ref());
2040 module
->addElementType(element
->getType().convertedValue
, element
);
2041 element
->addVariant(V_formAs
, Mstring("qualified"));
2044 if(st
->getType().convertedValue
== "anyType"){
2045 newType
= complexfields
.front()->getType().convertedValue
;
2047 newType
= st
->getName().convertedValue
;
2048 st
->addToNameDepList(element
);
2049 element
->nameDep
= st
;
2051 element
->setTypeValue(newType
);
2052 BlockValue front_block
= complexfields
.front()->getBlock();
2053 if(front_block
== all
|| front_block
== substitution
){
2054 element
->addVariant(V_block
);
2055 }else if(front_block
== restriction
|| front_block
== extension
){
2056 const Mstring
& head_type
= complexfields
.front()->getType().convertedValue
.getValueWithoutPrefix(':');
2057 //To decide if they came from a common ancestor
2058 Mstring elem_type
= findRoot(front_block
, st
, head_type
, true);
2059 if(head_type
== elem_type
){
2060 element
->addVariant(V_block
);
2065 element
->setNameValue(st
->getName().convertedValue
);
2066 element
->top
= false;
2067 complexfields
.push_back(element
);
2070 void ComplexType::addTypeSubstitution(SimpleType
* st
){
2071 ComplexType
* element
;
2072 if(st
->getXsdtype() == n_NOTSET
|| !complexfields
.empty()){
2073 element
= new ComplexType(*st
, fromTypeSubstitution
);
2075 //Only need a plain complextype
2077 element
= new ComplexType(this);
2078 //Just the block needed from st
2079 element
->block
= st
->getBlock();
2081 st
->addToNameDepList(element
);
2082 element
->nameDep
= st
;
2083 element
->typeSubsGroup
= this;
2084 element
->parent
= this;
2085 if(complexfields
.empty()){ //The first element(head) is the st
2086 if(st
->hasVariant(Mstring("\"abstract\""))){
2087 element
->addVariant(V_abstract
);
2090 BlockValue front_block
= complexfields
.front()->getBlock();
2091 if(front_block
== all
){
2092 element
->addVariant(V_block
);
2093 }else if(front_block
== restriction
|| front_block
== extension
){
2094 const Mstring
& head_type
= complexfields
.front()->getType().convertedValue
.getValueWithoutPrefix(':');
2095 //To decide if they came from a common ancestor
2096 Mstring elem_type
= findRoot(front_block
, st
, head_type
, true);
2097 if(head_type
== elem_type
){
2098 element
->addVariant(V_block
);
2102 //Cascading to parent type substitution
2103 if(parentTypeSubsGroup
!= NULL
&& !complexfields
.empty()){
2104 parentTypeSubsGroup
->addTypeSubstitution(st
);
2106 element
->top
= false;
2107 complexfields
.push_back(element
);
2108 element
->setTypeValue(st
->getName().convertedValue
.getValueWithoutPrefix(':'));
2109 element
->setNameValue(st
->getName().convertedValue
.getValueWithoutPrefix(':'));
2112 Mstring
ComplexType::findRoot(const BlockValue block_value
, SimpleType
* elem
, const Mstring
& head_type
, const bool first
){
2113 const Mstring elemName
= elem
->getName().convertedValue
.getValueWithoutPrefix(':');
2114 const Mstring elemType
= elem
->getType().convertedValue
.getValueWithoutPrefix(':');
2116 if(!first
&& !isFromRef() && elemType
== head_type
){
2118 }else if((isFromRef() &&
2119 ((elem
->getMode() == restrictionMode
&& block_value
== restriction
) ||
2120 (elem
->getMode() == extensionMode
&& block_value
== extension
))) && elemType
== head_type
){
2122 }else if(!first
&& elemName
== head_type
){
2125 SimpleType
* st
= NULL
;
2126 if((elem
->getMode() == restrictionMode
&& block_value
== restriction
) ||
2127 (elem
->getMode() == extensionMode
&& block_value
== extension
)){
2128 if(!elem
->getReference().is_resolved()){
2129 elem
->referenceResolving();
2131 if(elem
->getXsdtype() != n_NOTSET
){
2132 ComplexType
* ct
= (ComplexType
*)elem
;
2133 if(ct
->basefield
!= NULL
&& ct
->basefield
->getType().convertedValue
.getValueWithoutPrefix(':') == head_type
){
2135 }else if(ct
->basefield
!= NULL
){
2136 st
= (SimpleType
*)TTCN3ModuleInventory::getInstance().lookup(ct
->basefield
, want_BOTH
);
2140 st
= (SimpleType
*)(elem
->getReference().get_ref());
2142 }else if(elem
->getMode() == noMode
&& (block_value
== restriction
|| block_value
== extension
)){
2143 st
= (SimpleType
*)TTCN3ModuleInventory::getInstance().lookup(this, elem
->getType().convertedValue
, want_BOTH
);
2145 if(st
!= NULL
&& elem
!= st
){
2146 return findRoot(block_value
, st
, head_type
, false);
2149 if(elem
->getMode() == noMode
&& !first
){
2152 return empty_string
;