ComplexType.cc 85.4 KB
Newer Older
Elemer Lelik's avatar
Elemer Lelik committed
1
/******************************************************************************
balaskoa's avatar
balaskoa committed
2
 * Copyright (c) 2000-2018 Ericsson Telecom AB
Elemer Lelik's avatar
Elemer Lelik committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Balasko, Jeno
 *   Beres, Szabolcs
 *   Godar, Marton
 *   Ormandi, Matyas
 *   Raduly, Csaba
 *   Szabo, Bence Janos
 *
 ******************************************************************************/
Elemer Lelik's avatar
Elemer Lelik committed
17
18
19
20
21
22
#include "ComplexType.hh"

#include "GeneralFunctions.hh"
#include "XMLParser.hh"
#include "TTCN3Module.hh"
#include "TTCN3ModuleInventory.hh"
Elemer Lelik's avatar
Elemer Lelik committed
23
#include "Annotation.hh"
24
#include "Constant.hh"
Elemer Lelik's avatar
Elemer Lelik committed
25
26
27
28

#include <assert.h>

ComplexType::ComplexType(XMLParser * a_parser, TTCN3Module * a_module, ConstructType a_construct)
Elemer Lelik's avatar
Elemer Lelik committed
29
30
31
32
33
: SimpleType(a_parser, a_module, a_construct)
, top(true)
, nillable(false)
, enumerated(false)
, embed(false)
Elemer Lelik's avatar
Elemer Lelik committed
34
, with_union(false)
Elemer Lelik's avatar
Elemer Lelik committed
35
36
, first_child(false)
, fromAll(false)
37
38
39
, listPrint(false)
, listMinOccurs(1)
, listMaxOccurs(1)
Elemer Lelik's avatar
Elemer Lelik committed
40
41
42
43
44
45
46
47
, max_alt(0)
, skipback(0)
, lastType()
, actualPath(empty_string)
, actfield(this)
, nillable_field(NULL)
, basefield(NULL)
, cmode(CT_undefined_mode)
Elemer Lelik's avatar
Elemer Lelik committed
48
, resolved(No)
Elemer Lelik's avatar
Elemer Lelik committed
49
, parentTypeSubsGroup(NULL)
Elemer Lelik's avatar
Elemer Lelik committed
50
51
52
53
54
, complexfields()
, attribfields()
, enumfields()
, tagNames() {
  xsdtype = n_complexType;
Elemer Lelik's avatar
Elemer Lelik committed
55
56
}

