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