SimpleType.cc 57.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
 *   Raduly, Csaba
 *   Szabo, Bence Janos
 *
 ******************************************************************************/
Elemer Lelik's avatar
Elemer Lelik committed
17
18
19
20
21
22
23
#include "SimpleType.hh"

#include "GeneralFunctions.hh"

#include "TTCN3ModuleInventory.hh"
#include "TTCN3Module.hh"
#include "ComplexType.hh"
24
#include "Constant.hh"
25
#include "converter.hh"
Elemer Lelik's avatar
Elemer Lelik committed
26

27
#include <math.h>
28
29
#include <cfloat>

Elemer Lelik's avatar
Elemer Lelik committed
30
extern bool g_flag_used;
Elemer Lelik's avatar
Elemer Lelik committed
31
extern bool h_flag_used;
Elemer Lelik's avatar
Elemer Lelik committed
32

33
34
35
36
37
38
39
40
41
42
43
44
#ifndef INFINITY
#define INFINITY (DBL_MAX*DBL_MAX)
#endif
const double PLUS_INFINITY(INFINITY);
const double MINUS_INFINITY(-INFINITY);

#ifdef NAN
const double NOT_A_NUMBER(NAN);
#else
const double NOT_A_NUMBER((double)PLUS_INFINITY+(double)MINUS_INFINITY);
#endif

Elemer Lelik's avatar
Elemer Lelik committed
45
46
SimpleType::SimpleType(XMLParser * a_parser, TTCN3Module * a_module, ConstructType a_construct)
: RootType(a_parser, a_module, a_construct)
Elemer Lelik's avatar
Elemer Lelik committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
, builtInBase()
, length(this)
, pattern(this)
, enumeration(this)
, whitespace(this)
, value(this)
, element_form_as(notset)
, attribute_form_as(notset)
, mode(noMode)
, outside_reference()
, in_name_only(false)
, fromRef(false)
, xsdtype(n_NOTSET)
, isOptional(false)
Elemer Lelik's avatar
Elemer Lelik committed
61
, substitutionGroup(empty_string)
Elemer Lelik's avatar
Elemer Lelik committed
62
, subsGroup(NULL)
Elemer Lelik's avatar
Elemer Lelik committed
63
64
, typeSubsGroup(NULL)
, addedToTypeSubstitution(false)
Elemer Lelik's avatar
Elemer Lelik committed
65
, block(not_set)
66
, inList(false)
67
, alias(NULL)
68
, defaultForEmptyConstant(NULL)
69
70
, parent(NULL)
, nameDep(NULL) {
Elemer Lelik's avatar
Elemer Lelik committed
71
}
Elemer Lelik's avatar
Elemer Lelik committed
72
73
74

SimpleType::SimpleType(const SimpleType& other)
: RootType(other)
Elemer Lelik's avatar
Elemer Lelik committed
75
76
77
78
79
80
81
82
83
84
85
86
87
88
, builtInBase(other.builtInBase)
, length(other.length)
, pattern(other.pattern)
, enumeration(other.enumeration)
, whitespace(other.whitespace)
, value(other.value)
, element_form_as(other.element_form_as)
, attribute_form_as(other.attribute_form_as)
, mode(other.mode)
, outside_reference(other.outside_reference)
, in_name_only(other.in_name_only)
, fromRef(other.fromRef)
, xsdtype(other.xsdtype)
, isOptional(other.isOptional)
Elemer Lelik's avatar
Elemer Lelik committed
89
, substitutionGroup(other.substitutionGroup)
Elemer Lelik's avatar
Elemer Lelik committed
90
, subsGroup(other.subsGroup)
Elemer Lelik's avatar
Elemer Lelik committed
91
92
, typeSubsGroup(other.typeSubsGroup)
, addedToTypeSubstitution(other.addedToTypeSubstitution)
Elemer Lelik's avatar
Elemer Lelik committed
93
, block(other.block)
94
, inList(other.inList)
95
, alias(other.alias)
96
, defaultForEmptyConstant(other.defaultForEmptyConstant)
97
98
, parent(NULL)
, nameDep(other.nameDep) {
Elemer Lelik's avatar
Elemer Lelik committed
99
100
101
102
103
  length.parent = this;
  pattern.parent = this;
  enumeration.parent = this;
  whitespace.p_parent = this;
  value.parent = this;
104
105
106
107
  
  if (nameDep != NULL) {
    nameDep->addToNameDepList(this);
  }
Elemer Lelik's avatar
Elemer Lelik committed
108
109
}

Elemer Lelik's avatar
Elemer Lelik committed
110
void SimpleType::loadWithValues() {
Elemer Lelik's avatar
Elemer Lelik committed
111
  const XMLParser::TagAttributes & atts = parser->getActualTagAttributes();
Elemer Lelik's avatar
Elemer Lelik committed
112
113
114
115
116
  switch (parser->getActualTagName()) {
    case n_restriction:
      type.upload(atts.base);
      setReference(atts.base);
      mode = restrictionMode;
Elemer Lelik's avatar
Elemer Lelik committed
117
      break;
Elemer Lelik's avatar
Elemer Lelik committed
118
119
120
    case n_list:
      type.upload(atts.itemType);
      setReference(atts.itemType);
121
122
      setMinOccurs(0);
      setMaxOccurs(ULLONG_MAX);
Elemer Lelik's avatar
Elemer Lelik committed
123
124
      addVariant(V_list);
      mode = listMode;
125
      inList = true;
Elemer Lelik's avatar
Elemer Lelik committed
126
      break;
Elemer Lelik's avatar
Elemer Lelik committed
127
128
129
130
    case n_union:
    { // generating complextype from simpletype
      ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagUnion);
      new_complextype->loadWithValues();
Elemer Lelik's avatar
Elemer Lelik committed
131
132
      break;
    }
Elemer Lelik's avatar
Elemer Lelik committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    case n_element:
      name.upload(atts.name);
      type.upload(atts.type);
      setReference(atts.type, true);
      if (!atts.nillable) {
        applyDefaultAttribute(atts.default_);
        applyFixedAttribute(atts.fixed);
      }
      applyAbstractAttribute(atts.abstract);
      applySubstitionGroupAttribute(atts.substitionGroup);
      applyBlockAttribute(atts.block);
      //This shall be the last instruction always
      applyNillableAttribute(atts.nillable);
      break;
    case n_attribute:
      name.upload(atts.name);
      type.upload(atts.type);
      xsdtype = n_attribute;
      setReference(atts.type, true);
      applyDefaultAttribute(atts.default_);
      applyFixedAttribute(atts.fixed);
      break;
    case n_simpleType:
      name.upload(atts.name);
      break;
    case n_complexType:
    { // generating complextype from simpletype
      ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagComplexType);
      new_complextype->loadWithValues();
      break;
Elemer Lelik's avatar
Elemer Lelik committed
163
    }