Elemer Lelik's avatar
Elemer Lelik committed
57
58
59
60
61
62
ComplexType::ComplexType(ComplexType & other)
: SimpleType(other)
, top(other.top)
, nillable(other.nillable)
, enumerated(other.enumerated)
, embed(other.embed)
Elemer Lelik's avatar
Elemer Lelik committed
63
, with_union(other.with_union)
Elemer Lelik's avatar
Elemer Lelik committed
64
65
, first_child(other.first_child)
, fromAll(other.fromAll)
66
67
68
, listPrint(other.listPrint)
, listMinOccurs(other.listMinOccurs)
, listMaxOccurs(other.listMaxOccurs)
Elemer Lelik's avatar
Elemer Lelik committed
69
70
71
72
73
74
75
76
, max_alt(other.max_alt)
, skipback(other.skipback)
, lastType(other.lastType)
, actualPath(other.actualPath)
, actfield(this)
, nillable_field(NULL)
, basefield(NULL)
, cmode(other.cmode)
Elemer Lelik's avatar
Elemer Lelik committed
77
78
, resolved(other.resolved)
, parentTypeSubsGroup(other.parentTypeSubsGroup) {
Elemer Lelik's avatar
Elemer Lelik committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  type.originalValueWoPrefix = other.type.originalValueWoPrefix;
  for (List<AttributeType*>::iterator attr = other.attribfields.begin(); attr; attr = attr->Next) {
    attribfields.push_back(new AttributeType(*attr->Data));
    attribfields.back()->parent = this;
  }

  for (List<ComplexType*>::iterator field = other.complexfields.begin(); field; field = field->Next) {
    complexfields.push_back(new ComplexType(*field->Data));
    complexfields.back()->parent = this;
    if(field->Data == other.basefield){
      basefield = complexfields.back();
    }else if(field->Data == other.nillable_field){
      nillable_field = complexfields.back();
    }
Elemer Lelik's avatar
Elemer Lelik committed
93
  }
Elemer Lelik's avatar
Elemer Lelik committed
94
95
96
97
98
99
100
101
102

  if (other.nameDep != NULL) {
    SimpleType* dep = other.nameDep;
    if(dep->getSubstitution() != NULL){
      dep->getSubstitution()->addToNameDepList(this);
      nameDep = dep->getSubstitution();
    }else {
      other.nameDep->addToNameDepList(this);
    }
Elemer Lelik's avatar
Elemer Lelik committed
103
104
105
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
106
107
108
109
110
111
ComplexType::ComplexType(ComplexType * other)
: SimpleType(other->getParser(), other->getModule(), c_unknown)
, top(false)
, nillable(false)
, enumerated(false)
, embed(false)
Elemer Lelik's avatar
Elemer Lelik committed
112
, with_union(false)
Elemer Lelik's avatar
Elemer Lelik committed
113
114
, first_child(false)
, fromAll(false)
115
116
117
, listPrint(false)
, listMinOccurs(1)
, listMaxOccurs(1)
Elemer Lelik's avatar
Elemer Lelik committed
118
119
120
121
122
123
124
125
, max_alt(0)
, skipback(0)
, lastType()
, actualPath(empty_string)
, actfield(this)
, nillable_field(NULL)
, basefield(NULL)
, cmode(CT_undefined_mode)
Elemer Lelik's avatar
Elemer Lelik committed
126
, resolved(No)
Elemer Lelik's avatar
Elemer Lelik committed
127
, parentTypeSubsGroup(NULL)
Elemer Lelik's avatar
Elemer Lelik committed
128
129
130
131
132
133
134
135
, complexfields()
, attribfields()
, enumfields()
, tagNames() {
  xsdtype = n_complexType;
  parent = other;
  outside_reference = ReferenceData();
}
Elemer Lelik's avatar
Elemer Lelik committed
136

Elemer Lelik's avatar
Elemer Lelik committed
137
138
139
140
141
142
143
144
145
ComplexType::ComplexType(const SimpleType & other, CT_fromST c)
: SimpleType(other)
, top(true)
, nillable(false)
, enumerated(false)
, embed(false)
, with_union(false)
, first_child(false)
, fromAll(false)
146
147
148
, listPrint(false)
, listMinOccurs(1)
, listMaxOccurs(1)
Elemer Lelik's avatar
Elemer Lelik committed
149
150
151
152
153
154
155
156
157
, max_alt(0)
, skipback(0)
, lastType()
, actualPath(empty_string)
, actfield(this)
, nillable_field(NULL)
, basefield(NULL)
, cmode(CT_simpletype_mode)
, resolved(No)
Elemer Lelik's avatar
Elemer Lelik committed
158
, parentTypeSubsGroup(NULL)
Elemer Lelik's avatar
Elemer Lelik committed
159
160
161
162
163
, complexfields()
, attribfields()
, enumfields()
, tagNames() {

164
  if(c != fromElementSubstitution && c != fromTypeSubstitution){
Elemer Lelik's avatar
Elemer Lelik committed
165
166
    module->replaceLastMainType(this);
    module->setActualXsdConstruct(c_complexType);
Elemer Lelik's avatar
Elemer Lelik committed
167
  }
Elemer Lelik's avatar
Elemer Lelik committed
168
  construct = c_complexType;
169
  
Elemer Lelik's avatar
Elemer Lelik committed
170
171
  switch (c) {
    case fromTagUnion:
172
      type.upload(Mstring("union"), false);
Elemer Lelik's avatar
Elemer Lelik committed
173
174
175
176
177
      with_union = true;
      xsdtype = n_union;
      break;
    case fromTagNillable:
      addVariant(V_useNil);
178
      type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
179
180
      break;
    case fromTagComplexType:
181
      type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
182
183
      xsdtype = n_complexType;
      break;
184
    case fromElementSubstitution:
185
      type.upload(Mstring("union"), false);
Elemer Lelik's avatar
Elemer Lelik committed
186
187
188
189
      name.upload(getName().originalValueWoPrefix + Mstring("_group"));
      xsdtype = n_union;
      subsGroup = this;
      variant.clear();
Elemer Lelik's avatar
Elemer Lelik committed
190
      hidden_variant.clear();
Elemer Lelik's avatar
Elemer Lelik committed
191
192
193
194
195
      enumeration.modified = false;
      value.modified = false;
      pattern.modified = false;
      length.modified = false;
      whitespace.modified = false;
196
      new_construct = c_complexType;
Elemer Lelik's avatar
Elemer Lelik committed
197
      break;
Elemer Lelik's avatar
Elemer Lelik committed
198
    case fromTypeSubstitution:
199
      type.upload(Mstring("union"), false);
Elemer Lelik's avatar
Elemer Lelik committed
200
201
202
203
204
205
206
207
208
209
210
      name.upload(getName().originalValueWoPrefix + Mstring("_derivations"));
      xsdtype = n_union;
      substitutionGroup = empty_string;
      typeSubsGroup = this;
      variant.clear();
      hidden_variant.clear();
      enumeration.modified = false;
      value.modified = false;
      pattern.modified = false;
      length.modified = false;
      whitespace.modified = false;
211
      new_construct = c_complexType;
Elemer Lelik's avatar
Elemer Lelik committed
212
213
214
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
215
216
217
218
219
220
ComplexType::~ComplexType() {
  for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
    delete field->Data;
    field->Data = NULL;
  }
  complexfields.clear();
Elemer Lelik's avatar
Elemer Lelik committed
221

Elemer Lelik's avatar
Elemer Lelik committed
222
223
224
225
226
  for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
    delete field->Data;
    field->Data = NULL;
  }
  attribfields.clear();
Elemer Lelik's avatar
Elemer Lelik committed
227
228
}

Elemer Lelik's avatar
Elemer Lelik committed
229
230
231
232
233
234
235
void ComplexType::loadWithValues() {
  //Find the last field where the tag is found
  if (this != actfield) {
    actfield->loadWithValues();
    return;
  }
  
Elemer Lelik's avatar
Elemer Lelik committed
236
  const XMLParser::TagAttributes & atts = parser->getActualTagAttributes();
Elemer Lelik's avatar
Elemer Lelik committed
237
238
239
240
241
242
  
  switch (parser->getActualTagName()) {
    case n_sequence:
      if (!top && xsdtype != n_sequence && xsdtype != n_complexType && xsdtype != n_extension && xsdtype != n_restriction && xsdtype != n_element) {
        //Create new record
        ComplexType * rec = new ComplexType(this);
243
        rec->type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
244
245
246
247
248
249
250
251
252
253
254
        rec->name.upload(Mstring("sequence"));
        rec->addVariant(V_untagged);
        rec->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
        rec->setXsdtype(n_sequence);
        complexfields.push_back(rec);
        actfield = rec;
      } else {
        //Do not create new record, it is an embedded sequence
        if (xsdtype == n_sequence && atts.minOccurs == 1 && atts.maxOccurs == 1) {
          skipback += 1;
        }
255
        type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
256
257
258
        xsdtype = n_sequence;
        setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
      }
Elemer Lelik's avatar
Elemer Lelik committed
259
      break;
Elemer Lelik's avatar
Elemer Lelik committed
260
261
262
263
    case n_choice:
      if (!top || xsdtype != n_group) {
        //Create new union field
        ComplexType * choice = new ComplexType(this);
264
        choice->type.upload(Mstring("union"), false);
Elemer Lelik's avatar
Elemer Lelik committed
265
266
267
268
269
270
271
272
        choice->name.upload(Mstring("choice"));
        choice->setXsdtype(n_choice);
        choice->addVariant(V_untagged);
        choice->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
        actfield = choice;
        complexfields.push_back(choice);
      } else {
        xsdtype = n_choice;
273
        type.upload(Mstring("union"), false);
Elemer Lelik's avatar
Elemer Lelik committed
274
275
276
      }
      break;
    case n_all:
Elemer Lelik's avatar
Elemer Lelik committed
277
    {
Elemer Lelik's avatar
Elemer Lelik committed
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
      //Create the record of enumerated field
      xsdtype = n_all;
      ComplexType * enumField = new ComplexType(this);
      enumField->setTypeValue(Mstring("enumerated"));
      enumField->setNameValue(Mstring("order"));
      enumField->setBuiltInBase(Mstring("string"));
      enumField->enumerated = true;
      enumField->setMinMaxOccurs(0, ULLONG_MAX, false);
      setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
      addVariant(V_useOrder);
      complexfields.push_back(enumField);
      if (atts.minOccurs == 0) {
        isOptional = true;
      }
      break;
    }
    case n_restriction:
      mode = restrictionMode;
      //If it is an xsd:union then call SimpleType::loadWithValues
297
      if (parent != NULL && parent->with_union && parent->hasVariant(Mstring("useUnion"))) {
Elemer Lelik's avatar
Elemer Lelik committed
298
299
300
301
302
303
304
305
306
307
        SimpleType::loadWithValues();
        break;
      }
      if (cmode == CT_simpletype_mode) {
        //if it is from a SimpleType, then create a base field
        ComplexType * f = new ComplexType(this);
        f->name.upload(Mstring("base"));
        f->type.upload(atts.base);
        f->setReference(atts.base);
        f->addVariant(V_untagged);
308
        f->mode = restrictionMode;
Elemer Lelik's avatar
Elemer Lelik committed
309
310
311
        complexfields.push_back(f);
        basefield = f;
        actfield = f;
312
313
314
315
316
317
        
        // If it is a restriction of a list, then no new basefield will be 
        // present, to we apply the references to the parent.
        if(parent != NULL && parent->inList) {
          parent->applyReference(*f, true);
        }
Elemer Lelik's avatar
Elemer Lelik committed
318
319
320
321
322
323
324
325
326
327
328
329
330
331
      } else if (cmode == CT_complextype_mode) {
        setReference(atts.base);
        xsdtype = n_restriction;
      }
      break;
    case n_extension:
      mode = extensionMode;
      if (cmode == CT_simpletype_mode) {
        //if it is from a SimpleType, then create a base field
        ComplexType * f = new ComplexType(this);
        f->name.upload(Mstring("base"));
        f->type.upload(atts.base);
        f->setReference(atts.base);
        f->addVariant(V_untagged);
332
        f->mode = extensionMode;
Elemer Lelik's avatar
Elemer Lelik committed
333
334
335
336
337
338
339
340
341
        complexfields.push_back(f);
        basefield = f;
        actfield = f;
      } else if (cmode == CT_complextype_mode) {
        setReference(atts.base);
        xsdtype = n_extension;
      }
      break;
    case n_element:
Elemer Lelik's avatar
Elemer Lelik committed
342
    {
Elemer Lelik's avatar
Elemer Lelik committed
343
344
345
346
      if (atts.nillable) {
        if(cmode == CT_simpletype_mode){
          //If a simple top level element is nillable
          ComplexType * nilrec = new ComplexType(this);
347
          nilrec->xsdtype = n_element;
Elemer Lelik's avatar
Elemer Lelik committed
348
          if (atts.type.empty()) {
349
            nilrec->type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
350
351
          } else {
            nilrec->type.upload(atts.type);
352
            nilrec->setReference(atts.type);
Elemer Lelik's avatar
Elemer Lelik committed
353
354
355
356
357
358
          }
          nilrec->name.upload(Mstring("content"));
          nilrec->isOptional = true;
          nilrec->nillable = true;
          setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
          complexfields.push_back(nilrec);
359
          type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
360
361
362
363
364
365
366
          name.upload(atts.name);
          actfield = nilrec;
          nillable_field = nilrec;
        } else {
          //From a complexType element is nillable
          ComplexType * record = new ComplexType(this);
          ComplexType * nilrec = new ComplexType(record);
367
          nilrec->xsdtype = n_element;
Elemer Lelik's avatar
Elemer Lelik committed
368
          if (atts.type.empty()) {
369
            nilrec->type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
370
371
          } else {
            nilrec->type.upload(atts.type);
372
            nilrec->setReference(atts.type);
Elemer Lelik's avatar
Elemer Lelik committed
373
374
          }
          record->name.upload(atts.name);
375
          record->type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
376
377
378
379
380
381
382
383
384
385
386
          record->complexfields.push_back(nilrec);
          record->addVariant(V_useNil);
          record->nillable_field = nilrec;
          record->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);

          nilrec->name.upload(Mstring("content"));
          nilrec->nillable = true;
          nilrec->isOptional = true;
          nilrec->tagNames.push_back(parser->getActualTagName());
          complexfields.push_back(record);
          actfield = nilrec;
Elemer Lelik's avatar
Elemer Lelik committed
387
        }
Elemer Lelik's avatar
Elemer Lelik committed
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
      }else {
        //It is a simple element
        ComplexType* c = new ComplexType(this);
        c->setXsdtype(n_element);
        c->type.upload(atts.type);
        c->name.upload(atts.name);
        c->setReference(atts.type);
        c->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
        c->applyDefaultAttribute(atts.default_);
        c->applyFixedAttribute(atts.fixed);
        c->setElementFormAs(atts.form);
        if (atts.ref.empty()) {
          c->setReference(atts.type);
        } else {
          c->applyRefAttribute(atts.ref);
          c->name.upload(atts.ref.getValueWithoutPrefix(':'));
          c->type.upload(atts.ref);
Elemer Lelik's avatar
Elemer Lelik committed
405
        }
Elemer Lelik's avatar
Elemer Lelik committed
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
        c->applySubstitionGroupAttribute(atts.substitionGroup);
        c->applyBlockAttribute(atts.block);
        actfield = c;

        //Inside all have some special conditions
        if (xsdtype == n_all) {
          if (atts.minOccurs > 1) {
            printError(getModule()->getSchemaname(), name.convertedValue,
              Mstring("Inside <all>, minOccurs must be 0 or 1"));
            TTCN3ModuleInventory::incrNumErrors();
          }
          if (atts.maxOccurs != 1) {
            printError(getModule()->getSchemaname(), name.convertedValue,
              Mstring("Inside <all>, maxOccurs must be 1"));
            TTCN3ModuleInventory::incrNumErrors();
          }
          c->fromAll = true;
          complexfields.push_back(c);
          if (isOptional) {
            c->isOptional = true;
          }
        } else {
          complexfields.push_back(c);
Elemer Lelik's avatar
Elemer Lelik committed
429
430
431
432
        }
      }
      break;
    }
Elemer Lelik's avatar
Elemer Lelik committed
433
    case n_attribute:
Elemer Lelik's avatar
Elemer Lelik committed
434
    {
Elemer Lelik's avatar
Elemer Lelik committed
435
436
437
438
439
440
441
442
443
444
445
446
447
      AttributeType * attribute = new AttributeType(this);
      attribute->addVariant(V_attribute);
      attribute->applyMinMaxOccursAttribute(0, 1);
      attribute->setXsdtype(n_attribute);
      attribute->setUseVal(atts.use);
      attribute->setAttributeFormAs(atts.form);
      lastType = n_attribute;
      if (atts.ref.empty()) {
        attribute->setNameOfField(atts.name);
        attribute->setTypeOfField(atts.type);
        attribute->setReference(atts.type, true);
      } else {
        attribute->applyRefAttribute(atts.ref);
Elemer Lelik's avatar
Elemer Lelik committed
448
      }
449
450
      attribute->applyDefaultAttribute(atts.default_);
      attribute->applyFixedAttribute(atts.fixed);
Elemer Lelik's avatar
Elemer Lelik committed
451
452
453
454
455
456
457
458
459
460
461
462
463
      actfield = attribute;
      
      //In case of nillable parent it is difficult...
      if (nillable && parent != NULL) {
        parent->attribfields.push_back(attribute);
        attribute->parent = parent;
      } else if (nillable && !complexfields.empty() && parent == NULL) {
        complexfields.back()->attribfields.push_back(attribute);
      } else if (parent != NULL && (parent->mode == extensionMode || parent->mode == restrictionMode) && name.convertedValue == Mstring("base")) {
        parent->attribfields.push_back(attribute);
        attribute->parent = parent;
      } else {
        attribfields.push_back(attribute);
Elemer Lelik's avatar
Elemer Lelik committed
464
      }
Elemer Lelik's avatar
Elemer Lelik committed
465
      break;
Elemer Lelik's avatar
Elemer Lelik committed
466
    }
Elemer Lelik's avatar
Elemer Lelik committed
467
468
469
470
    case n_any:
    {
      ComplexType * any = new ComplexType(this);
      any->name.upload(Mstring("elem"));
471
      any->type.upload(Mstring("string"), false);
Elemer Lelik's avatar
Elemer Lelik committed
472
473
474
475
476
      any->applyNamespaceAttribute(V_anyElement, atts.namespace_);
      any->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
      any->setXsdtype(n_any);
      complexfields.push_back(any);
      break;
Elemer Lelik's avatar
Elemer Lelik committed
477
    }
Elemer Lelik's avatar
Elemer Lelik committed
478
    case n_anyAttribute:
Elemer Lelik's avatar
Elemer Lelik committed
479
    {
Elemer Lelik's avatar
Elemer Lelik committed
480
481
482
      AttributeType * anyattr = new AttributeType(this);
      anyattr->setXsdtype(n_anyAttribute);
      anyattr->setNameOfField(Mstring("attr"));
483
      anyattr->setTypeValue(Mstring("string"));
Elemer Lelik's avatar
Elemer Lelik committed
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
      anyattr->setToAnyAttribute();
      anyattr->applyMinMaxOccursAttribute(0, ULLONG_MAX);
      anyattr->addNameSpaceAttribute(atts.namespace_);
      actfield = anyattr;

      //In case of nillable parent it is difficult...
      if (nillable && parent != NULL) {
        parent->attribfields.push_back(anyattr);
        anyattr->parent = parent;
      } else if (nillable && !complexfields.empty() && parent == NULL) {
        complexfields.back()->attribfields.push_back(anyattr);
      } else if (parent != NULL && (parent->mode == extensionMode || parent->mode == restrictionMode) && name.convertedValue == Mstring("base")) {
        parent->attribfields.push_back(anyattr);
        anyattr->parent = parent;
      } else {
        attribfields.push_back(anyattr);
Elemer Lelik's avatar
Elemer Lelik committed
500
      }
Elemer Lelik's avatar
Elemer Lelik committed
501
      break;
Elemer Lelik's avatar
Elemer Lelik committed
502
    }
Elemer Lelik's avatar
Elemer Lelik committed
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    case n_attributeGroup:
      if (!atts.ref.empty()) {
        ComplexType * g = new ComplexType(this);
        g->setXsdtype(n_attributeGroup);
        g->setReference(atts.ref);
        complexfields.push_back(g);
        actfield = g;
      } else {
        xsdtype = n_attributeGroup;
        name.upload(Mstring(atts.name));
        setInvisible();
      }
      break;
    case n_group:
      if (atts.ref.empty()) {
        //It is a definition
        xsdtype = n_group;
        name.upload(atts.name);
      } else {
        //It is a reference
        ComplexType* group = new ComplexType(this);
        group->setXsdtype(n_group);
        group->name.upload(atts.name);
        group->setReference(Mstring(atts.ref));
        group->setMinMaxOccurs(atts.minOccurs, atts.maxOccurs);
        complexfields.push_back(group);
        actfield = group;
      }
      break;
    case n_union:
Elemer Lelik's avatar
Elemer Lelik committed
533
    {
Elemer Lelik's avatar
Elemer Lelik committed
534
535
      with_union = true;
      xsdtype = n_union;
536
      type.upload(Mstring("union"), false);
Elemer Lelik's avatar
Elemer Lelik committed
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
      addVariant(V_useUnion);
      if (!atts.memberTypes.empty()) {
        List<Mstring> types;
        //Get the union values
        expstring_t valueToSplitIntoTokens = mcopystr(atts.memberTypes.c_str());
        char * token;
        token = strtok(valueToSplitIntoTokens, " ");
        while (token != NULL) {
          types.push_back(Mstring(token));
          token = strtok(NULL, " ");
        }
        Free(valueToSplitIntoTokens);
        
        //Create the union elements and push into the container
        for (List<Mstring>::iterator memberType = types.begin(); memberType; memberType = memberType->Next) {
          Mstring tmp_name = memberType->Data.getValueWithoutPrefix(':');
          ComplexType * f = new ComplexType(this);
          f->name.upload(tmp_name);
          f->type.upload(memberType->Data);
          f->setXsdtype(n_simpleType);
          f->setReference(memberType->Data);
          complexfields.push_back(f);
        }
Elemer Lelik's avatar
Elemer Lelik committed
560
      }
Elemer Lelik's avatar
Elemer Lelik committed
561
      break;
Elemer Lelik's avatar
Elemer Lelik committed
562
    }
Elemer Lelik's avatar
Elemer Lelik committed
563
564
    case n_simpleType:
    case n_simpleContent:
Elemer Lelik's avatar
Elemer Lelik committed
565
    {
Elemer Lelik's avatar
Elemer Lelik committed
566
567
      xsdtype = parser->getActualTagName();
      cmode = CT_simpletype_mode;
568
      if (with_union && hasVariant(Mstring("useUnion"))) {
569
        Mstring fieldname;
Elemer Lelik's avatar
Elemer Lelik committed
570
571
572
        if (max_alt == 0) {
          fieldname = Mstring("alt_");
        } else {
573
574
575
          expstring_t new_name = mprintf("alt_%d", max_alt);
          fieldname = new_name;
          Free(new_name);
Elemer Lelik's avatar
Elemer Lelik committed
576
577
578
579
580
581
582
583
        }
        max_alt++;
        ComplexType * field = new ComplexType(this);
        field->name.upload(fieldname);
        field->setXsdtype(n_simpleType);
        field->addVariant(V_nameAs, empty_string, true);
        complexfields.push_back(field);
        actfield = field;
Elemer Lelik's avatar
Elemer Lelik committed
584
      }
Elemer Lelik's avatar
Elemer Lelik committed
585
      break;
Elemer Lelik's avatar
Elemer Lelik committed
586
    }
Elemer Lelik's avatar
Elemer Lelik committed
587
588
    case n_complexType:
      name.upload(atts.name);
589
      type.upload(Mstring("record"), false);
Elemer Lelik's avatar
Elemer Lelik committed
590
591
592
593
594
595
596
597
598
599
      applyAbstractAttribute(atts.abstract);
      applySubstitionGroupAttribute(atts.substitionGroup);
      applyBlockAttribute(atts.block);
      // fall through
    case n_complexContent:
      tagNames.push_back(parser->getActualTagName());
      cmode = CT_complextype_mode;
      if (atts.mixed) {
        ComplexType * mixed = new ComplexType(this);
        mixed->name.upload(Mstring("embed_values"));
600
        mixed->type.upload(Mstring("string"), false);
Elemer Lelik's avatar
Elemer Lelik committed
601
602
603
604
605
606
607
        mixed->setMinMaxOccurs(0, ULLONG_MAX, false);
        mixed->embed = true;
        complexfields.push_back(mixed);
        addVariant(V_embedValues);
      }
      break;
    case n_list:
ebensza's avatar
ebensza committed
608
      if (parent != NULL && parent->basefield == this) {
609
610
611
612
613
614
615
616
617
618
619
620
621
622
        if (parent->getMaxOccurs() == 1) { // optional or minOccurs = maxOccurs = 1
          if (parent->getMinOccurs() == 0) {
            parent->isOptional = true;
            if (parent->parent != NULL && parent->parent->getXsdtype() == n_choice) {
              parent->listPrint = true;
              parent->listMinOccurs = parent->getMinOccurs();
              parent->listMaxOccurs = parent->getMaxOccurs();
            }
          }
        } else if (parent->parent != NULL){
          parent->listPrint = true;
          parent->listMinOccurs = parent->getMinOccurs();
          parent->listMaxOccurs = parent->getMaxOccurs();
        }
ebensza's avatar
ebensza committed
623
        parent->basefield = NULL;
624
        parent->SimpleType::loadWithValues();
ebensza's avatar
ebensza committed
625
        setInvisible();
626
      } else if(parent != NULL) {
627
628
629
630
631
632
633
634
635
636
637
638
639
640
        if (getMaxOccurs() == 1) { // optional or minOccurs = maxOccurs = 1
          if (getMinOccurs() == 0) {
            isOptional = true;
            if (parent->getXsdtype() == n_choice) {
              listPrint = true;
              listMinOccurs = getMinOccurs();
              listMaxOccurs = getMaxOccurs();
            }
          }
        } else {
          listPrint = true;
          listMinOccurs = getMinOccurs();
          listMaxOccurs = getMaxOccurs();
        }
641
        SimpleType::loadWithValues();
ebensza's avatar
ebensza committed
642
      }
643
      break;
Elemer Lelik's avatar
Elemer Lelik committed
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
    case n_length:
    case n_minLength:
    case n_maxLength:
    case n_pattern:
    case n_enumeration:
    case n_whiteSpace:
    case n_minInclusive:
    case n_maxInclusive:
    case n_minExclusive:
    case n_maxExclusive:
    case n_totalDigits:
    case n_fractionDigits:
      SimpleType::loadWithValues();
      break;
    case n_label:
      addComment(Mstring("LABEL:"));
      break;
    case n_definition:
      addComment(Mstring("DEFINITION:"));
      break;
    default:
      break;
Elemer Lelik's avatar
Elemer Lelik committed
666
667
668
669
  }
}

// called from endelementHandler
Elemer Lelik's avatar
Elemer Lelik committed
670
671
672
673
674
675
676
void ComplexType::modifyValues() {
  if (this != actfield) {
    actfield->modifyValues();
    return;
  }
  if (xsdtype == n_sequence) {
    skipback = skipback - 1;
Elemer Lelik's avatar
Elemer Lelik committed
677
678
  }

ebensza's avatar
ebensza committed
679
680
  if ( parent != NULL && 
      (xsdtype == n_element || 
Elemer Lelik's avatar
Elemer Lelik committed
681
682
683
684
685
686
687
688
689
690
       xsdtype == n_complexType || 
       xsdtype == n_complexContent || 
       xsdtype == n_all || 
       xsdtype == n_attribute || 
       xsdtype == n_anyAttribute ||
       xsdtype == n_choice || 
       xsdtype == n_group || 
       xsdtype == n_attributeGroup || 
       xsdtype == n_extension || 
       xsdtype == n_restriction || 
691
       (xsdtype == n_simpleType && !inList) || 
Elemer Lelik's avatar
Elemer Lelik committed
692
693
       xsdtype == n_simpleContent ||
       (xsdtype == n_sequence && skipback < 0)
ebensza's avatar
ebensza committed
694
      )) {
Elemer Lelik's avatar
Elemer Lelik committed
695
696
697
698
699
700
701
702
    if (!tagNames.empty() && tagNames.back() == parser->getParentTagName()) {
      if (nillable && tagNames.back() == n_element) {
        parent->modifyValues();
      }
      tagNames.pop_back();
    } else if (tagNames.empty()) {
      parent->actfield = parent;
      parent->lastType = xsdtype;
Elemer Lelik's avatar
Elemer Lelik committed
703
704
    }
  }
705
706
707
  if (xsdtype == n_simpleType) {
    inList = false;
  }
Elemer Lelik's avatar
Elemer Lelik committed
708
709
}

710
711
712
713
714
715
716
717
718
719
720
void ComplexType::modifyList() {
  if (this != actfield) {
    ((SimpleType*)actfield)->modifyList();
    return;
  }
  if (!inList && mode == listMode && parent != NULL) {
    parent->actfield = parent;
    parent->lastType = xsdtype;
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
721
722
723
724
725
void ComplexType::referenceResolving() {
  if (resolved != No) return; // nothing to do
  if(this == subsGroup){
    resolved = Yes;
    return;
Elemer Lelik's avatar
Elemer Lelik committed
726
  }
Elemer Lelik's avatar
Elemer Lelik committed
727
728
  resolved = InProgress;
  for (List<ComplexType*>::iterator ct = complexfields.begin(); ct; ct = ct->Next) {
729
    // Reference resolving of ComplexTypes
Elemer Lelik's avatar
Elemer Lelik committed
730
    ct->Data->referenceResolving();
Elemer Lelik's avatar
Elemer Lelik committed
731
  }
Elemer Lelik's avatar
Elemer Lelik committed
732
733
734
  for (List<AttributeType*>::iterator attr = attribfields.begin(); attr; attr = attr->Next) {
    //Reference resolving for Attributes
    resolveAttribute(attr->Data);
Elemer Lelik's avatar
Elemer Lelik committed
735
  }
Elemer Lelik's avatar
Elemer Lelik committed
736
737
738
  
  reference_resolving_funtion();
  
Elemer Lelik's avatar
Elemer Lelik committed
739
  if(!substitutionGroup.empty()){
Elemer Lelik's avatar
Elemer Lelik committed
740
    addToSubstitutions();
Elemer Lelik's avatar
Elemer Lelik committed
741
  }
Elemer Lelik's avatar
Elemer Lelik committed
742
  resolved = Yes;
Elemer Lelik's avatar
Elemer Lelik committed
743
744
}

Elemer Lelik's avatar
Elemer Lelik committed
745
746
747
void ComplexType::reference_resolving_funtion() {
  //Every child element references are resolved here.
  if (outside_reference.empty() && basefield == NULL) {
Elemer Lelik's avatar
Elemer Lelik committed
748
749
750
751
752
    //Its not in the resolveElement function because we need the built in type
    //reference too, and then the outside_reference is empty.
    if(xsdtype == n_element){
      collectElementTypes(NULL, NULL);
    }
Elemer Lelik's avatar
Elemer Lelik committed
753
    return;
Elemer Lelik's avatar
Elemer Lelik committed
754
755
  }

756
  resolveAttributeGroup();
Elemer Lelik's avatar
Elemer Lelik committed
757

758
  resolveGroup();
Elemer Lelik's avatar
Elemer Lelik committed
759

760
  resolveElement();
Elemer Lelik's avatar
Elemer Lelik committed
761

Elemer Lelik's avatar
Elemer Lelik committed
762
  resolveSimpleTypeExtension();
Elemer Lelik's avatar
Elemer Lelik committed
763

Elemer Lelik's avatar
Elemer Lelik committed
764
  resolveSimpleTypeRestriction();
Elemer Lelik's avatar
Elemer Lelik committed
765

Elemer Lelik's avatar
Elemer Lelik committed
766
  resolveComplexTypeExtension();
Elemer Lelik's avatar
Elemer Lelik committed
767

Elemer Lelik's avatar
Elemer Lelik committed
768
  resolveComplexTypeRestriction();
Elemer Lelik's avatar
Elemer Lelik committed
769

770
  resolveUnion();
Elemer Lelik's avatar
Elemer Lelik committed
771

Elemer Lelik's avatar
Elemer Lelik committed
772
773
  addToTypeSubstitutions();

Elemer Lelik's avatar
Elemer Lelik committed
774
775
}

Elemer Lelik's avatar
Elemer Lelik committed
776
777
void ComplexType::setParent(ComplexType * par, SimpleType * child) {
  child->parent = par;
Elemer Lelik's avatar
Elemer Lelik committed
778
779
}

Elemer Lelik's avatar
Elemer Lelik committed
780
781
void ComplexType::applyReference(const SimpleType & other, const bool on_attributes) {
  type.convertedValue = other.getType().convertedValue;
Elemer Lelik's avatar
Elemer Lelik committed
782
  type.originalValueWoPrefix = other.getType().convertedValue.getValueWithoutPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
783

784
785
  if (other.getMinOccurs() > getMinOccurs() ||
      other.getMaxOccurs() < getMaxOccurs()) {
Elemer Lelik's avatar
Elemer Lelik committed
786
787
788
789
790
791
    if (!on_attributes) {
      expstring_t temp = memptystr();
      temp = mputprintf(
        temp,
        "The occurrence range (%llu .. %llu) of the element (%s) is not compatible "
        "with the occurrence range (%llu .. %llu) of the referenced element.",
792
793
        getMinOccurs(),
        getMaxOccurs(),
Elemer Lelik's avatar
Elemer Lelik committed
794
795
796
797
798
799
        name.originalValueWoPrefix.c_str(),
        other.getMinOccurs(),
        other.getMaxOccurs());
      printError(module->getSchemaname(), parent->getName().originalValueWoPrefix,
        Mstring(temp));
      Free(temp);
Elemer Lelik's avatar
Elemer Lelik committed
800
801
      TTCN3ModuleInventory::getInstance().incrNumErrors();
    }
Elemer Lelik's avatar
Elemer Lelik committed
802
  } else {
803
804
    setMinOccurs(llmax(getMinOccurs(), other.getMinOccurs()));
    setMaxOccurs(llmin(getMaxOccurs(), other.getMaxOccurs()));
Elemer Lelik's avatar
Elemer Lelik committed
805
806
  }

Elemer Lelik's avatar
Elemer Lelik committed
807
808
809
810
811
  for (List<Mstring>::iterator var = other.getVariantRef().begin(); var; var = var->Next) {
    bool found = false;
    for (List<Mstring>::iterator var1 = variant.begin(); var1; var1 = var1->Next) {
      if (var->Data == var1->Data) {
        found = true;
Elemer Lelik's avatar
Elemer Lelik committed
812
813
814
        break;
      }
    }
Elemer Lelik's avatar
Elemer Lelik committed
815
816
817
    if (!found) {
      variant.push_back(var->Data);
      variant_ref.push_back(var->Data);
Elemer Lelik's avatar
Elemer Lelik committed
818
819
820
    }
  }

Elemer Lelik's avatar
Elemer Lelik committed
821
  builtInBase = other.getBuiltInBase();
822
  
Elemer Lelik's avatar
Elemer Lelik committed
823
824
825
826
827
  length.applyReference(other.getLength());
  pattern.applyReference(other.getPattern());
  enumeration.applyReference(other.getEnumeration());
  whitespace.applyReference(other.getWhitespace());
  value.applyReference(other.getValue());
Elemer Lelik's avatar
Elemer Lelik committed
828
829
}

Elemer Lelik's avatar
Elemer Lelik committed
830
831
832
833
834
835
836
837
838
839
840
841
void ComplexType::nameConversion(NameConversionMode conversion_mode, const List<NamespaceType> & ns) {
  if(!visible) return;
  switch (conversion_mode) {
    case nameMode:
      nameConversion_names(ns);
      break;
    case typeMode:
      nameConversion_types(ns);
      break;
    case fieldMode:
      nameConversion_fields(ns);
      break;
Elemer Lelik's avatar
Elemer Lelik committed
842
843
844
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
845
void ComplexType::nameConversion_names(const List<NamespaceType> &) {
Elemer Lelik's avatar
Elemer Lelik committed
846
847
848
849
  Mstring res, var(module->getTargetNamespace());
  XSDName2TTCN3Name(name.convertedValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_name, res, var);
  name.convertedValue = res;
  bool found = false;
Elemer Lelik's avatar
Elemer Lelik committed
850
  for (List<Mstring>::iterator vari = variant.begin(); vari; vari = vari->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
851
852
853
854
855
    if (vari->Data == "\"untagged\"") {
      found = true;
      break;
    }
  }
856
857
  // element or type substitution generated types do not need 'name as' variant
  if (!found && subsGroup != this && typeSubsGroup != this) {
Elemer Lelik's avatar
Elemer Lelik committed
858
859
    addVariant(V_onlyValue, var);
  }
860
  for (List<RootType*>::iterator dep = nameDepList.begin(); dep; dep = dep->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
861
    dep->Data->setTypeValue(res);
Elemer Lelik's avatar
Elemer Lelik committed
862
863
864
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
865
866
867
868
869
870
871
872
873
874
875
876
void ComplexType::nameConversion_types(const List<NamespaceType> & ns) {
  attribfields.sort(compareAttributeNameSpaces);
  attribfields.sort(compareAttributeTypes);
  for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
    field->Data->nameConversion(typeMode, ns);
  }

  for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
    field->Data->nameConversion_types(ns);
  }

  Mstring prefix, uri, typeValue;
Elemer Lelik's avatar
Elemer Lelik committed
877
878
879
880

  if (type.convertedValue == "record" ||
    type.convertedValue == "set" ||
    type.convertedValue == "union" ||
Elemer Lelik's avatar
Elemer Lelik committed
881
    type.convertedValue == "enumerated") {
Elemer Lelik's avatar
Elemer Lelik committed
882
    return;
Elemer Lelik's avatar
Elemer Lelik committed
883
  }
Elemer Lelik's avatar
Elemer Lelik committed
884
885

  prefix = type.convertedValue.getPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
886
  typeValue = type.convertedValue.getValueWithoutPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
887

Elemer Lelik's avatar
Elemer Lelik committed
888
  for (List<NamespaceType>::iterator namesp = ns.begin(); namesp; namesp = namesp->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
889
890
891
892
893
894
    if (prefix == namesp->Data.prefix) {
      uri = namesp->Data.uri;
      break;
    }
  }

Elemer Lelik's avatar
Elemer Lelik committed
895
  QualifiedName in(uri, typeValue); // ns uri + original name
Elemer Lelik's avatar
Elemer Lelik committed
896
897
898

  // Check all known types
  QualifiedNames::iterator origTN = TTCN3ModuleInventory::getInstance().getTypenames().begin();
Elemer Lelik's avatar
Elemer Lelik committed
899
  for (; origTN; origTN = origTN->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
900
901
    if (origTN->Data == in) {
      QualifiedName tmp_name(module->getTargetNamespace(), name.convertedValue);
Elemer Lelik's avatar
Elemer Lelik committed
902
      if (origTN->Data != tmp_name){
Elemer Lelik's avatar
Elemer Lelik committed
903
        break;
Elemer Lelik's avatar
Elemer Lelik committed
904
      }
Elemer Lelik's avatar
Elemer Lelik committed
905
906
907
908
909
    }
  }

  if (origTN != NULL) {
    setTypeValue(origTN->Data.name);
Elemer Lelik's avatar
Elemer Lelik committed
910
  } else {
Elemer Lelik's avatar
Elemer Lelik committed
911
    Mstring res, var;
Elemer Lelik's avatar
Elemer Lelik committed
912
    XSDName2TTCN3Name(typeValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var, type.no_replace);
Elemer Lelik's avatar
Elemer Lelik committed
913
914
915
916
    setTypeValue(res);
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
void ComplexType::nameConversion_fields(const List<NamespaceType> & ns) {
  QualifiedNames used_field_names;
  
  for (List<AttributeType*>::iterator field = attribfields.begin(); field; field = field->Next) {
    field->Data->nameConversion_names(used_field_names);
  }

  for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
    if (field->Data->getMinOccurs() == 0 && field->Data->getMaxOccurs() == 0) {
      continue;
    }
    if (!field->Data->isVisible()) {
      continue;
    }
    
    field->Data->nameConversion_fields(ns);
Elemer Lelik's avatar
Elemer Lelik committed
933
934

    Mstring prefix = field->Data->getType().convertedValue.getPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
    Mstring typeValue = field->Data->getType().convertedValue.getValueWithoutPrefix(':');

    Mstring res, var;
    var = getModule()->getTargetNamespace();
    XSDName2TTCN3Name(typeValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var);

    field->Data->addVariant(V_onlyValue, var);
    var = getModule()->getTargetNamespace();

    if (field->Data->getName().list_extension) {
      field->Data->useNameListProperty();
      XSDName2TTCN3Name(field->Data->getName().convertedValue,
        used_field_names, field_name, res, var);
      field->Data->setNameValue(res);
      bool found_in_variant = false;
      for (List<Mstring>::iterator vari = field->Data->getVariant().begin(); vari; vari = vari->Next) {
        if (vari->Data == Mstring("\"untagged\"")) {
          found_in_variant = true;
          break;
        }
      }
      if (!field->Data->getName().originalValueWoPrefix.empty() &&
        field->Data->getName().originalValueWoPrefix != "sequence" &&
        field->Data->getName().originalValueWoPrefix != "choice" &&
        field->Data->getName().originalValueWoPrefix != "elem" &&
        !found_in_variant) {
        field->Data->addVariant(V_nameAs, field->Data->getName().originalValueWoPrefix);
Elemer Lelik's avatar
Elemer Lelik committed
962
963
      }

Elemer Lelik's avatar
Elemer Lelik committed
964
965
966
967
968
969
970
971
972

      if (!found_in_variant) {
        field->Data->addVariant(V_untagged, empty_string, true);
      }
    } else {
      XSDName2TTCN3Name(field->Data->getName().convertedValue,
        used_field_names, field_name, res, var);
      field->Data->setNameValue(res);
      field->Data->addVariant(V_onlyValue, var);
Elemer Lelik's avatar
Elemer Lelik committed
973
    }
Elemer Lelik's avatar
Elemer Lelik committed
974
975
976
977
978
979
980
981

  }
}

void ComplexType::setFieldPaths(Mstring path) {
  if (path.empty()) {
    if (!top) {
      Mstring field_prefix = empty_string;
982
      if(parent->getMinOccurs() == 0 && parent->getMaxOccurs() == ULLONG_MAX){
Elemer Lelik's avatar
Elemer Lelik committed
983
        field_prefix = "[-].";
Elemer Lelik's avatar
Elemer Lelik committed
984
      }
Elemer Lelik's avatar
Elemer Lelik committed
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
      path = field_prefix + getName().convertedValue;
      actualPath = field_prefix + getName().convertedValue;
    }else {
      actualPath = getName().convertedValue;
    }
  } else if (parent != NULL && (parent->getMinOccurs() != 1 || parent->getMaxOccurs() != 1) &&
             (parent->getName().list_extension || parent->mode == listMode)) {
    path = path + Mstring("[-].") + getName().convertedValue;
    actualPath = path;
  } else {
    path = path + Mstring(".") + getName().convertedValue;
    actualPath = path;
  }

  for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
    field->Data->setFieldPaths(path);
  }
  for (List<AttributeType*>::iterator attr = attribfields.begin(); attr; attr = attr->Next) {
    attr->Data->setFieldPath(path);
  }
}

1007
void ComplexType::subFinalModification() {  
Elemer Lelik's avatar
Elemer Lelik committed
1008
1009
  //Call SimpleType finalModification
  SimpleType::finalModification();
1010
  
Elemer Lelik's avatar
Elemer Lelik committed
1011
  //Set isOptional field
1012
  isOptional = isOptional || (getMinOccurs() == 0 && getMaxOccurs() == 1);
Elemer Lelik's avatar
Elemer Lelik committed
1013
1014
1015
1016
1017
1018
  
  //
  List<Mstring> enumNames;
  for (List<ComplexType*>::iterator field = complexfields.begin(), nextField; field; field = nextField) {
    nextField = field->Next;
    //Remove invisible fields
1019
    if ((field->Data->getMinOccurs() == 0 && field->Data->getMaxOccurs() == 0) || !field->Data->isVisible()) {
Elemer Lelik's avatar
Elemer Lelik committed
1020
1021
1022
1023
1024
      delete field->Data;
      field->Data = NULL;
      complexfields.remove(field);
    } else {
      //Recursive call
1025
      field->Data->subFinalModification();
Elemer Lelik's avatar
Elemer Lelik committed
1026
1027
1028
      //collect <xsd:all> elements
      if (field->Data->fromAll) {
        enumNames.push_back(field->Data->getName().convertedValue);
Elemer Lelik's avatar
Elemer Lelik committed
1029
1030
      }
    }
Elemer Lelik's avatar
Elemer Lelik committed
1031
  }
Elemer Lelik's avatar
Elemer Lelik committed
1032

Elemer Lelik's avatar
Elemer Lelik committed
1033
1034
  ComplexType * embedField = NULL;
  ComplexType * enumField = NULL;
Elemer Lelik's avatar
Elemer Lelik committed
1035

Elemer Lelik's avatar
Elemer Lelik committed
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
  //Find the embed and order fields, and remove them
  for (List<ComplexType*>::iterator field = complexfields.begin(), nextField; field; field = nextField) {
    nextField = field->Next;
    if (field->Data->embed) {
      embedField = new ComplexType(*field->Data);
      embedField->parent = this;
      delete field->Data;
      field->Data = NULL;
      complexfields.remove(field);
    } else if (field->Data->enumerated) {
      enumField = new ComplexType(*field->Data);
      enumField->parent = this;
      delete field->Data;
      field->Data = NULL;
      complexfields.remove(field);
    }
  }
Elemer Lelik's avatar
Elemer Lelik committed
1053

Elemer Lelik's avatar
Elemer Lelik committed
1054
1055
1056
1057
1058
1059
  if (enumField != NULL) {
    //Insert the order field in the front
    complexfields.push_front(enumField);
    //Push the field names into the order field
    for (List<Mstring>::iterator field = enumNames.begin(); field; field = field->Next) {
      enumField->enumfields.push_back(field->Data);
Elemer Lelik's avatar
Elemer Lelik committed
1060
    }
Elemer Lelik's avatar
Elemer Lelik committed
1061
  }
Elemer Lelik's avatar
Elemer Lelik committed
1062

Elemer Lelik's avatar
Elemer Lelik committed
1063
1064
1065
1066
  if (embedField != NULL) {
    //Insert the embed field to the front
    complexfields.push_front(embedField);
  }
Elemer Lelik's avatar
Elemer Lelik committed
1067

Elemer Lelik's avatar
Elemer Lelik committed
1068
1069
1070
1071
1072
1073
1074
  if (with_union) {
    unsigned number = 0;
    for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
      if (field->Data->name.convertedValue.foundAt("alt_") == field->Data->name.convertedValue.c_str()) {
        if (number == 0) {
          field->Data->name.upload(Mstring("alt_"));
        } else {
1075
1076
1077
          expstring_t new_name = mprintf("alt_%d", number);
          field->Data->name.upload(Mstring(new_name));
          Free(new_name);
Elemer Lelik's avatar
Elemer Lelik committed
1078
        }
Elemer Lelik's avatar
Elemer Lelik committed
1079
        number++;
Elemer Lelik's avatar
Elemer Lelik committed
1080
      }
Elemer Lelik's avatar
Elemer Lelik committed
1081
1082
    }
  }
Elemer Lelik's avatar
Elemer Lelik committed
1083

Elemer Lelik's avatar
Elemer Lelik committed
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  AttributeType * anyAttr = NULL;
  for (List<AttributeType*>::iterator field = attribfields.begin(), nextField; field; field = nextField) {
    nextField = field->Next;
    field->Data->applyUseAttribute();
    //Find anyattribute, and remove it
    if (field->Data->isAnyAttribute()) {
      anyAttr = new AttributeType(*field->Data);
      setParent(this, anyAttr);
      delete field->Data;
      field->Data = NULL;
      attribfields.remove(field);
    } else {
      field->Data->SimpleType::finalModification();
    }
  }
  
  //Push anyattribute to the front
  if (anyAttr != NULL) {
    anyAttr->applyNamespaceAttribute(V_anyAttributes);
    attribfields.push_back(anyAttr);
  }

  //Substitution group ordering
Elemer Lelik's avatar
Elemer Lelik committed
1107
  if(subsGroup == this || typeSubsGroup == this){ //We are a generated substitution group
Elemer Lelik's avatar
Elemer Lelik committed
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
    //Substitution group never empty
    ComplexType * front = complexfields.front();
    List<ComplexType*>::iterator it = complexfields.begin();
    complexfields.remove(it);
    complexfields.sort(compareComplexTypeNameSpaces);
    complexfields.sort(compareTypes);
    complexfields.push_front(front);
  }
}

void ComplexType::finalModification() {
1119
  subFinalModification();
Elemer Lelik's avatar
Elemer Lelik committed
1120
  setFieldPaths(empty_string);
1121
1122
1123
1124
}

void ComplexType::finalModification2() {
  subFinalModification2();
Elemer Lelik's avatar
Elemer Lelik committed
1125
1126
1127
1128
1129
1130
  List<Mstring> container;
  collectVariants(container);
  variant.clear();
  variant = container;
}

1131
1132
1133
1134
1135
1136
void ComplexType::subFinalModification2() {
  SimpleType::finalModification2();
  for (List<ComplexType*>::iterator field = complexfields.begin(); field; field = field->Next) {
    //Recursive call
    field->Data->subFinalModification2();
  }
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  for (List<AttributeType*>::iterator field = attribfields.begin(), nextField; field; field = nextField) {
    nextField = field->Next;
    if (field->Data->getUseVal() == prohibited || !field->Data->isVisible()) {
      //Not visible attribute removed
      delete field->Data;
      field->Data = NULL;
      attribfields.remove(field);
    } else {
      field->Data->SimpleType::finalModification2();
    }
1147
1148
1149
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
void ComplexType::printToFile(FILE * file) {
  printToFile(file, 0, false);
}

void ComplexType::printToFile(FILE * file, const unsigned level, const bool is_union) {
  if (!isVisible()) {
    return;
  }
  printComment(file, level);
  if (top) {
    fprintf(file, "type ");
    if(mode == listMode){
      printMinOccursMaxOccurs(file, is_union);
      fprintf(file, "%s", type.convertedValue.c_str());
    }else {
      fprintf(file, "%s %s", type.convertedValue.c_str(), name.convertedValue.c_str());
    }
1167
1168
1169
1170
1171
1172
    if(type.convertedValue == "record" || type.convertedValue == "union"){
      fprintf(file, "\n{\n");
      if (attribfields.empty() && complexfields.empty()) {
        fprintf(file, "\n");
      }
    } 
Elemer Lelik's avatar
Elemer Lelik committed
1173
1174
1175
1176
1177
1178
1179
1180
1181

    for (List<ComplexType*>::iterator c = complexfields.begin(), nextField; c; c = nextField) {
      nextField = c->Next;
      if (c->Data->embed || c->Data->enumerated) {
        c->Data->printToFile(file, level + 1, is_union);
        if (c->Next != NULL || !attribfields.empty()) {
          fprintf(file, ",\n");
        } else {
          fprintf(file, "\n");
Elemer Lelik's avatar
Elemer Lelik committed
1182
        }
Elemer Lelik's avatar
Elemer Lelik committed
1183
1184
1185
        delete c->Data;
        c->Data = NULL;
        complexfields.remove(c);
Elemer Lelik's avatar
Elemer Lelik committed
1186
      }
Elemer Lelik's avatar
Elemer Lelik committed
1187
1188
1189
1190
1191
1192
1193
1194
    }

    for (List<AttributeType*>::iterator f = attribfields.begin(); f; f = f->Next) {
      f->Data->printToFile(file, level + 1);
      if (f->Next != NULL || !complexfields.empty()) {
        fprintf(file, ",\n");
      } else {
        fprintf(file, "\n");
Elemer Lelik's avatar
Elemer Lelik committed
1195
1196
      }
    }
Elemer Lelik's avatar
Elemer Lelik committed
1197
1198
1199
1200
1201
1202
1203

    for (List<ComplexType*>::iterator c = complexfields.begin(); c; c = c->Next) {
      c->Data->printToFile(file, level + 1, is_union);
      if (c->Next != NULL) {
        fprintf(file, ",\n");
      } else {
        fprintf(file, "\n");
Elemer Lelik's avatar
Elemer Lelik committed
1204
1205
      }
    }
Elemer Lelik's avatar
Elemer Lelik committed
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
  } else {
    const bool field_is_record = getType().convertedValue == Mstring("record");
    const bool field_is_union = getType().convertedValue == "union";
    if (complexfields.empty() && attribfields.empty() && (field_is_record || field_is_union)) {
      if (field_is_record) {
        indent(file, level);
        printMinOccursMaxOccurs(file, is_union);
        fprintf(file, "%s {\n", getType().convertedValue.c_str());
        indent(file, level);
        fprintf(file, "} %s", getName().convertedValue.c_str());
        if (isOptional) {
          fprintf(file, " optional");
        }
      } else if (field_is_union) {
        indent(file, level);
        printMinOccursMaxOccurs(file, is_union);
        fprintf(file, "%s {\n", getType().convertedValue.c_str());
        indent(file, level + 1);
        fprintf(file, "record length(0 .. 1) of enumerated { NULL_ } choice\n");
        indent(file, level);
        fprintf(file, "} %s", getName().convertedValue.c_str());
        if (isOptional) {
          fprintf(file, " optional");
        }
      }
    } else {
      indent(file, level);
      if (getEnumeration().modified) {
        if (isFloatType(getBuiltInBase())) {
          fprintf(file, "%s (", type.convertedValue.c_str());
          getEnumeration().sortFacets();
          getEnumeration().printToFile(file);
          fprintf(file, ")");
        } else {
          printMinOccursMaxOccurs(file, with_union);
          fprintf(file, "enumerated {\n");
          //getEnumeration().sortFacets();
          getEnumeration().printToFile(file, level);
          fprintf(file, "\n");
          indent(file, level);
          fprintf(file, "} ");
        }
      } else {
        int multiplicity = multi(module, getReference(), this);
        if ((multiplicity > 1) && getReference().get_ref()) {
          fprintf(file, "%s.", getReference().get_ref()->getModule()->getModulename().c_str());
        }
1253
1254
1255
1256
1257
1258
1259
        if (field_is_record || field_is_union || listPrint) {
          unsigned long long int tempMin = getMinOccurs();
          unsigned long long int tempMax = getMaxOccurs();
          if (listPrint) {
            setMinOccurs(listMinOccurs);
            setMaxOccurs(listMaxOccurs);
          }
Elemer Lelik's avatar
Elemer Lelik committed
1260
          printMinOccursMaxOccurs(file, with_union, !first_child || parent->getXsdtype() != n_choice);
1261
1262
1263
          if (listPrint) {
            setMinOccurs(tempMin);
            setMaxOccurs(tempMax);
Elemer Lelik's avatar
Elemer Lelik committed
1264
          }
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
          if (listPrint && complexfields.size() == 0) {
            printMinOccursMaxOccurs(file, false);
            fprintf(file, "%s ",getType().convertedValue.c_str());
          } else {
            fprintf(file, "%s {\n", getType().convertedValue.c_str());
            for (List<AttributeType*>::iterator f = attribfields.begin(); f; f = f->Next) {
              f->Data->printToFile(file, level + 1);
              if (f->Next != NULL || !complexfields.empty()) {
                fprintf(file, ",\n");
              } else {
                fprintf(file, "\n");
              }
            }
Elemer Lelik's avatar
Elemer Lelik committed
1278

1279
1280
1281
1282
1283
1284
1285
            for (List<ComplexType*>::iterator c = complexfields.begin(); c; c = c->Next) {
              c->Data->printToFile(file, level + 1, is_union);
              if (c->Next != NULL) {
                fprintf(file, ",\n");
              } else {
                fprintf(file, "\n");
              }
Elemer Lelik's avatar
Elemer Lelik committed
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
            }
          }
        } else {
          printMinOccursMaxOccurs(file, with_union, !first_child);
          fprintf(file, "%s ", getType().convertedValue.c_str());
          if (getName().convertedValue == Mstring("order") && getType().convertedValue == Mstring("enumerated")) {
            fprintf(file, "{\n");
            for (List<Mstring>::iterator e = enumfields.begin(); e; e = e->Next) {
              indent(file, level + 1);
              fprintf(file, "%s", e->Data.c_str());
              if (e->Next != NULL) {
                fprintf(file, ",\n");
              } else {
                fprintf(file, "\n");
              }
            }
            indent(file, level);
            fprintf(file, "} ");
          }
        }
Elemer Lelik's avatar
Elemer Lelik committed
1306
      }
1307
      if ((field_is_record || field_is_union) && !listPrint) {
Elemer Lelik's avatar