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