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