Elemer Lelik's avatar
Elemer Lelik committed
164
    case n_length:
165
       if (inList && (xsdtype != n_NOTSET || mode == restrictionAfterListMode)) {
166
167
        setMinOccurs(strtoull(atts.value.c_str(), NULL, 0));
        setMaxOccurs(strtoull(atts.value.c_str(), NULL, 0));
Elemer Lelik's avatar
Elemer Lelik committed
168
169
170
171
172
173
174
        break;
      }
      length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
      length.facet_maxLength = strtoull(atts.value.c_str(), NULL, 0);
      length.modified = true;
      break;
    case n_minLength:
175
      if (inList && (xsdtype != n_NOTSET || mode == restrictionAfterListMode)) {
176
        setMinOccurs(strtoull(atts.value.c_str(), NULL, 0));
Elemer Lelik's avatar
Elemer Lelik committed
177
178
179
180
181
182
        break;
      }
      length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
      length.modified = true;
      break;
    case n_maxLength:
183
      if (inList && (xsdtype != n_NOTSET || mode == restrictionAfterListMode)) {
184
        setMaxOccurs(strtoull(atts.value.c_str(), NULL, 0));
Elemer Lelik's avatar
Elemer Lelik committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
        break;
      }
      length.facet_maxLength = strtoull(atts.value.c_str(), NULL, 0);
      length.modified = true;
      break;
    case n_pattern:
      pattern.facet = atts.value;
      pattern.modified = true;
      break;
    case n_enumeration:
      enumeration.facets.push_back(atts.value);
      enumeration.modified = true;
      break;
    case n_whiteSpace:
      whitespace.facet = atts.value;
      whitespace.modified = true;
      break;
    case n_minInclusive:
      if (atts.value == "NaN") {
        value.not_a_number = true;
      } else if (atts.value == "-INF") {
        value.facet_minInclusive = -DBL_MAX;
      } else if (atts.value == "INF") {
        value.facet_minInclusive = DBL_MAX;
      } else {
        value.facet_minInclusive = stringToLongDouble(atts.value.c_str());
      }
      value.modified = true;
      break;
    case n_maxInclusive:
      if (atts.value == "NaN") {
        value.not_a_number = true;
      } else if (atts.value == "-INF") {
        value.facet_maxInclusive = -DBL_MAX;
      } else if (atts.value == "INF") {
        value.facet_maxInclusive = DBL_MAX;
      } else {
        value.facet_maxInclusive = stringToLongDouble(atts.value.c_str());
      }
      value.modified = true;
      break;
    case n_minExclusive:
      if (atts.value == "NaN") {
        setInvisible();
      } else if (atts.value == "-INF") {
        value.facet_minExclusive = -DBL_MAX;
      } else if (atts.value == "INF") {
        setInvisible();
      } else {
        value.facet_minExclusive = stringToLongDouble(atts.value.c_str());
      }
      value.modified = true;
      value.lowerExclusive = true;
      break;
    case n_maxExclusive:
      if (atts.value == "NaN") {
        setInvisible();
      } else if (atts.value == "-INF") {
        setInvisible();
      } else if (atts.value == "INF") {
        value.facet_maxExclusive = DBL_MAX;
      } else {
        value.facet_maxExclusive = stringToLongDouble(atts.value.c_str());
      }
      value.modified = true;
      value.upperExclusive = true;
      break;
    case n_totalDigits:
      value.facet_totalDigits = strtoul(atts.value.c_str(), NULL, 0);
      value.modified = true;
      break;
    case n_fractionDigits:
257
      addVariant(V_fractionDigits, atts.value);
Elemer Lelik's avatar
Elemer Lelik committed
258
259
260
261
262
263
264
265
266
      break;
    case n_label:
      addComment(Mstring("LABEL:"));
      break;
    case n_definition:
      addComment(Mstring("DEFINITION:"));
      break;
    default:
      break;
Elemer Lelik's avatar
Elemer Lelik committed
267
268
269
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
270
void SimpleType::applyDefaultAttribute(const Mstring& default_value) {
Elemer Lelik's avatar
Elemer Lelik committed
271
272
  if (!default_value.empty()) {
    value.default_value = default_value;
273
    const Mstring typeT = type.originalValueWoPrefix.getValueWithoutPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
274
    //Not supported for hexBinary and base64Binary
275
    if (typeT != "hexBinary" && typeT != "base64Binary" && typeT != "NMTOKENS" && typeT != "IDREFS" && typeT != "ENTITIES") {
276
277
278
279
280
      Constant * c = new Constant(this, type.convertedValue, default_value);
      module->addConstant(c);
      defaultForEmptyConstant = c;
      // Delay adding the defaultForEmpty variant after the nameconversion
      // happened on the constants
Elemer Lelik's avatar
Elemer Lelik committed
281
    }
Elemer Lelik's avatar
Elemer Lelik committed
282
283
284
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
285
void SimpleType::applyFixedAttribute(const Mstring& fixed_value) {
Elemer Lelik's avatar
Elemer Lelik committed
286
287
  if (!fixed_value.empty()) {
    value.fixed_value = fixed_value;
Elemer Lelik's avatar
Elemer Lelik committed
288
    value.modified = true;
289
    const Mstring typeT = type.originalValueWoPrefix.getValueWithoutPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
290
    //Not supported for hexBinary and base64Binary
291
    if (typeT != "hexBinary" && typeT != "base64Binary" && typeT != "NMTOKENS" && typeT != "IDREFS" && typeT != "ENTITIES") {
292
293
294
295
296
      Constant * c = new Constant(this, type.convertedValue, fixed_value);
      module->addConstant(c);
      defaultForEmptyConstant = c;
      // Delay adding the defaultForEmpty variant after the nameconversion
      // happened on the constants
Elemer Lelik's avatar
Elemer Lelik committed
297
    }
Elemer Lelik's avatar
Elemer Lelik committed
298
299
300
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
301
302
void SimpleType::applyNillableAttribute(const bool nillable) {
  if (nillable) {
Elemer Lelik's avatar
Elemer Lelik committed
303
304
305
306
307
    ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagNillable); // generating complextype from simpletype
    new_complextype->loadWithValues();
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
308
309
void SimpleType::applyAbstractAttribute(const bool abstract_value) {
  if (abstract_value) {
Elemer Lelik's avatar
Elemer Lelik committed
310
    addVariant(V_abstract);
Elemer Lelik's avatar
Elemer Lelik committed
311
312
313
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
314
315
316
void SimpleType::applySubstitionGroupAttribute(const Mstring& substitution_group){
  if(!substitution_group.empty()){
    substitutionGroup = substitution_group;
Elemer Lelik's avatar
Elemer Lelik committed
317
318
319
320
321
322
323
324
325
326
327
328
  }
}

void SimpleType::applyBlockAttribute(const BlockValue block_){
  if(block_ == not_set){
    block = getModule()->getBlockDefault();
  }else {
    block = block_;
  }
}

void SimpleType::addToSubstitutions(){
Elemer Lelik's avatar
Elemer Lelik committed
329
  if(!g_flag_used || substitutionGroup.empty()){
Elemer Lelik's avatar
Elemer Lelik committed
330
331
    return;
  }
332
  SimpleType * st_ = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(this, substitutionGroup, want_BOTH, c_element);
Elemer Lelik's avatar
Elemer Lelik committed
333
334
  if(st_ == NULL){
    printError(module->getSchemaname(), name.convertedValue,
Elemer Lelik's avatar
Elemer Lelik committed
335
        "Reference for a non-defined type: " + substitutionGroup);
Elemer Lelik's avatar
Elemer Lelik committed
336
337
338
339
340
341
342
343
344
      TTCN3ModuleInventory::getInstance().incrNumErrors();
    return;
  }
  SimpleType * st = (SimpleType*)st_;
  if(st->getSubstitution() != NULL){
    st = st->getSubstitution();
  }

  st->referenceResolving();
Elemer Lelik's avatar
Elemer Lelik committed
345
  substitutionGroup = empty_string;
346
  //SimpleType
Elemer Lelik's avatar
Elemer Lelik committed
347
  if(st->subsGroup == NULL){
348
    ComplexType * head_element = new ComplexType(*st, ComplexType::fromElementSubstitution);
349
    for(List<RootType*>::iterator simpletype = st->nameDepList.begin(); simpletype; simpletype = simpletype->Next){
Elemer Lelik's avatar
Elemer Lelik committed
350
      head_element->getNameDepList().push_back(simpletype->Data);
Elemer Lelik's avatar
Elemer Lelik committed
351
352
353
354
355
356
357
358
359
360
361
362
363
364
    }
    st->nameDepList.clear();
    st->getModule()->addMainType(head_element);
    head_element->addVariant(V_untagged);
    head_element->addSubstitution(st);
    head_element->addSubstitution(this);
    //if st->subsGroup == this, then it is a generated subs group
    st->subsGroup = head_element;
    st->setInvisible();
  }else {
    st->subsGroup->addSubstitution(this);
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
void SimpleType::addToTypeSubstitutions() {
  //If the user did not request type substitution generation or
  //the type is already added to type substitution
  if(!h_flag_used || addedToTypeSubstitution){
    return;
  }
  //Only available if it is a restricion or extension
  if(mode != extensionMode && mode != restrictionMode){
    return;
  }
  //Only top level complexTypes or simpleTypes, ergo no elements
  if(parent != NULL || hasVariant(Mstring("\"element\""))){
    return;
  }

  //It would be nice if here outside_reference.resolved to everything
  bool newST = false;
Elemer Lelik's avatar
Elemer Lelik committed
382
  SimpleType * st = (SimpleType*)outside_reference.get_ref();
383
384
  bool isConvertedBuiltIn = isBuiltInType(type.convertedValue);
  if(st == NULL && !isConvertedBuiltIn){
Elemer Lelik's avatar
Elemer Lelik committed
385
386
    //Not even a reference, and not a built in type
    return;
387
  }else if(st == NULL && isConvertedBuiltIn){
Elemer Lelik's avatar
Elemer Lelik committed
388
389
390
391
    st = new SimpleType(parser, module, construct);
    st->type.upload(type.convertedValue);
    st->name.upload(type.convertedValue);
    st->typeSubsGroup = findBuiltInTypeInStoredTypeSubstitutions(type.convertedValue);
Elemer Lelik's avatar
Elemer Lelik committed
392
393
394
395
    outside_reference.set_resolved(st);
    //Add this decoy type to the maintypes -> module will free st
    //st->setInvisible();
    module->addMainType(st);
Elemer Lelik's avatar
Elemer Lelik committed
396
397
398
399
    newST = true;
  }

  addedToTypeSubstitution = true;
Elemer Lelik's avatar
Elemer Lelik committed
400
  st->addToTypeSubstitutions();
Elemer Lelik's avatar
Elemer Lelik committed
401
402
403
  //If type substitution is NULL then we need to create the union
  if(st->getTypeSubstitution() == NULL){
    ComplexType * head_element = new ComplexType(*st, ComplexType::fromTypeSubstitution);
Elemer Lelik's avatar
Elemer Lelik committed
404
    head_element->getNameDepList().clear();
405
406
    for(List<RootType*>::iterator roottype = st->nameDepList.begin(), nextST; roottype; roottype = nextST){
      nextST = roottype->Next;
Elemer Lelik's avatar
Elemer Lelik committed
407
      //Don't add if it is in a type substitution 
408
409
410
411
412
      SimpleType* simpletype = dynamic_cast<SimpleType*>(roottype->Data);
      if (simpletype == NULL) continue;
      if(simpletype->getTypeSubstitution() == NULL){
        head_element->getNameDepList().push_back(roottype->Data);
        st->getNameDepList().remove(roottype);
Elemer Lelik's avatar
Elemer Lelik committed
413
      }
Elemer Lelik's avatar
Elemer Lelik committed
414
    }
Elemer Lelik's avatar
Elemer Lelik committed
415
    
Elemer Lelik's avatar
Elemer Lelik committed
416
417
    st->getModule()->addMainType(head_element);
    head_element->addVariant(V_useType);
Elemer Lelik's avatar
Elemer Lelik committed
418
419
420
421
    //For cascading type substitution
    if(st->outside_reference.get_ref() != NULL && ((ComplexType*)st->outside_reference.get_ref())->getTypeSubstitution() != NULL){
      head_element->setParentTypeSubsGroup(((ComplexType*)st->outside_reference.get_ref())->getTypeSubstitution());
    }
Elemer Lelik's avatar
Elemer Lelik committed
422
423
424
425
426
427
    head_element->addTypeSubstitution(st);
    head_element->addTypeSubstitution(this);
    bool found = false;
    //Check to find if there was already an element reference with this type
    for(List<typeNameDepList>::iterator str = module->getElementTypes().begin(); str; str = str->Next){
      Mstring prefix = str->Data.type.getPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
428
      Mstring value_ = str->Data.type.getValueWithoutPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
429

Elemer Lelik's avatar
Elemer Lelik committed
430
431
      if((value_ == st->getName().convertedValue.getValueWithoutPrefix(':') && prefix == module->getTargetNamespaceConnector()) ||
         (isBuiltInType(value_) && !isBuiltInType(st->getType().convertedValue) && value_ == st->getType().convertedValue && prefix == module->getTargetNamespaceConnector())){
Elemer Lelik's avatar
Elemer Lelik committed
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
        //Push the namedeplist
        for(List<SimpleType*>::iterator simpletype = str->Data.nameDepList.begin(); simpletype; simpletype = simpletype->Next){
          head_element->getNameDepList().push_back(simpletype->Data);
        }
        found = true;
        str->Data.typeSubsGroup = head_element;
        break;
      }
    }
    if(!found){
      head_element->setInvisible();
    }
    st->typeSubsGroup = head_element;
    st->getModule()->addStoredTypeSubstitution(head_element);
  }else {
    st->getTypeSubstitution()->addTypeSubstitution(this);
  }
  if(newST){
Elemer Lelik's avatar
Elemer Lelik committed
450
451
    //Make the decoy invisible
    st->setInvisible();
Elemer Lelik's avatar
Elemer Lelik committed
452
453
454
455
456
457
458
  }
}

void SimpleType::collectElementTypes(SimpleType* found_ST, ComplexType* found_CT){
  //Only if type substitution is enabled and it is a top level(simpletype) element or
  //it is a not top level element(complextype)
  if(h_flag_used && (hasVariant(Mstring("\"element\"")) || xsdtype == n_element)){
459
    SimpleType * st =  NULL, *nameDepType = NULL;
Elemer Lelik's avatar
Elemer Lelik committed
460
    Mstring uri, value_, type_;
Elemer Lelik's avatar
Elemer Lelik committed
461
462
463
464
    if(found_ST != NULL || found_CT != NULL){
      // st := found_ST or found_CT, which is not null
      st = found_ST != NULL ? found_ST : found_CT;
      uri = outside_reference.get_uri();
Elemer Lelik's avatar
Elemer Lelik committed
465
466
      value_ = outside_reference.get_val();
      type_ = value_;
Elemer Lelik's avatar
Elemer Lelik committed
467
468
469
    }else if(isBuiltInType(type.convertedValue)){
      st = this;
      uri = module->getTargetNamespace();
Elemer Lelik's avatar
Elemer Lelik committed
470
      value_ = type.convertedValue;
Elemer Lelik's avatar
Elemer Lelik committed
471
      if(outside_reference.empty()){
Elemer Lelik's avatar
Elemer Lelik committed
472
        type_ = value_;
473
        nameDepType = this;
Elemer Lelik's avatar
Elemer Lelik committed
474
475
476
477
478
479
480
481
482
      }else {
        type_ = outside_reference.get_val();
      }
    }else {
      //It is not possible to reach here (should be)
      return;
    }
    type_ = type_.getValueWithoutPrefix(':');
    bool found = false;
Elemer Lelik's avatar
Elemer Lelik committed
483
    const Mstring typeSubsName = value_ + Mstring("_derivations");
Elemer Lelik's avatar
Elemer Lelik committed
484
485
486
487
488
489
490
    //Find if we already have a substitution type to this element reference
    for(List<ComplexType*>::iterator complex = st->getModule()->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next){

      if(uri == st->getModule()->getTargetNamespace() && typeSubsName == complex->Data->getName().convertedValue){
        complex->Data->setVisible();
        if(st->getXsdtype() != n_NOTSET && this == st){ //otherwise records would be renamed too
          complex->Data->addToNameDepList(st);
491
          ((ComplexType*)st)->setNameDep(nameDepType);
Elemer Lelik's avatar
Elemer Lelik committed
492
493
494
495
496
497
498
499
500
501
502
        }
        found = true;
        break;
      }
    }
    //Add the reference, to future possible type substitution
    if(!found){
      Mstring prefix = st->getModule()->getTargetNamespaceConnector();
      if(prefix != empty_string){
        prefix += ":";
      }
503
      st->getModule()->addElementType(prefix + type_, nameDepType);
Elemer Lelik's avatar
Elemer Lelik committed
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    }
  }
}

ComplexType * SimpleType::findBuiltInTypeInStoredTypeSubstitutions(const Mstring& builtInType){
  const Mstring typeSubsName = builtInType.getValueWithoutPrefix(':') + Mstring("_derivations");
  for(List<ComplexType*>::iterator complex = module->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next){
    if(typeSubsName == complex->Data->getName().convertedValue){
      return complex->Data;
    }
  }
  return NULL;
}


Elemer Lelik's avatar
Elemer Lelik committed
519
void SimpleType::setReference(const Mstring& ref, bool only_name_dependency) {
Elemer Lelik's avatar
Elemer Lelik committed
520
521
522
523
524
  if (ref.empty()) {
    return;
  }
  if (isBuiltInType(ref)) {
    builtInBase = ref.getValueWithoutPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
525
526
527
    if (name.convertedValue.empty()) {
      name.upload(ref);
    }
528
529
    if (type.convertedValue.empty() ||
        type.convertedValue.getValueWithoutPrefix(':') == "anySimpleType") {
530
531
532
533
534
535
536
537
      type.upload(ref);
    }
    bool found = false;
    for (List<NamespaceType>::iterator ns = getModule()->getDeclaredNamespaces().begin(); ns; ns = ns->Next) {
      if (ns->Data.uri != XMLSchema && type.refPrefix == ns->Data.prefix.c_str()) {
        found = true;
        break;
      }
Elemer Lelik's avatar
Elemer Lelik committed
538
    }
539
    if (!found) {
540
      fromRef = true;
541
542
      return;
    }
Elemer Lelik's avatar
Elemer Lelik committed
543
544
545
546
547
548
549
  }

  Mstring refPrefix = ref.getPrefix(':');
  Mstring refValue = ref.getValueWithoutPrefix(':');
  Mstring refUri;
  // Find the URI amongst the known namespace URIs
  List<NamespaceType>::iterator declNS;
Elemer Lelik's avatar
Elemer Lelik committed
550
  for (declNS = module->getDeclaredNamespaces().begin(); declNS; declNS = declNS->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
551
552
553
554
555
556
557
558
559
560
    if (refPrefix == declNS->Data.prefix) {
      refUri = declNS->Data.uri;
      break;
    }
  }

  // FIXME: can this part be moved above the search ?
  if (refUri.empty()) { // not found
    if (refPrefix == "xml") {
      refUri = "http://www.w3.org/XML/1998/namespace";
Elemer Lelik's avatar
Elemer Lelik committed
561
    } else if (refPrefix == "xmlns") {
Elemer Lelik's avatar
Elemer Lelik committed
562
      refUri = "http://www.w3.org/2000/xmlns";
Elemer Lelik's avatar
Elemer Lelik committed
563
    } else if (refPrefix.empty() && module->getTargetNamespace() == "NoTargetNamespace") {
Elemer Lelik's avatar
Elemer Lelik committed
564
565
566
567
568
569
570
571
      refUri = "NoTargetNamespace";
    }
  }

  if (refUri.empty()) { // something is incorrect - unable to find the uri to the given prefix
    if (refPrefix.empty()) {
      printError(module->getSchemaname(), parser->getActualLineNumber(),
        Mstring("The absent namespace must be imported because "
Elemer Lelik's avatar
Elemer Lelik committed
572
        "it is not the same as the target namespace of the current schema."));
Elemer Lelik's avatar
Elemer Lelik committed
573
574
      parser->incrNumErrors();
      return;
Elemer Lelik's avatar
Elemer Lelik committed
575
    } else {
Elemer Lelik's avatar
Elemer Lelik committed
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
      printError(module->getSchemaname(), parser->getActualLineNumber(),
        "The value \'" + ref + "\' is incorrect: "
        "A namespace prefix does not denote any URI.");
      parser->incrNumErrors();
      return;
    }
  }

  if (only_name_dependency) {
    in_name_only = true;
  }

  outside_reference.load(refUri, refValue, &declNS->Data);
}

Elemer Lelik's avatar
Elemer Lelik committed
591
void SimpleType::referenceResolving() {
Elemer Lelik's avatar
Elemer Lelik committed
592
  if (outside_reference.empty() || outside_reference.is_resolved()){
Elemer Lelik's avatar
Elemer Lelik committed
593
594
595
596
    addToTypeSubstitutions();
    collectElementTypes();
  }
  if(outside_reference.empty() && substitutionGroup.empty()) return;
Elemer Lelik's avatar
Elemer Lelik committed
597
  if (outside_reference.is_resolved()) return;
598
  
Elemer Lelik's avatar
Elemer Lelik committed
599
600
  if(!outside_reference.empty()){
    SimpleType * found_ST = static_cast<SimpleType*> (
601
      TTCN3ModuleInventory::getInstance().lookup(this, want_ST, c_simpleType));
Elemer Lelik's avatar
Elemer Lelik committed
602
    ComplexType * found_CT = static_cast<ComplexType*> (
603
      TTCN3ModuleInventory::getInstance().lookup(this, want_CT, c_complexType));
Elemer Lelik's avatar
Elemer Lelik committed
604
    // It _is_ possible to find both
Elemer Lelik's avatar
Elemer Lelik committed
605
    collectElementTypes(found_ST, found_CT);
606
607
608
609
610
    // If found_ST is a complexType with an xsd:union restricted to certain values
    if (found_ST != NULL && found_ST->getType().convertedValue == Mstring("union") && mode == restrictionMode) {
      found_CT = (ComplexType*)found_ST;
      found_ST = NULL;
    }
Elemer Lelik's avatar
Elemer Lelik committed
611
612
613
    if (found_ST != NULL) {
      if (!found_ST->outside_reference.empty() && !found_ST->outside_reference.is_resolved() && found_ST != this) {
        found_ST->referenceResolving();
Elemer Lelik's avatar
Elemer Lelik committed
614
615
616
        if(!found_ST->outside_reference.is_resolved()){
          found_ST->outside_reference.set_resolved(NULL);
        }
Elemer Lelik's avatar
Elemer Lelik committed
617
618
      }
      referenceForST(found_ST);
Elemer Lelik's avatar
Elemer Lelik committed
619
      addToTypeSubstitutions();
Elemer Lelik's avatar
Elemer Lelik committed
620
621
622
623
624
      if (!isBuiltInType(type.convertedValue)) {
        found_ST->addToNameDepList(this);
      }
    } else if (found_CT != NULL) {
      referenceForCT(found_CT);
Elemer Lelik's avatar
Elemer Lelik committed
625
      addToTypeSubstitutions();
Elemer Lelik's avatar
Elemer Lelik committed
626
627
628
      if (!isBuiltInType(type.convertedValue)) {
        found_CT->addToNameDepList(this);
      }
629
    } else {
Elemer Lelik's avatar
Elemer Lelik committed
630
      printError(module->getSchemaname(), name.convertedValue,
631
        "Reference for a non-defined simpleType or complexType type: " + outside_reference.repr());
Elemer Lelik's avatar
Elemer Lelik committed
632
633
634
      TTCN3ModuleInventory::getInstance().incrNumErrors();
      outside_reference.set_resolved(NULL);
    }
Elemer Lelik's avatar
Elemer Lelik committed
635
636
    addToSubstitutions();
  }else {
Elemer Lelik's avatar
Elemer Lelik committed
637
    addToSubstitutions();
Elemer Lelik's avatar
Elemer Lelik committed
638
639
640
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
641
void SimpleType::referenceForST(SimpleType * found_ST) {
642
643
644
  while(found_ST != NULL && found_ST->alias != NULL){
    found_ST = found_ST->alias;
  }
Elemer Lelik's avatar
Elemer Lelik committed
645
646
647
648
  outside_reference.set_resolved(found_ST);
  if (in_name_only)
    return;

649
650
651
652
  if (!found_ST->builtInBase.empty()) {
    builtInBase = found_ST->builtInBase;
  }

Elemer Lelik's avatar
Elemer Lelik committed
653
654
655
  if (construct == c_element)
    return;

656
  if (mode == listMode || mode == restrictionAfterListMode)
Elemer Lelik's avatar
Elemer Lelik committed
657
    return;
658
659
660
  
  bool hasRestrOrExt = hasRestrictionOrExtension();
  
Elemer Lelik's avatar
Elemer Lelik committed
661
662
663
664
665
  length.applyReference(found_ST->length);
  pattern.applyReference(found_ST->pattern);
  enumeration.applyReference(found_ST->enumeration);
  whitespace.applyReference(found_ST->whitespace);
  value.applyReference(found_ST->value);
666
667
668
669
670
671
672
673
674
  
  if(!hasRestrOrExt){
    length.modified = false;
    pattern.modified = false;
    enumeration.modified = false;
    whitespace.modified = false;
    value.modified = false;
    alias = found_ST;
  }
Elemer Lelik's avatar
Elemer Lelik committed
675
676

  mode = found_ST->mode;
677
678
  if (found_ST->mode != listMode && found_ST->mode != restrictionAfterListMode
      && hasRestrOrExt) {
Elemer Lelik's avatar
Elemer Lelik committed
679
680
    type.upload(found_ST->getType().convertedValue);
  }
Elemer Lelik's avatar
Elemer Lelik committed
681
682
}

Elemer Lelik's avatar
Elemer Lelik committed
683
void SimpleType::referenceForCT(ComplexType * found_CT) {
Elemer Lelik's avatar
Elemer Lelik committed
684
685
686
687
688
  outside_reference.set_resolved(found_CT);

  if (in_name_only)
    return;

Elemer Lelik's avatar
Elemer Lelik committed
689
690
691
692
693
694
695
  // Section 7.5.3 Example5
  if (found_CT->getType().convertedValue == Mstring("union") && mode == restrictionMode) {
    for (List<Mstring>::iterator facet = enumeration.facets.begin(); facet; facet = facet->Next) {
      enumeration.items_misc.push_back(facet->Data);
    }
  }
  size_t value_size = value.items_with_value.size(); //Used to check changes
Elemer Lelik's avatar
Elemer Lelik committed
696
  enumeration.modified = false;
Elemer Lelik's avatar
Elemer Lelik committed
697
698
699
700
701
702
703
704
  for (List<Mstring>::iterator itemMisc = enumeration.items_misc.begin(); itemMisc; itemMisc = itemMisc->Next) {
    size_t act_size = value.items_with_value.size(); //Used to detect if field did not match any field
    for (List<ComplexType*>::iterator field = found_CT->complexfields.begin(); field; field = field->Next) {
      if (isIntegerType(field->Data->getType().convertedValue)) {
        int read_chars = -1;
        int val = -1;
        sscanf(itemMisc->Data.c_str(), "%d%n", &val, &read_chars);
        if ((size_t) read_chars == itemMisc->Data.size()) {
Elemer Lelik's avatar
Elemer Lelik committed
705
          expstring_t tmp_string = mprintf("{%s:=%d}",
Elemer Lelik's avatar
Elemer Lelik committed
706
            field->Data->getName().convertedValue.c_str(), val);
Elemer Lelik's avatar
Elemer Lelik committed
707
          value.items_with_value.push_back(Mstring(tmp_string));
708
          Free(tmp_string);
Elemer Lelik's avatar
Elemer Lelik committed
709
          break;
Elemer Lelik's avatar
Elemer Lelik committed
710
        }
Elemer Lelik's avatar
Elemer Lelik committed
711
712
713
714
715
716
717
      }

      if (isFloatType(field->Data->getType().convertedValue)) {
        int read_chars = -1;
        float val = -1.0;
        sscanf(itemMisc->Data.c_str(), "%f%n", &val, &read_chars);
        if ((size_t) read_chars == itemMisc->Data.size()) {
Elemer Lelik's avatar
Elemer Lelik committed
718
          expstring_t tmp_string = mprintf("{%s:=%f}",
Elemer Lelik's avatar
Elemer Lelik committed
719
            field->Data->getName().convertedValue.c_str(), val);
Elemer Lelik's avatar
Elemer Lelik committed
720
          value.items_with_value.push_back(Mstring(tmp_string));
721
          Free(tmp_string);
Elemer Lelik's avatar
Elemer Lelik committed
722
          break;
Elemer Lelik's avatar
Elemer Lelik committed
723
724
        }
      }
Elemer Lelik's avatar
Elemer Lelik committed
725
726
727

      if (isTimeType(field->Data->getType().convertedValue)) {
        if (matchDates(itemMisc->Data.c_str(), field->Data->getType().originalValueWoPrefix.c_str())) {
Elemer Lelik's avatar
Elemer Lelik committed
728
729
730
          expstring_t tmp_string = mprintf("{%s:=\"%s\"}",
            field->Data->getName().convertedValue.c_str(), itemMisc->Data.c_str());
          value.items_with_value.push_back(Mstring(tmp_string));
731
          Free(tmp_string);
Elemer Lelik's avatar
Elemer Lelik committed
732
          break;
Elemer Lelik's avatar
Elemer Lelik committed
733
734
        }
      }
Elemer Lelik's avatar
Elemer Lelik committed
735
736
737
738
739

      if (isStringType(field->Data->getType().convertedValue)) {
        expstring_t tmp_string = mprintf("{%s:=\"%s\"}",
          field->Data->getName().convertedValue.c_str(), itemMisc->Data.c_str());
        value.items_with_value.push_back(Mstring(tmp_string));
740
        Free(tmp_string);
Elemer Lelik's avatar
Elemer Lelik committed
741
742
743
744
745
746
747
748
        break;
      }
    }

    if (act_size == value.items_with_value.size()) {
      printWarning(getModule()->getSchemaname(), getName().convertedValue,
        Mstring("The following enumeration did not match any field: ") + itemMisc->Data + Mstring("."));
      TTCN3ModuleInventory::getInstance().incrNumWarnings();
Elemer Lelik's avatar
Elemer Lelik committed
749
750
751
    }
  }

Elemer Lelik's avatar
Elemer Lelik committed
752
753
754
755
  if (value_size != value.items_with_value.size()) {
    value.modified = true;
  }
}
Elemer Lelik's avatar
Elemer Lelik committed
756

Elemer Lelik's avatar
Elemer Lelik committed
757
758
759
760
761
762
763
764
765
766
767
void SimpleType::nameConversion(NameConversionMode conversion_mode, const List<NamespaceType> & ns) {
  if(!visible) return;
  switch (conversion_mode) {
    case nameMode:
      nameConversion_names();
      break;
    case typeMode:
      nameConversion_types(ns);
      break;
    case fieldMode:
      break;
Elemer Lelik's avatar
Elemer Lelik committed
768
769
770
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
771
void SimpleType::nameConversion_names() {
Elemer Lelik's avatar
Elemer Lelik committed
772
  Mstring res, var(module->getTargetNamespace());
773
  XSDName2TTCN3Name(name.convertedValue, empty_string, TTCN3ModuleInventory::getInstance().getTypenames(), type_name, res, var);
Elemer Lelik's avatar
Elemer Lelik committed
774
775
  name.convertedValue = res;
  addVariant(V_onlyValue, var);
776
  for (List<RootType*>::iterator st = nameDepList.begin(); st; st = st->Next) {
777
    st->Data->setTypeValueWoPrefix(res);
Elemer Lelik's avatar
Elemer Lelik committed
778
  }
779
780
781
782
783
784
  if (outside_reference.get_ref() != NULL && defaultForEmptyConstant!= NULL) {
    // We don't know if the name conversion already happened on the get_ref()
    // so we push defaultForEmptyConstant to it's namedeplist.
    defaultForEmptyConstant->setTypeValue(outside_reference.get_ref()->getType().convertedValue);
    outside_reference.get_ref()->getNameDepList().push_back(defaultForEmptyConstant);
  }
Elemer Lelik's avatar
Elemer Lelik committed
785
786
}

Elemer Lelik's avatar
Elemer Lelik committed
787
void SimpleType::nameConversion_types(const List<NamespaceType> & ns) {
Elemer Lelik's avatar
Elemer Lelik committed
788
  if (type.convertedValue == "record" || type.convertedValue == "set"
Elemer Lelik's avatar
Elemer Lelik committed
789
    || type.convertedValue == "union" || type.convertedValue == "enumerated") return;
Elemer Lelik's avatar
Elemer Lelik committed
790

Elemer Lelik's avatar
Elemer Lelik committed
791
  Mstring prefix = type.convertedValue.getPrefix(':');
Elemer Lelik's avatar
Elemer Lelik committed
792
793
794
  Mstring value_str = type.convertedValue.getValueWithoutPrefix(':');

  Mstring uri;
Elemer Lelik's avatar
Elemer Lelik committed
795
  for (List<NamespaceType>::iterator namesp = ns.begin(); namesp; namesp = namesp->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
796
797
798
799
800
801
802
803
804
    if (prefix == namesp->Data.prefix) {
      uri = namesp->Data.uri;
      break;
    }
  }

  QualifiedName tmp(uri, value_str);

  QualifiedNames::iterator origTN = TTCN3ModuleInventory::getInstance().getTypenames().begin();
Elemer Lelik's avatar
Elemer Lelik committed
805
  for (; origTN; origTN = origTN->Next) {
Elemer Lelik's avatar
Elemer Lelik committed
806
807
808
809
810
811
812
813
814
815
816
817
818
    if (tmp == origTN->Data) {
      QualifiedName tmp_name(module->getTargetNamespace(), name.convertedValue);
      if (tmp_name == origTN->Data)
        continue; // get a new type name
      else
        break;
    }
  }
  if (origTN != NULL) {
    setTypeValue(origTN->Data.name);
    // This      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
    // The only effect here is to remove the "xs:" prefix from type.convertedValue,
    // otherwise the new value is always the same as the old.
Elemer Lelik's avatar
Elemer Lelik committed
819
  } else {
Elemer Lelik's avatar
Elemer Lelik committed
820
    Mstring res, var;
821
    XSDName2TTCN3Name(value_str, uri, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var);
Elemer Lelik's avatar
Elemer Lelik committed
822
823
824
825
    setTypeValue(res);
  }
}

Elemer Lelik's avatar
Elemer Lelik committed
826
void SimpleType::finalModification() {
Elemer Lelik's avatar
Elemer Lelik committed
827
828
829
830
831
832
833
834
835
  value.applyFacets();
  length.applyFacets();
  pattern.applyFacet();
  whitespace.applyFacet();
  enumeration.applyFacets();

  if (module->getElementFormDefault() == qualified &&
    element_form_as == unqualified) {
    addVariant(V_formAs, Mstring("unqualified"));
Elemer Lelik's avatar
Elemer Lelik committed
836
837
838
  } else if (module->getElementFormDefault() != qualified &&
    element_form_as == qualified) {
    addVariant(V_formAs, Mstring("qualified"));
Elemer Lelik's avatar
Elemer Lelik committed
839
  }
Elemer Lelik's avatar
Elemer Lelik committed
840

Elemer Lelik's avatar
Elemer Lelik committed
841
842
843
  if (module->getAttributeFormDefault() == qualified &&
    attribute_form_as == unqualified) {
    addVariant(V_formAs, Mstring("unqualified"));
Elemer Lelik's avatar
Elemer Lelik committed
844
845
846
847
848
849
850
851
852
853
  } else if (module->getAttributeFormDefault() != qualified &&
    attribute_form_as == qualified) {
    addVariant(V_formAs, Mstring("qualified"));
  }

  if (type.originalValueWoPrefix == Mstring("boolean")) {
    addVariant(V_onlyValueHidden, Mstring("\"text 'false' as '0'\""));
    addVariant(V_onlyValueHidden, Mstring("\"text 'true' as '1'\""));
  }

854
  isOptional = isOptional || (getMinOccurs() == 0 && getMaxOccurs() == 0);
855
856
857
858
859
860
861
  

}

void SimpleType::finalModification2() {
  // Delayed adding the defaultForEmpty variant after the nameconversion
  // happened on the constants
862
  if (defaultForEmptyConstant != NULL && !defaultForEmptyConstant->isUnsupported()) {
863
864
865
    TTCN3Module * mod = parent != NULL ? parent->getModule() : getModule();
    addVariant(V_defaultForEmpty, defaultForEmptyConstant->getAlterego()->getConstantName(mod));
  }
Elemer Lelik's avatar
Elemer Lelik committed
866
867
}

Elemer Lelik's avatar
Elemer Lelik committed
868
869
bool SimpleType::hasUnresolvedReference() {
  if (!outside_reference.empty() && !outside_reference.is_resolved()) {
Elemer Lelik's avatar
Elemer Lelik committed
870
    return true;
Elemer Lelik's avatar
Elemer Lelik committed
871
  } else {
Elemer Lelik's avatar
Elemer Lelik committed
872
    return false;
Elemer Lelik's avatar
Elemer Lelik committed
873
  }
Elemer Lelik's avatar
Elemer Lelik committed
874
875
}

876
877
878
879
void SimpleType::modifyList() {
  // Intentional empty
}

Elemer Lelik's avatar
Elemer Lelik committed
880
881
882
883
884
885
void SimpleType::applyRefAttribute(const Mstring& ref_value) {
  if (!ref_value.empty()) {
    setReference(ref_value);
    fromRef = true;
  }
}
Elemer Lelik's avatar
Elemer Lelik committed
886

887
888
889
890
891
892
893
894
895
bool SimpleType::hasRestrictionOrExtension() const {
  return
    enumeration.modified ||
    length.modified ||
    value.modified ||
    pattern.modified ||
    whitespace.modified;
}

896
897
898
899
900
901
902
903
904
 ComplexType * SimpleType::getMainType() {
    ComplexType * par = parent;
    if (par == NULL) return NULL;
    while (par->parent != NULL) {
      par = par->parent;
    }
    return par;
  }

Elemer Lelik's avatar
Elemer Lelik committed
905
906
907
908
void SimpleType::printToFile(FILE * file) {
  if (!visible) {
    return;
  }
Elemer Lelik's avatar
Elemer Lelik committed
909
910
911
912

  printComment(file);

  fputs("type ", file);
Elemer Lelik's avatar
Elemer Lelik committed
913
914
915
916
917
918
919
  if(enumeration.modified && hasVariant(Mstring("\"list\""))){
    printMinOccursMaxOccurs(file, false);
    fprintf(file, "enumerated\n{\n");
    enumeration.sortFacets();
    enumeration.printToFile(file);
    fprintf(file, "\n} %s", name.convertedValue.c_str());
  } else if (enumeration.modified) {
Elemer Lelik's avatar
Elemer Lelik committed
920
921
922
923
924
    if (isFloatType(builtInBase)) {
      fprintf(file, "%s %s (", type.convertedValue.c_str(), name.convertedValue.c_str());
      enumeration.sortFacets();
      enumeration.printToFile(file);
      fputc(')', file);
Elemer Lelik's avatar
Elemer Lelik committed
925
    } else {
Elemer Lelik's avatar
Elemer Lelik committed
926
927
928
929
930
      fprintf(file, "enumerated %s\n{\n", name.convertedValue.c_str());
      enumeration.sortFacets();
      enumeration.printToFile(file);
      fputs("\n}", file);
    }
Elemer Lelik's avatar
Elemer Lelik committed
931
  } else {
Elemer Lelik's avatar
Elemer Lelik committed
932
933
934
935
    printMinOccursMaxOccurs(file, false);

    int multiplicity = multi(module, outside_reference, this);
    const RootType *type_ref = outside_reference.get_ref();
936
937
    if ((multiplicity > 1 && type_ref && type_ref->getModule() != module)
       || name.convertedValue == type.convertedValue) {
Elemer Lelik's avatar
Elemer Lelik committed
938
939
940
941
942
943
944
945
946
      fprintf(file, "%s.", type_ref->getModule()->getModulename().c_str());
    }

    fprintf(file, "%s %s",
      type.convertedValue.c_str(), name.convertedValue.c_str());
    pattern.printToFile(file);
    value.printToFile(file);
    length.printToFile(file);
  }
Elemer Lelik's avatar
Elemer Lelik committed
947
  enumeration.insertVariants();
Elemer Lelik's avatar
Elemer Lelik committed
948
949
950
951
  printVariant(file);
  fputs(";\n\n\n", file);
}

Elemer Lelik's avatar
Elemer Lelik committed
952
void SimpleType::dump(unsigned int depth) const {
Elemer Lelik's avatar
Elemer Lelik committed
953
  static const char *modes[] = {
954
    "", "restriction", "extension", "list", "restrictionAfterList"
Elemer Lelik's avatar
Elemer Lelik committed
955
956
957
  };
  fprintf(stderr, "%*s SimpleType '%s' -> '%s' at %p\n", depth * 2, "",
    name.originalValueWoPrefix.c_str(), name.convertedValue.c_str(),
Elemer Lelik's avatar
Elemer Lelik committed
958
    (const void*) this);
Elemer Lelik's avatar
Elemer Lelik committed
959
960
961
962
963
964
965
  fprintf(stderr, "%*s   type '%s' -> '%s'\n", depth * 2, "",
    type.originalValueWoPrefix.c_str(), type.convertedValue.c_str());

  if (mode != noMode) {
    fprintf(stderr, "%*s   %s, base='%s'\n", depth * 2, "", modes[mode], builtInBase.c_str());
  }

Elemer Lelik's avatar
Elemer Lelik committed
966
967
  //  fprintf  (stderr, "%*s   rfo='%s' n_d='%s'\n", depth * 2, "",
  //    reference_for_other.c_str(), name_dependency.c_str());
Elemer Lelik's avatar
Elemer Lelik committed
968
969
970
971
972
973
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LengthType::LengthType(SimpleType * a_simpleType)
: parent(a_simpleType)
Elemer Lelik's avatar
Elemer Lelik committed
974
975
976
977
978
979
980
, modified(false)
, facet_minLength(0)
, facet_maxLength(ULLONG_MAX)
, lower(0)
, upper(ULLONG_MAX) {
}

981
void LengthType::applyReference(const LengthType & other) { 
Elemer Lelik's avatar
Elemer Lelik committed
982
983
984
985
986
987
988
989
990
  if (!modified) modified = other.modified;
  if (other.facet_minLength > facet_minLength) facet_minLength = other.facet_minLength;
  if (other.facet_maxLength < facet_maxLength) facet_maxLength = other.facet_maxLength;
}

void LengthType::applyFacets() // only for string types and list types without QName
{
  if (!modified) return;

Elemer Lelik's avatar
Elemer Lelik committed
991
992
  switch (parent->getMode()) {
    case SimpleType::restrictionMode:
Elemer Lelik's avatar
Elemer Lelik committed
993
    {
Elemer Lelik's avatar
Elemer Lelik committed
994
995
996
997
998
999
1000
      const Mstring & base = parent->getBuiltInBase();
      if ((isStringType(base) || (isSequenceType(base) && base != "QName") || isAnyType(base)) || base.empty()) {
        lower = facet_minLength;
        upper = facet_maxLength;
      } else {
        printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
          Mstring("Length restriction is not supported on type '") + base + Mstring("'."));
For faster browsing, not all history is shown. View entire blame