xsd2ttcn: fixed error when reading XMLSchema.xsd (Bug 495653)
[deliverable/titan.core.git] / xsdconvert / SimpleType.cc
CommitLineData
d44e3c4f 1/******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * >
10 * Balasko, Jeno
11 * Beres, Szabolcs
12 * Godar, Marton
13 * Raduly, Csaba
14 * Szabo, Bence Janos
15 *
16 ******************************************************************************/
970ed795
EL
17#include "SimpleType.hh"
18
19#include "GeneralFunctions.hh"
20
21#include "TTCN3ModuleInventory.hh"
22#include "TTCN3Module.hh"
23#include "ComplexType.hh"
970ed795 24
3abe9331 25extern bool g_flag_used;
51fa56b9 26extern bool h_flag_used;
970ed795
EL
27
28SimpleType::SimpleType(XMLParser * a_parser, TTCN3Module * a_module, ConstructType a_construct)
29: RootType(a_parser, a_module, a_construct)
3abe9331 30, builtInBase()
31, length(this)
32, pattern(this)
33, enumeration(this)
34, whitespace(this)
35, value(this)
36, element_form_as(notset)
37, attribute_form_as(notset)
38, mode(noMode)
39, outside_reference()
40, in_name_only(false)
41, fromRef(false)
42, xsdtype(n_NOTSET)
43, isOptional(false)
51fa56b9 44, substitutionGroup(empty_string)
3abe9331 45, subsGroup(NULL)
51fa56b9 46, typeSubsGroup(NULL)
47, addedToTypeSubstitution(false)
3abe9331 48, block(not_set)
49, parent(NULL) {
50}
970ed795
EL
51
52SimpleType::SimpleType(const SimpleType& other)
53: RootType(other)
3abe9331 54, builtInBase(other.builtInBase)
55, length(other.length)
56, pattern(other.pattern)
57, enumeration(other.enumeration)
58, whitespace(other.whitespace)
59, value(other.value)
60, element_form_as(other.element_form_as)
61, attribute_form_as(other.attribute_form_as)
62, mode(other.mode)
63, outside_reference(other.outside_reference)
64, in_name_only(other.in_name_only)
65, fromRef(other.fromRef)
66, xsdtype(other.xsdtype)
67, isOptional(other.isOptional)
51fa56b9 68, substitutionGroup(other.substitutionGroup)
3abe9331 69, subsGroup(other.subsGroup)
51fa56b9 70, typeSubsGroup(other.typeSubsGroup)
71, addedToTypeSubstitution(other.addedToTypeSubstitution)
3abe9331 72, block(other.block)
73, parent(NULL) {
970ed795
EL
74 length.parent = this;
75 pattern.parent = this;
76 enumeration.parent = this;
77 whitespace.p_parent = this;
78 value.parent = this;
79}
80
3abe9331 81void SimpleType::loadWithValues() {
970ed795 82 const XMLParser::TagAttributes & atts = parser->getActualTagAttributes();
3abe9331 83 switch (parser->getActualTagName()) {
84 case n_restriction:
85 type.upload(atts.base);
86 setReference(atts.base);
87 mode = restrictionMode;
970ed795 88 break;
3abe9331 89 case n_list:
90 type.upload(atts.itemType);
91 setReference(atts.itemType);
4999ad2e 92 setMinOccurs(0);
93 setMaxOccurs(ULLONG_MAX);
3abe9331 94 addVariant(V_list);
95 mode = listMode;
970ed795 96 break;
3abe9331 97 case n_union:
98 { // generating complextype from simpletype
99 ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagUnion);
100 new_complextype->loadWithValues();
970ed795
EL
101 break;
102 }
3abe9331 103 case n_element:
104 name.upload(atts.name);
105 type.upload(atts.type);
106 setReference(atts.type, true);
107 if (!atts.nillable) {
108 applyDefaultAttribute(atts.default_);
109 applyFixedAttribute(atts.fixed);
110 }
111 applyAbstractAttribute(atts.abstract);
112 applySubstitionGroupAttribute(atts.substitionGroup);
113 applyBlockAttribute(atts.block);
114 //This shall be the last instruction always
115 applyNillableAttribute(atts.nillable);
116 break;
117 case n_attribute:
118 name.upload(atts.name);
119 type.upload(atts.type);
120 xsdtype = n_attribute;
121 setReference(atts.type, true);
122 applyDefaultAttribute(atts.default_);
123 applyFixedAttribute(atts.fixed);
124 break;
125 case n_simpleType:
126 name.upload(atts.name);
127 break;
128 case n_complexType:
129 { // generating complextype from simpletype
130 ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagComplexType);
131 new_complextype->loadWithValues();
132 break;
970ed795 133 }
3abe9331 134 case n_length:
135 if (mode == listMode) {
4999ad2e 136 setMinOccurs(strtoull(atts.value.c_str(), NULL, 0));
137 setMaxOccurs(strtoull(atts.value.c_str(), NULL, 0));
3abe9331 138 break;
139 }
140 length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
141 length.facet_maxLength = strtoull(atts.value.c_str(), NULL, 0);
142 length.modified = true;
143 break;
144 case n_minLength:
145 if (mode == listMode) {
4999ad2e 146 setMinOccurs(strtoull(atts.value.c_str(), NULL, 0));
3abe9331 147 break;
148 }
149 length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
150 length.modified = true;
151 break;
152 case n_maxLength:
153 if (mode == listMode) {
4999ad2e 154 setMaxOccurs(strtoull(atts.value.c_str(), NULL, 0));
3abe9331 155 break;
156 }
157 length.facet_maxLength = strtoull(atts.value.c_str(), NULL, 0);
158 length.modified = true;
159 break;
160 case n_pattern:
161 pattern.facet = atts.value;
162 pattern.modified = true;
163 break;
164 case n_enumeration:
165 enumeration.facets.push_back(atts.value);
166 enumeration.modified = true;
167 break;
168 case n_whiteSpace:
169 whitespace.facet = atts.value;
170 whitespace.modified = true;
171 break;
172 case n_minInclusive:
173 if (atts.value == "NaN") {
174 value.not_a_number = true;
175 } else if (atts.value == "-INF") {
176 value.facet_minInclusive = -DBL_MAX;
177 } else if (atts.value == "INF") {
178 value.facet_minInclusive = DBL_MAX;
179 } else {
180 value.facet_minInclusive = stringToLongDouble(atts.value.c_str());
181 }
182 value.modified = true;
183 break;
184 case n_maxInclusive:
185 if (atts.value == "NaN") {
186 value.not_a_number = true;
187 } else if (atts.value == "-INF") {
188 value.facet_maxInclusive = -DBL_MAX;
189 } else if (atts.value == "INF") {
190 value.facet_maxInclusive = DBL_MAX;
191 } else {
192 value.facet_maxInclusive = stringToLongDouble(atts.value.c_str());
193 }
194 value.modified = true;
195 break;
196 case n_minExclusive:
197 if (atts.value == "NaN") {
198 setInvisible();
199 } else if (atts.value == "-INF") {
200 value.facet_minExclusive = -DBL_MAX;
201 } else if (atts.value == "INF") {
202 setInvisible();
203 } else {
204 value.facet_minExclusive = stringToLongDouble(atts.value.c_str());
205 }
206 value.modified = true;
207 value.lowerExclusive = true;
208 break;
209 case n_maxExclusive:
210 if (atts.value == "NaN") {
211 setInvisible();
212 } else if (atts.value == "-INF") {
213 setInvisible();
214 } else if (atts.value == "INF") {
215 value.facet_maxExclusive = DBL_MAX;
216 } else {
217 value.facet_maxExclusive = stringToLongDouble(atts.value.c_str());
218 }
219 value.modified = true;
220 value.upperExclusive = true;
221 break;
222 case n_totalDigits:
223 value.facet_totalDigits = strtoul(atts.value.c_str(), NULL, 0);
224 value.modified = true;
225 break;
226 case n_fractionDigits:
227 //addVariant(V_fractionDigits, atts.value);
228 break;
229 case n_label:
230 addComment(Mstring("LABEL:"));
231 break;
232 case n_definition:
233 addComment(Mstring("DEFINITION:"));
234 break;
235 default:
236 break;
970ed795
EL
237 }
238}
239
3abe9331 240void SimpleType::applyDefaultAttribute(const Mstring& default_value) {
970ed795
EL
241 if (!default_value.empty()) {
242 value.default_value = default_value;
3abe9331 243 const Mstring nameT = type.originalValueWoPrefix.getValueWithoutPrefix(':');
244 //Not supported for hexBinary and base64Binary
245 if (nameT != "hexBinary" && nameT != "base64Binary") {
246 addVariant(V_defaultForEmpty, default_value);
247 }
970ed795
EL
248 }
249}
250
3abe9331 251void SimpleType::applyFixedAttribute(const Mstring& fixed_value) {
970ed795
EL
252 if (!fixed_value.empty()) {
253 value.fixed_value = fixed_value;
3abe9331 254 value.modified = true;
255 const Mstring nameT = type.originalValueWoPrefix.getValueWithoutPrefix(':');
256 //Not supported for hexBinary and base64Binary
257 if (nameT != "hexBinary" && nameT != "base64Binary") {
258 addVariant(V_defaultForEmpty, fixed_value);
259 }
970ed795
EL
260 }
261}
262
3abe9331 263void SimpleType::applyNillableAttribute(const bool nillable) {
264 if (nillable) {
970ed795
EL
265 ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagNillable); // generating complextype from simpletype
266 new_complextype->loadWithValues();
267 }
268}
269
3abe9331 270void SimpleType::applyAbstractAttribute(const bool abstract_value) {
271 if (abstract_value) {
51fa56b9 272 addVariant(V_abstract);
3abe9331 273 }
274}
275
51fa56b9 276void SimpleType::applySubstitionGroupAttribute(const Mstring& substitution_group){
277 if(!substitution_group.empty()){
278 substitutionGroup = substitution_group;
3abe9331 279 }
280}
281
282void SimpleType::applyBlockAttribute(const BlockValue block_){
283 if(block_ == not_set){
284 block = getModule()->getBlockDefault();
285 }else {
286 block = block_;
287 }
288}
289
290void SimpleType::addToSubstitutions(){
51fa56b9 291 if(!g_flag_used || substitutionGroup.empty()){
3abe9331 292 return;
293 }
51fa56b9 294 SimpleType * st_ = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(this, substitutionGroup, want_BOTH);
3abe9331 295 if(st_ == NULL){
296 printError(module->getSchemaname(), name.convertedValue,
51fa56b9 297 "Reference for a non-defined type: " + substitutionGroup);
3abe9331 298 TTCN3ModuleInventory::getInstance().incrNumErrors();
3abe9331 299 return;
300 }
301 SimpleType * st = (SimpleType*)st_;
302 if(st->getSubstitution() != NULL){
303 st = st->getSubstitution();
304 }
305
306 st->referenceResolving();
51fa56b9 307 substitutionGroup = empty_string;
3abe9331 308 //Simpletype
309 if(st->subsGroup == NULL){
51fa56b9 310 ComplexType * head_element = new ComplexType(*st, ComplexType::fromTagSubstitution);
3abe9331 311 for(List<SimpleType*>::iterator simpletype = st->nameDepList.begin(); simpletype; simpletype = simpletype->Next){
51fa56b9 312 head_element->getNameDepList().push_back(simpletype->Data);
3abe9331 313 }
314 st->nameDepList.clear();
315 st->getModule()->addMainType(head_element);
316 head_element->addVariant(V_untagged);
317 head_element->addSubstitution(st);
318 head_element->addSubstitution(this);
319 //if st->subsGroup == this, then it is a generated subs group
320 st->subsGroup = head_element;
321 st->setInvisible();
322 }else {
323 st->subsGroup->addSubstitution(this);
324 }
325}
326
51fa56b9 327void SimpleType::addToTypeSubstitutions() {
328 //If the user did not request type substitution generation or
329 //the type is already added to type substitution
330 if(!h_flag_used || addedToTypeSubstitution){
331 return;
332 }
333 //Only available if it is a restricion or extension
334 if(mode != extensionMode && mode != restrictionMode){
335 return;
336 }
337 //Only top level complexTypes or simpleTypes, ergo no elements
338 if(parent != NULL || hasVariant(Mstring("\"element\""))){
339 return;
340 }
341
342 //It would be nice if here outside_reference.resolved to everything
51fa56b9 343 bool newST = false;
3f84031e 344 SimpleType * st = (SimpleType*)outside_reference.get_ref();
51fa56b9 345 if(st == NULL && !isBuiltInType(type.convertedValue)){
346 //Not even a reference, and not a built in type
347 return;
348 }else if(st == NULL && isBuiltInType(type.convertedValue)){
349 st = new SimpleType(parser, module, construct);
350 st->type.upload(type.convertedValue);
351 st->name.upload(type.convertedValue);
352 st->typeSubsGroup = findBuiltInTypeInStoredTypeSubstitutions(type.convertedValue);
3f84031e 353 outside_reference.set_resolved(st);
354 //Add this decoy type to the maintypes -> module will free st
355 //st->setInvisible();
356 module->addMainType(st);
51fa56b9 357 newST = true;
358 }
359
360 addedToTypeSubstitution = true;
3f84031e 361 st->addToTypeSubstitutions();
51fa56b9 362 //If type substitution is NULL then we need to create the union
363 if(st->getTypeSubstitution() == NULL){
364 ComplexType * head_element = new ComplexType(*st, ComplexType::fromTypeSubstitution);
3f84031e 365 head_element->getNameDepList().clear();
366 for(List<SimpleType*>::iterator simpletype = st->nameDepList.begin(), nextST; simpletype; simpletype = nextST){
367 nextST = simpletype->Next;
368 //Don't add if it is in a type substitution
369 if(simpletype->Data->getTypeSubstitution() == NULL){
370 head_element->getNameDepList().push_back(simpletype->Data);
371 st->getNameDepList().remove(simpletype);
372 }
51fa56b9 373 }
3f84031e 374
51fa56b9 375 st->getModule()->addMainType(head_element);
376 head_element->addVariant(V_useType);
3f84031e 377 //For cascading type substitution
378 if(st->outside_reference.get_ref() != NULL && ((ComplexType*)st->outside_reference.get_ref())->getTypeSubstitution() != NULL){
379 head_element->setParentTypeSubsGroup(((ComplexType*)st->outside_reference.get_ref())->getTypeSubstitution());
380 }
51fa56b9 381 head_element->addTypeSubstitution(st);
382 head_element->addTypeSubstitution(this);
383 bool found = false;
384 //Check to find if there was already an element reference with this type
385 for(List<typeNameDepList>::iterator str = module->getElementTypes().begin(); str; str = str->Next){
386 Mstring prefix = str->Data.type.getPrefix(':');
3f84031e 387 Mstring value_ = str->Data.type.getValueWithoutPrefix(':');
51fa56b9 388
3f84031e 389 if((value_ == st->getName().convertedValue.getValueWithoutPrefix(':') && prefix == module->getTargetNamespaceConnector()) ||
390 (isBuiltInType(value_) && !isBuiltInType(st->getType().convertedValue) && value_ == st->getType().convertedValue && prefix == module->getTargetNamespaceConnector())){
51fa56b9 391 //Push the namedeplist
392 for(List<SimpleType*>::iterator simpletype = str->Data.nameDepList.begin(); simpletype; simpletype = simpletype->Next){
393 head_element->getNameDepList().push_back(simpletype->Data);
394 }
395 found = true;
396 str->Data.typeSubsGroup = head_element;
397 break;
398 }
399 }
400 if(!found){
401 head_element->setInvisible();
402 }
403 st->typeSubsGroup = head_element;
404 st->getModule()->addStoredTypeSubstitution(head_element);
405 }else {
406 st->getTypeSubstitution()->addTypeSubstitution(this);
407 }
51fa56b9 408 if(newST){
3f84031e 409 //Make the decoy invisible
410 st->setInvisible();
51fa56b9 411 }
412}
413
414void SimpleType::collectElementTypes(SimpleType* found_ST, ComplexType* found_CT){
415 //Only if type substitution is enabled and it is a top level(simpletype) element or
416 //it is a not top level element(complextype)
417 if(h_flag_used && (hasVariant(Mstring("\"element\"")) || xsdtype == n_element)){
418 SimpleType * st = NULL, *nameDep = NULL;
3f84031e 419 Mstring uri, value_, type_;
51fa56b9 420 if(found_ST != NULL || found_CT != NULL){
421 // st := found_ST or found_CT, which is not null
422 st = found_ST != NULL ? found_ST : found_CT;
423 uri = outside_reference.get_uri();
3f84031e 424 value_ = outside_reference.get_val();
425 type_ = value_;
51fa56b9 426 }else if(isBuiltInType(type.convertedValue)){
427 st = this;
428 uri = module->getTargetNamespace();
3f84031e 429 value_ = type.convertedValue;
51fa56b9 430 if(outside_reference.empty()){
3f84031e 431 type_ = value_;
51fa56b9 432 nameDep = this;
433 }else {
434 type_ = outside_reference.get_val();
435 }
436 }else {
437 //It is not possible to reach here (should be)
438 return;
439 }
440 type_ = type_.getValueWithoutPrefix(':');
441 bool found = false;
3f84031e 442 const Mstring typeSubsName = value_ + Mstring("_derivations");
51fa56b9 443 //Find if we already have a substitution type to this element reference
444 for(List<ComplexType*>::iterator complex = st->getModule()->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next){
445
446 if(uri == st->getModule()->getTargetNamespace() && typeSubsName == complex->Data->getName().convertedValue){
447 complex->Data->setVisible();
448 if(st->getXsdtype() != n_NOTSET && this == st){ //otherwise records would be renamed too
449 complex->Data->addToNameDepList(st);
450 ((ComplexType*)st)->setNameDep(nameDep);
451 }
452 found = true;
453 break;
454 }
455 }
456 //Add the reference, to future possible type substitution
457 if(!found){
458 Mstring prefix = st->getModule()->getTargetNamespaceConnector();
459 if(prefix != empty_string){
460 prefix += ":";
461 }
462 st->getModule()->addElementType(prefix + type_, nameDep);
463 }
464 }
465}
466
467ComplexType * SimpleType::findBuiltInTypeInStoredTypeSubstitutions(const Mstring& builtInType){
468 const Mstring typeSubsName = builtInType.getValueWithoutPrefix(':') + Mstring("_derivations");
469 for(List<ComplexType*>::iterator complex = module->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next){
470 if(typeSubsName == complex->Data->getName().convertedValue){
471 return complex->Data;
472 }
473 }
474 return NULL;
475}
476
477
3abe9331 478void SimpleType::setReference(const Mstring& ref, bool only_name_dependency) {
970ed795
EL
479 if (ref.empty()) {
480 return;
481 }
482 if (isBuiltInType(ref)) {
483 builtInBase = ref.getValueWithoutPrefix(':');
3abe9331 484 if (name.convertedValue.empty()) {
485 name.upload(ref);
486 }
487 if (type.convertedValue.empty() || type.convertedValue == "anySimpleType") {
488 type.upload(ref.getValueWithoutPrefix(':'));
489 }
490 fromRef = true;
970ed795
EL
491 return;
492 }
493
494 Mstring refPrefix = ref.getPrefix(':');
495 Mstring refValue = ref.getValueWithoutPrefix(':');
496 Mstring refUri;
497 // Find the URI amongst the known namespace URIs
498 List<NamespaceType>::iterator declNS;
3abe9331 499 for (declNS = module->getDeclaredNamespaces().begin(); declNS; declNS = declNS->Next) {
970ed795
EL
500 if (refPrefix == declNS->Data.prefix) {
501 refUri = declNS->Data.uri;
502 break;
503 }
504 }
505
506 // FIXME: can this part be moved above the search ?
507 if (refUri.empty()) { // not found
508 if (refPrefix == "xml") {
509 refUri = "http://www.w3.org/XML/1998/namespace";
3abe9331 510 } else if (refPrefix == "xmlns") {
970ed795 511 refUri = "http://www.w3.org/2000/xmlns";
3abe9331 512 } else if (refPrefix.empty() && module->getTargetNamespace() == "NoTargetNamespace") {
970ed795
EL
513 refUri = "NoTargetNamespace";
514 }
515 }
516
517 if (refUri.empty()) { // something is incorrect - unable to find the uri to the given prefix
518 if (refPrefix.empty()) {
519 printError(module->getSchemaname(), parser->getActualLineNumber(),
520 Mstring("The absent namespace must be imported because "
3abe9331 521 "it is not the same as the target namespace of the current schema."));
970ed795
EL
522 parser->incrNumErrors();
523 return;
3abe9331 524 } else {
970ed795
EL
525 printError(module->getSchemaname(), parser->getActualLineNumber(),
526 "The value \'" + ref + "\' is incorrect: "
527 "A namespace prefix does not denote any URI.");
528 parser->incrNumErrors();
529 return;
530 }
531 }
532
533 if (only_name_dependency) {
970ed795
EL
534 in_name_only = true;
535 }
536
970ed795
EL
537 outside_reference.load(refUri, refValue, &declNS->Data);
538}
539
3abe9331 540void SimpleType::referenceResolving() {
3f84031e 541 if (outside_reference.empty() || outside_reference.is_resolved()){
51fa56b9 542 addToTypeSubstitutions();
543 collectElementTypes();
544 }
545 if(outside_reference.empty() && substitutionGroup.empty()) return;
970ed795
EL
546 if (outside_reference.is_resolved()) return;
547
3abe9331 548 if(!outside_reference.empty()){
549 SimpleType * found_ST = static_cast<SimpleType*> (
550 TTCN3ModuleInventory::getInstance().lookup(this, want_ST));
551 ComplexType * found_CT = static_cast<ComplexType*> (
552 TTCN3ModuleInventory::getInstance().lookup(this, want_CT));
553 // It _is_ possible to find both
51fa56b9 554 collectElementTypes(found_ST, found_CT);
3abe9331 555 if (found_ST != NULL) {
556 if (!found_ST->outside_reference.empty() && !found_ST->outside_reference.is_resolved() && found_ST != this) {
3abe9331 557 found_ST->referenceResolving();
3f84031e 558 if(!found_ST->outside_reference.is_resolved()){
559 found_ST->outside_reference.set_resolved(NULL);
560 }
3abe9331 561 }
562 referenceForST(found_ST);
51fa56b9 563 addToTypeSubstitutions();
3abe9331 564 if (!isBuiltInType(type.convertedValue)) {
565 found_ST->addToNameDepList(this);
566 }
567 } else if (found_CT != NULL) {
568 referenceForCT(found_CT);
51fa56b9 569 addToTypeSubstitutions();
3abe9331 570 if (!isBuiltInType(type.convertedValue)) {
571 found_CT->addToNameDepList(this);
572 }
573 }else {
574 printError(module->getSchemaname(), name.convertedValue,
575 "Reference for a non-defined type: " + outside_reference.repr());
576 TTCN3ModuleInventory::getInstance().incrNumErrors();
577 outside_reference.set_resolved(NULL);
578 }
51fa56b9 579 addToSubstitutions();
580 }else {
3abe9331 581 addToSubstitutions();
970ed795
EL
582 }
583}
584
3abe9331 585void SimpleType::referenceForST(SimpleType * found_ST) {
970ed795
EL
586 outside_reference.set_resolved(found_ST);
587
588 if (in_name_only)
589 return;
590
591 if (construct == c_element)
592 return;
593
594 if (mode == listMode)
595 return;
596
3abe9331 597 if (!found_ST->builtInBase.empty()) {
598 builtInBase = found_ST->builtInBase;
599 }
970ed795
EL
600
601 length.applyReference(found_ST->length);
602 pattern.applyReference(found_ST->pattern);
603 enumeration.applyReference(found_ST->enumeration);
604 whitespace.applyReference(found_ST->whitespace);
605 value.applyReference(found_ST->value);
606
607 mode = found_ST->mode;
3abe9331 608 if (found_ST->mode != listMode) {
609 type.upload(found_ST->getType().convertedValue);
610 }
970ed795
EL
611}
612
3abe9331 613void SimpleType::referenceForCT(ComplexType * found_CT) {
970ed795
EL
614 outside_reference.set_resolved(found_CT);
615
616 if (in_name_only)
617 return;
618
3abe9331 619 // Section 7.5.3 Example5
620 if (found_CT->getType().convertedValue == Mstring("union") && mode == restrictionMode) {
621 for (List<Mstring>::iterator facet = enumeration.facets.begin(); facet; facet = facet->Next) {
622 enumeration.items_misc.push_back(facet->Data);
623 }
624 }
625 size_t value_size = value.items_with_value.size(); //Used to check changes
970ed795 626 enumeration.modified = false;
3abe9331 627 for (List<Mstring>::iterator itemMisc = enumeration.items_misc.begin(); itemMisc; itemMisc = itemMisc->Next) {
628 size_t act_size = value.items_with_value.size(); //Used to detect if field did not match any field
629 for (List<ComplexType*>::iterator field = found_CT->complexfields.begin(); field; field = field->Next) {
630 if (isIntegerType(field->Data->getType().convertedValue)) {
631 int read_chars = -1;
632 int val = -1;
633 sscanf(itemMisc->Data.c_str(), "%d%n", &val, &read_chars);
634 if ((size_t) read_chars == itemMisc->Data.size()) {
970ed795 635 expstring_t tmp_string = mprintf("{%s:=%d}",
3abe9331 636 field->Data->getName().convertedValue.c_str(), val);
970ed795 637 value.items_with_value.push_back(Mstring(tmp_string));
3abe9331 638 break;
970ed795 639 }
3abe9331 640 }
641
642 if (isFloatType(field->Data->getType().convertedValue)) {
643 int read_chars = -1;
644 float val = -1.0;
645 sscanf(itemMisc->Data.c_str(), "%f%n", &val, &read_chars);
646 if ((size_t) read_chars == itemMisc->Data.size()) {
970ed795 647 expstring_t tmp_string = mprintf("{%s:=%f}",
3abe9331 648 field->Data->getName().convertedValue.c_str(), val);
970ed795 649 value.items_with_value.push_back(Mstring(tmp_string));
3abe9331 650 break;
970ed795
EL
651 }
652 }
3abe9331 653
654 if (isTimeType(field->Data->getType().convertedValue)) {
655 if (matchDates(itemMisc->Data.c_str(), field->Data->getType().originalValueWoPrefix.c_str())) {
970ed795
EL
656 expstring_t tmp_string = mprintf("{%s:=\"%s\"}",
657 field->Data->getName().convertedValue.c_str(), itemMisc->Data.c_str());
658 value.items_with_value.push_back(Mstring(tmp_string));
3abe9331 659 break;
970ed795
EL
660 }
661 }
3abe9331 662
663 if (isStringType(field->Data->getType().convertedValue)) {
664 expstring_t tmp_string = mprintf("{%s:=\"%s\"}",
665 field->Data->getName().convertedValue.c_str(), itemMisc->Data.c_str());
666 value.items_with_value.push_back(Mstring(tmp_string));
667 break;
668 }
669 }
670
671 if (act_size == value.items_with_value.size()) {
672 printWarning(getModule()->getSchemaname(), getName().convertedValue,
673 Mstring("The following enumeration did not match any field: ") + itemMisc->Data + Mstring("."));
674 TTCN3ModuleInventory::getInstance().incrNumWarnings();
970ed795
EL
675 }
676 }
970ed795 677
3abe9331 678 if (value_size != value.items_with_value.size()) {
679 value.modified = true;
680 }
681}
970ed795 682
3abe9331 683void SimpleType::nameConversion(NameConversionMode conversion_mode, const List<NamespaceType> & ns) {
684 if(!visible) return;
685 switch (conversion_mode) {
686 case nameMode:
687 nameConversion_names();
688 break;
689 case typeMode:
690 nameConversion_types(ns);
691 break;
692 case fieldMode:
693 break;
970ed795
EL
694 }
695}
696
3abe9331 697void SimpleType::nameConversion_names() {
970ed795
EL
698 Mstring res, var(module->getTargetNamespace());
699 XSDName2TTCN3Name(name.convertedValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_name, res, var);
700 name.convertedValue = res;
701 addVariant(V_onlyValue, var);
702 for (List<SimpleType*>::iterator st = nameDepList.begin(); st; st = st->Next) {
703 st->Data->setTypeValue(res);
704 }
705}
706
3abe9331 707void SimpleType::nameConversion_types(const List<NamespaceType> & ns) {
970ed795 708 if (type.convertedValue == "record" || type.convertedValue == "set"
3abe9331 709 || type.convertedValue == "union" || type.convertedValue == "enumerated") return;
970ed795 710
3abe9331 711 Mstring prefix = type.convertedValue.getPrefix(':');
970ed795
EL
712 Mstring value_str = type.convertedValue.getValueWithoutPrefix(':');
713
714 Mstring uri;
3abe9331 715 for (List<NamespaceType>::iterator namesp = ns.begin(); namesp; namesp = namesp->Next) {
970ed795
EL
716 if (prefix == namesp->Data.prefix) {
717 uri = namesp->Data.uri;
718 break;
719 }
720 }
721
722 QualifiedName tmp(uri, value_str);
723
724 QualifiedNames::iterator origTN = TTCN3ModuleInventory::getInstance().getTypenames().begin();
3abe9331 725 for (; origTN; origTN = origTN->Next) {
970ed795
EL
726 if (tmp == origTN->Data) {
727 QualifiedName tmp_name(module->getTargetNamespace(), name.convertedValue);
728 if (tmp_name == origTN->Data)
729 continue; // get a new type name
730 else
731 break;
732 }
733 }
734 if (origTN != NULL) {
735 setTypeValue(origTN->Data.name);
736 // This ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
737 // The only effect here is to remove the "xs:" prefix from type.convertedValue,
738 // otherwise the new value is always the same as the old.
3abe9331 739 } else {
970ed795
EL
740 Mstring res, var;
741 XSDName2TTCN3Name(value_str, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var);
742 setTypeValue(res);
743 }
744}
745
3abe9331 746void SimpleType::finalModification() {
970ed795
EL
747 value.applyFacets();
748 length.applyFacets();
749 pattern.applyFacet();
750 whitespace.applyFacet();
751 enumeration.applyFacets();
752
753 if (module->getElementFormDefault() == qualified &&
754 element_form_as == unqualified) {
755 addVariant(V_formAs, Mstring("unqualified"));
3abe9331 756 } else if (module->getElementFormDefault() != qualified &&
757 element_form_as == qualified) {
758 addVariant(V_formAs, Mstring("qualified"));
970ed795 759 }
3abe9331 760
970ed795
EL
761 if (module->getAttributeFormDefault() == qualified &&
762 attribute_form_as == unqualified) {
763 addVariant(V_formAs, Mstring("unqualified"));
3abe9331 764 } else if (module->getAttributeFormDefault() != qualified &&
765 attribute_form_as == qualified) {
766 addVariant(V_formAs, Mstring("qualified"));
767 }
768
769 if (type.originalValueWoPrefix == Mstring("boolean")) {
770 addVariant(V_onlyValueHidden, Mstring("\"text 'false' as '0'\""));
771 addVariant(V_onlyValueHidden, Mstring("\"text 'true' as '1'\""));
772 }
773
4999ad2e 774 isOptional = isOptional || (getMinOccurs() == 0 && getMaxOccurs() == 0);
3abe9331 775
776 // If the type name is the same as the identifier then we have to prefix it
777 // with the module identifier.
778 if (type.convertedValue == name.convertedValue && !outside_reference.empty()) {
779 List<const TTCN3Module*>::iterator import_module = module->getImportedModules().begin();
780 for (; import_module; import_module = import_module->Next) {
781 if (import_module->Data->getTargetNamespace() == outside_reference.get_uri()) {
782 type.upload(import_module->Data->getModulename() + Mstring(".") + type.convertedValue);
783 break;
784 }
785 }
970ed795
EL
786 }
787}
788
3abe9331 789bool SimpleType::hasUnresolvedReference() {
790 if (!outside_reference.empty() && !outside_reference.is_resolved()) {
970ed795 791 return true;
3abe9331 792 } else {
970ed795 793 return false;
3abe9331 794 }
970ed795
EL
795}
796
3abe9331 797void SimpleType::applyRefAttribute(const Mstring& ref_value) {
798 if (!ref_value.empty()) {
799 setReference(ref_value);
800 fromRef = true;
801 }
802}
970ed795 803
3abe9331 804void SimpleType::printToFile(FILE * file) {
805 if (!visible) {
806 return;
807 }
970ed795
EL
808
809 printComment(file);
810
811 fputs("type ", file);
3abe9331 812 if(enumeration.modified && hasVariant(Mstring("\"list\""))){
813 printMinOccursMaxOccurs(file, false);
814 fprintf(file, "enumerated\n{\n");
815 enumeration.sortFacets();
816 enumeration.printToFile(file);
817 fprintf(file, "\n} %s", name.convertedValue.c_str());
818 } else if (enumeration.modified) {
970ed795
EL
819 if (isFloatType(builtInBase)) {
820 fprintf(file, "%s %s (", type.convertedValue.c_str(), name.convertedValue.c_str());
821 enumeration.sortFacets();
822 enumeration.printToFile(file);
823 fputc(')', file);
3abe9331 824 } else {
970ed795
EL
825 fprintf(file, "enumerated %s\n{\n", name.convertedValue.c_str());
826 enumeration.sortFacets();
827 enumeration.printToFile(file);
828 fputs("\n}", file);
829 }
3abe9331 830 } else {
970ed795
EL
831 printMinOccursMaxOccurs(file, false);
832
833 int multiplicity = multi(module, outside_reference, this);
834 const RootType *type_ref = outside_reference.get_ref();
835 if ((multiplicity > 1) && type_ref
836 && type_ref->getModule() != module) {
837 fprintf(file, "%s.", type_ref->getModule()->getModulename().c_str());
838 }
839
840 fprintf(file, "%s %s",
841 type.convertedValue.c_str(), name.convertedValue.c_str());
842 pattern.printToFile(file);
843 value.printToFile(file);
844 length.printToFile(file);
845 }
3abe9331 846 enumeration.insertVariants();
970ed795
EL
847 printVariant(file);
848 fputs(";\n\n\n", file);
849}
850
3abe9331 851void SimpleType::dump(unsigned int depth) const {
970ed795
EL
852 static const char *modes[] = {
853 "", "restriction", "extension", "list"
854 };
855 fprintf(stderr, "%*s SimpleType '%s' -> '%s' at %p\n", depth * 2, "",
856 name.originalValueWoPrefix.c_str(), name.convertedValue.c_str(),
3abe9331 857 (const void*) this);
970ed795
EL
858 fprintf(stderr, "%*s type '%s' -> '%s'\n", depth * 2, "",
859 type.originalValueWoPrefix.c_str(), type.convertedValue.c_str());
860
861 if (mode != noMode) {
862 fprintf(stderr, "%*s %s, base='%s'\n", depth * 2, "", modes[mode], builtInBase.c_str());
863 }
864
3abe9331 865 // fprintf (stderr, "%*s rfo='%s' n_d='%s'\n", depth * 2, "",
866 // reference_for_other.c_str(), name_dependency.c_str());
970ed795
EL
867}
868
869/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
870
871LengthType::LengthType(SimpleType * a_simpleType)
872: parent(a_simpleType)
3abe9331 873, modified(false)
874, facet_minLength(0)
875, facet_maxLength(ULLONG_MAX)
876, lower(0)
877, upper(ULLONG_MAX) {
878}
879
880void LengthType::applyReference(const LengthType & other) {
970ed795
EL
881 if (!modified) modified = other.modified;
882 if (other.facet_minLength > facet_minLength) facet_minLength = other.facet_minLength;
883 if (other.facet_maxLength < facet_maxLength) facet_maxLength = other.facet_maxLength;
884}
885
886void LengthType::applyFacets() // only for string types and list types without QName
887{
888 if (!modified) return;
889
3abe9331 890 switch (parent->getMode()) {
891 case SimpleType::restrictionMode:
970ed795 892 {
3abe9331 893 const Mstring & base = parent->getBuiltInBase();
894 if ((isStringType(base) || (isSequenceType(base) && base != "QName") || isAnyType(base)) || base.empty()) {
895 lower = facet_minLength;
896 upper = facet_maxLength;
897 } else {
898 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
899 Mstring("Length restriction is not supported on type '") + base + Mstring("'."));
900 TTCN3ModuleInventory::getInstance().incrNumWarnings();
901 }
902 break;
903 }
904 case SimpleType::extensionMode:
905 case SimpleType::listMode:
970ed795
EL
906 lower = facet_minLength;
907 upper = facet_maxLength;
3abe9331 908 break;
909 case SimpleType::noMode:
910 break;
970ed795
EL
911 }
912 if (lower > upper) {
913 printError(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
914 Mstring("The upper boundary of length restriction cannot be smaller than the lower boundary."));
915 TTCN3ModuleInventory::getInstance().incrNumErrors();
916 return;
917 }
918}
919
3abe9331 920void LengthType::printToFile(FILE * file) const {
970ed795
EL
921 if (!modified) return;
922 if (parent->getEnumeration().modified) return;
923
3abe9331 924 if (lower == upper) {
970ed795 925 fprintf(file, " length(%llu)", lower);
3abe9331 926 } else {
970ed795
EL
927 fprintf(file, " length(%llu .. ", lower);
928
3abe9331 929 if (upper == ULLONG_MAX) {
970ed795 930 fputs("infinity", file);
3abe9331 931 } else {
970ed795
EL
932 fprintf(file, "%llu", upper);
933 }
934
935 fputc(')', file);
936 }
937}
938
939/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
940
941PatternType::PatternType(SimpleType * a_simpleType)
942: parent(a_simpleType)
3abe9331 943, modified(false)
944, facet()
945, value() {
946}
970ed795 947
3abe9331 948void PatternType::applyReference(const PatternType & other) {
970ed795
EL
949 if (!modified) modified = other.modified;
950 if (facet.empty()) facet = other.facet;
951}
952
953void PatternType::applyFacet() // only for time types and string types without hexBinary
954{
955 if (!modified) return;
956
957 const Mstring & base = parent->getBuiltInBase();
3abe9331 958 if (((isStringType(base) && base != "hexBinary") || isTimeType(base) || isAnyType(base)) || base.empty()) {
970ed795
EL
959 // XSD pattern to TTCN-3 pattern; ETSI ES 201 873-9 clause 6.1.4
960 // FIXME a proper scanner is needed, e.g. from flex
961 int charclass = 0;
3abe9331 962 for (size_t i = 0; i != facet.size(); ++i) {
970ed795
EL
963 char c = facet[i];
964 switch (c) {
3abe9331 965 case '(':
966 value += charclass ? "\\("
967 : "(";
970ed795 968 break;
3abe9331 969 case ')':
970 value += charclass ? "\\)"
971 : ")";
970ed795 972 break;
3abe9331 973 case '/':
974 value += '/';
970ed795 975 break;
3abe9331 976 case '^':
977 value += charclass ? "\\^"
978 : "^";
970ed795 979 break;
3abe9331 980 case '[':
981 value += c;
982 ++charclass;
970ed795 983 break;
3abe9331 984 case ']':
985 value += c;
986 --charclass;
970ed795 987 break;
3abe9331 988 case '.': // any character
989 value += charclass ? '.'
990 : '?';
970ed795 991 break;
3abe9331 992 case '*': // 0 or more
993 value += '*'; //#(0,)
970ed795 994 break;
3abe9331 995 case '+':
996 value += '+'; //#(1,)
970ed795 997 break;
3abe9331 998 case '?':
999 value += charclass ? "?"
1000 : "#(0,1)";
970ed795 1001 break;
3abe9331 1002 case '"':
1003 value += "\"\"";
3f84031e 1004 break;
3abe9331 1005 case '{':
1006 {
1007 if (charclass == 0) {
1008 Mstring s;
1009 int k = 1;
1010 while (facet[i + k] != '}') {
1011 s += facet[i + k];
1012 ++k;
1013 }
1014 int a, b, match;
1015 match = sscanf(s.c_str(), "%i,%i", &a, &b);
1016 if (match == 1 || match == 2) {
1017 value += "#(";
1018 value += s;
1019 value += ')';
1020 i = i + k;
1021 } else {
1022 value += "\\{";
1023 }
1024 } else {
1025 value += "\\{";
970ed795 1026 }
3abe9331 1027 break;
1028 }
1029 case '}':
1030 value += charclass ? "\\}"
1031 : "}";
1032 break;
1033 case '\\':
1034 {
1035 // Appendix G1.1 of XML Schema Datatypes: Character class escapes;
1036 // specifically, http://www.w3.org/TR/xmlschema11-2/#nt-MultiCharEsc
1037 char cn = facet[i + 1];
1038 switch (cn) {
1039 case 'c':
1040 value += charclass ? "\\w\\d.\\-_:"
1041 : "[\\w\\d.\\-_:]";
1042 break;
1043 case 'C':
1044 value += charclass ? "^\\w\\d.\\-_:"
1045 : "[^\\w\\d.\\-_:]";
1046 break;
1047 case 'D':
1048 value += charclass ? "^\\d"
1049 : "[^\\d]";
1050 break;
1051 case 'i':
1052 value += charclass ? "\\w\\d:"
1053 : "[\\w\\d:]";
1054 break;
1055 case 'I':
1056 value += charclass ? "^\\w\\d:"
1057 : "[^\\w\\d:]";
1058 break;
1059 case 's':
1060 value += charclass ? "\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1061 : "[\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1062 break;
1063 case 'S':
1064 value += charclass ? "^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1065 : "[^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1066 break;
1067 case 'W':
1068 value += charclass ? "^\\w"
1069 : "[^\\w]";
1070 break;
1071 case 'p':
1072 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1073 Mstring("Character categories and blocks are not supported."));
1074 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1075 parent->addComment(
1076 Mstring("Pattern is not converted due to using character categories and blocks in patterns is not supported."));
1077 value.clear();
1078 return;
1079
1080 case '.':
1081 value += '.';
1082 break;
1083 default:
1084 // backslash + another: pass unmodified; this also handles \d and \w
1085 value += c;
1086 value += cn;
1087 break;
970ed795 1088 }
3abe9331 1089 ++i;
1090 break;
970ed795 1091 }
3abe9331 1092 case '&':
1093 if (facet[i + 1] == '#') { // &#....;
1094 Mstring s;
1095 int k = 2;
1096 while (facet[i + k] != ';') {
1097 s += facet[i + k];
1098 ++k;
1099 }
1100 long long int d = atoll(s.c_str());
1101 if (d < 0 || d > 2147483647) {
1102 printError(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1103 Mstring("Invalid unicode character."));
1104 TTCN3ModuleInventory::getInstance().incrNumErrors();
1105 }
1106 unsigned char group = (d >> 24) & 0xFF;
1107 unsigned char plane = (d >> 16) & 0xFF;
1108 unsigned char row = (d >> 8) & 0xFF;
1109 unsigned char cell = d & 0xFF;
1110
1111 expstring_t res = mprintf("\\q{%d, %d, %d, %d}", group, plane, row, cell);
1112 value += res;
1113 Free(res);
1114 i = i + k;
1115 }
1116 // else fall through
1117 default: //just_copy:
1118 value += c;
1119 break;
970ed795
EL
1120 } // switch(c)
1121 } // next i
3abe9331 1122 } else {
970ed795
EL
1123 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1124 Mstring("Pattern restriction is not supported on type '") + base + Mstring("'."));
1125 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1126 }
1127}
1128
3abe9331 1129void PatternType::printToFile(FILE * file) const {
970ed795
EL
1130 if (!modified || value.empty()) return;
1131 if (parent->getEnumeration().modified) return;
1132
1133 fprintf(file, " (pattern \"%s\")", value.c_str());
1134}
1135
1136/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1137
1138EnumerationType::EnumerationType(SimpleType * a_simpleType)
1139: parent(a_simpleType)
1140, modified(false)
1141, facets()
1142, items_string()
1143, items_int()
1144, items_float()
1145, items_time()
1146, items_misc()
3abe9331 1147, variants() {
1148}
970ed795 1149
3abe9331 1150void EnumerationType::applyReference(const EnumerationType & other) {
970ed795 1151 if (!modified) modified = other.modified;
233d2d31 1152 if ((other.parent->getXsdtype() == n_NOTSET && parent->getMode() != SimpleType::restrictionMode)
1153 || parent->getXsdtype() == n_simpleType) {
1154 for (List<Mstring>::iterator facet = other.facets.begin(); facet; facet = facet->Next) {
1155 facets.push_back(facet->Data);
1156 }
970ed795
EL
1157 }
1158}
1159
1160void EnumerationType::applyFacets() // string types, integer types, float types, time types
1161{
1162 if (!modified) return;
1163
3abe9331 1164 facets.remove_dups();
1165
970ed795
EL
1166 const Mstring & base = parent->getBuiltInBase();
1167
1168 if (isStringType(base)) // here length restriction is applicable
1169 {
1170 List<Mstring> text_variants;
3abe9331 1171 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
970ed795 1172 const LengthType & length = parent->getLength();
3abe9331 1173 if (length.lower <= facet->Data.size() && facet->Data.size() <= length.upper) {
970ed795
EL
1174 Mstring res, var;
1175 XSDName2TTCN3Name(facet->Data, items_string, enum_id_name, res, var);
1176 text_variants.push_back(var);
1177 }
1178 }
1179 text_variants.sort();
1180 for (List<Mstring>::iterator var = text_variants.end(); var; var = var->Prev) {
3abe9331 1181 variants.push_back(var->Data);
970ed795 1182 }
3abe9331 1183 } else if (isIntegerType(base)) // here value restriction is applicable
970ed795 1184 {
3abe9331 1185 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
970ed795
EL
1186 int int_value = atoi(facet->Data.c_str());
1187 const ValueType & value = parent->getValue();
3abe9331 1188 if (value.lower <= int_value && int_value <= value.upper) {
970ed795 1189 bool found = false;
3abe9331 1190 for (List<int>::iterator itemInt = items_int.begin(); itemInt; itemInt = itemInt->Next) {
970ed795
EL
1191 if (int_value == itemInt->Data) {
1192 found = true;
1193 break;
1194 }
1195 }
1196 if (!found) items_int.push_back(int_value);
1197
3abe9331 1198 if (variants.empty() || variants.back() != "\"useNumber\"") {
1199 variants.push_back(Mstring("\"useNumber\""));
970ed795
EL
1200 }
1201 }
1202 }
3abe9331 1203 } else if (isFloatType(base)) // here value restriction is applicable
970ed795 1204 {
3abe9331 1205 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
970ed795
EL
1206 double float_value = atof(facet->Data.c_str());
1207 const ValueType & value = parent->getValue();
3abe9331 1208 if (value.lower <= float_value && float_value <= value.upper) {
970ed795 1209 bool found = false;
3abe9331 1210 for (List<double>::iterator itemFloat = items_float.begin(); itemFloat; itemFloat = itemFloat->Next) {
970ed795
EL
1211 if (float_value == itemFloat->Data) {
1212 found = true;
1213 break;
1214 }
1215 }
1216 if (!found) {
1217 items_float.push_back(float_value);
970ed795
EL
1218 }
1219 }
1220 }
3abe9331 1221 } else if (isTimeType(base)) {
970ed795 1222 List<Mstring> text_variants;
3abe9331 1223 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
970ed795
EL
1224 Mstring res, var;
1225 XSDName2TTCN3Name(facet->Data, items_time, enum_id_name, res, var);
1226 text_variants.push_back(var);
1227 }
1228 text_variants.sort();
1229 for (List<Mstring>::iterator var = text_variants.end(); var; var = var->Prev) {
3abe9331 1230 variants.push_back(var->Data);
970ed795 1231 }
3abe9331 1232 } else if (isAnyType(base)) {
1233 } else if (base.empty()) {
1234 } else {
970ed795
EL
1235 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1236 Mstring("Enumeration restriction is not supported on type '") + base + Mstring("'."));
1237 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1238 parent->setInvisible();
1239 }
1240}
1241
3abe9331 1242void EnumerationType::sortFacets() {
970ed795
EL
1243 items_string.sort();
1244 items_int.sort();
1245 items_float.sort();
1246 items_time.sort();
1247}
1248
3abe9331 1249void EnumerationType::printToFile(FILE * file, unsigned int indent_level) const {
970ed795
EL
1250 if (!modified) return;
1251
1252 const Mstring & base = parent->getBuiltInBase();
3abe9331 1253 if (isStringType(base)) {
1254 for (QualifiedNames::iterator itemString = items_string.begin(); itemString; itemString = itemString->Next) {
970ed795
EL
1255 if (itemString != items_string.begin()) fputs(",\n", file);
1256 for (unsigned int l = 0; l != indent_level; ++l) fputs("\t", file);
1257 fprintf(file, "\t%s", itemString->Data.name.c_str());
1258 }
3abe9331 1259 } else if (isIntegerType(base)) {
1260 for (List<int>::iterator itemInt = items_int.begin(); itemInt; itemInt = itemInt->Next) {
970ed795
EL
1261 if (itemInt != items_int.begin()) fputs(",\n", file);
1262 for (unsigned int l = 0; l != indent_level; ++l) fputs("\t", file);
1263 if (itemInt->Data < 0) {
1264 fprintf(file, "\tint_%d(%d)", abs(itemInt->Data), itemInt->Data);
3abe9331 1265 } else {
970ed795
EL
1266 fprintf(file, "\tint%d(%d)", itemInt->Data, itemInt->Data);
1267 }
1268 }
3abe9331 1269 } else if (isFloatType(base)) {
1270 for (List<double>::iterator itemFloat = items_float.begin(); itemFloat; itemFloat = itemFloat->Next) {
970ed795
EL
1271 if (itemFloat != items_float.begin()) fputs(", ", file);
1272
1273 double intpart = 0;
1274 double fracpart = 0;
1275 fracpart = modf(itemFloat->Data, &intpart);
1276 if (fracpart == 0) {
3abe9331 1277 fprintf(file, "%lld.0", (long long int) (itemFloat->Data));
1278 } else {
970ed795
EL
1279 fprintf(file, "%g", itemFloat->Data);
1280 }
1281 }
3abe9331 1282 } else if (isTimeType(base)) {
1283 for (QualifiedNames::iterator itemTime = items_time.begin(); itemTime; itemTime = itemTime->Next) {
970ed795
EL
1284 if (itemTime != items_time.begin()) fputs(",\n", file);
1285 for (unsigned int l = 0; l != indent_level; ++l) fputs("\t", file);
1286 fprintf(file, "\t%s", itemTime->Data.name.c_str());
1287 }
1288 }
1289}
1290
3abe9331 1291void EnumerationType::insertVariants(){
1292 if(!modified) return;
1293
1294 Mstring pre_connector = empty_string;
1295 if(parent->getMinOccurs() == 0 && parent->getMaxOccurs() == ULLONG_MAX){
1296 pre_connector = "([-]) ";
1297 }
1298 for(List<Mstring>::iterator var = variants.begin(); var; var = var->Next){
1299 parent->addVariant(V_onlyValue, pre_connector + var->Data);
1300 }
1301}
1302
970ed795
EL
1303/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1304
1305WhitespaceType::WhitespaceType(SimpleType * a_simpleType)
1306: p_parent(a_simpleType)
1307, modified(false)
1308, facet()
3abe9331 1309, value() {
1310}
970ed795 1311
3abe9331 1312void WhitespaceType::applyReference(const WhitespaceType & other) {
970ed795
EL
1313 if (!modified) modified = other.modified;
1314 if (facet.empty()) facet = other.facet;
1315}
1316
1317void WhitespaceType::applyFacet() // only for string types: string, normalizedString, token, Name, NCName, language
1318{
1319 if (!modified) return;
1320
1321 const Mstring & base = p_parent->getBuiltInBase();
1322 if (base == "string" || base == "normalizedString" || base == "token" || base == "language" ||
3abe9331 1323 base == "Name" || base == "NCName" || isAnyType(base) || base.empty()) {
970ed795 1324 p_parent->addVariant(V_whiteSpace, facet);
3abe9331 1325 } else {
970ed795
EL
1326 printWarning(p_parent->getModule()->getSchemaname(), p_parent->getName().convertedValue,
1327 Mstring("Facet 'whiteSpace' is not applicable for type '") + base + Mstring("'."));
1328 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1329 }
1330}
1331
1332ValueType::ValueType(SimpleType * a_simpleType)
1333: parent(a_simpleType)
1334, modified(false)
1335, facet_minInclusive(-DBL_MAX)
1336, facet_maxInclusive(DBL_MAX)
1337, facet_minExclusive(-DBL_MAX)
1338, facet_maxExclusive(DBL_MAX)
3abe9331 1339, facet_totalDigits(-1)
970ed795
EL
1340, lower(-DBL_MAX)
1341, upper(DBL_MAX)
1342, lowerExclusive(false)
1343, upperExclusive(false)
3abe9331 1344, not_a_number(false)
970ed795
EL
1345, fixed_value()
1346, default_value()
3abe9331 1347, items_with_value() {
1348}
970ed795 1349
3abe9331 1350void ValueType::applyReference(const ValueType & other) {
1351 if (!modified) {
1352 modified = other.modified;
1353 }
1354 if (not_a_number) {
1355 return;
1356 }
1357 if (other.not_a_number) not_a_number = true;
970ed795
EL
1358 if (other.facet_minInclusive > facet_minInclusive) facet_minInclusive = other.facet_minInclusive;
1359 if (other.facet_maxInclusive < facet_maxInclusive) facet_maxInclusive = other.facet_maxInclusive;
1360 if (other.facet_minExclusive > facet_minExclusive) facet_minExclusive = other.facet_minExclusive;
1361 if (other.facet_maxExclusive < facet_maxExclusive) facet_maxExclusive = other.facet_maxExclusive;
3f84031e 1362 if (other.upperExclusive) upperExclusive = other.upperExclusive;
1363 if (other.lowerExclusive) lowerExclusive = other.lowerExclusive;
3abe9331 1364 //-1 in case when it is not modified
1365 if (other.facet_totalDigits < facet_totalDigits || facet_totalDigits == -1) facet_totalDigits = other.facet_totalDigits;
1366 if (!other.default_value.empty()) {
1367 default_value = other.default_value;
1368 parent->addVariant(V_defaultForEmpty, default_value);
1369 }
1370 if (!other.fixed_value.empty()) {
1371 fixed_value = other.fixed_value;
1372 parent->addVariant(V_defaultForEmpty, fixed_value);
1373 }
970ed795
EL
1374}
1375
1376void ValueType::applyFacets() // only for integer and float types
1377{
3abe9331 1378 if (!modified) {
1379 return;
1380 }
1381
1382 if (not_a_number) {
1383 return;
1384 }
970ed795
EL
1385
1386 const Mstring & base = parent->getBuiltInBase();
1387 /*
1388 * Setting of default value range of built-in types
1389 */
3abe9331 1390 if (base == "positiveInteger") {
970ed795 1391 lower = 1;
3abe9331 1392 } else if (base == "nonPositiveInteger") {
970ed795 1393 upper = 0;
3abe9331 1394 } else if (base == "negativeInteger") {
970ed795 1395 upper = -1;
3abe9331 1396 } else if (base == "nonNegativeInteger") {
970ed795 1397 lower = 0;
3abe9331 1398 } else if (base == "unsignedLong") {
970ed795
EL
1399 lower = 0;
1400 upper = ULLONG_MAX;
3abe9331 1401 } else if (base == "int") {
970ed795
EL
1402 lower = INT_MIN;
1403 upper = INT_MAX;
3abe9331 1404 } else if (base == "unsignedInt") {
970ed795
EL
1405 lower = 0;
1406 upper = UINT_MAX;
3abe9331 1407 } else if (base == "short") {
970ed795
EL
1408 lower = SHRT_MIN;
1409 upper = SHRT_MAX;
3abe9331 1410 } else if (base == "unsignedShort") {
970ed795
EL
1411 lower = 0;
1412 upper = USHRT_MAX;
3abe9331 1413 } else if (base == "byte") {
970ed795
EL
1414 lower = CHAR_MIN;
1415 upper = CHAR_MAX;
3abe9331 1416 } else if (base == "unsignedByte") {
970ed795
EL
1417 lower = 0;
1418 upper = UCHAR_MAX;
1419 }
1420
3abe9331 1421 if (isIntegerType(base)) {
970ed795
EL
1422 if (facet_minInclusive != -DBL_MAX && facet_minInclusive > lower) lower = facet_minInclusive;
1423 if (facet_maxInclusive != DBL_MAX && upper > facet_maxInclusive) upper = facet_maxInclusive;
1424 if (facet_minExclusive != -DBL_MAX && lower < facet_minExclusive) lower = facet_minExclusive;
1425 if (facet_maxExclusive != DBL_MAX && upper > facet_maxExclusive) upper = facet_maxExclusive;
3abe9331 1426 } else if (isFloatType(base)) {
970ed795
EL
1427 if (facet_minInclusive != -DBL_MAX && lower < facet_minInclusive) lower = facet_minInclusive;
1428 if (facet_maxInclusive != DBL_MAX && upper > facet_maxInclusive) upper = facet_maxInclusive;
1429 if (facet_minExclusive != -DBL_MAX && lower < facet_minExclusive) lower = facet_minExclusive;
1430 if (facet_maxExclusive != DBL_MAX && upper > facet_maxExclusive) upper = facet_maxExclusive;
3abe9331 1431 } else if (isAnyType(base) || isTimeType(base) || isBooleanType(base)) {
1432 } else if (isStringType(base) && (
1433 base.getValueWithoutPrefix(':') != "hexBinary" && base.getValueWithoutPrefix(':') != "base64Binary")) {
1434 } else if (base.empty()) {
1435 } else {
970ed795
EL
1436 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1437 Mstring("Value restriction is not supported on type '") + base + Mstring("'."));
1438 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1439 }
1440
1441 // totalDigits facet is only for integer types and decimal
3abe9331 1442 if (facet_totalDigits > 0) // if this facet is used
970ed795
EL
1443 {
1444 double r = pow(10.0, facet_totalDigits);
1445
3abe9331 1446 if (base == "integer") {
1447 lower = (int) -(r - 1);
1448 upper = (int) (r - 1);
1449 } else if (base == "positiveInteger") {
970ed795 1450 lower = 1;
3abe9331 1451 upper = (int) (r - 1);
1452 } else if (base == "nonPositiveInteger") {
1453 lower = (int) -(r - 1);
970ed795 1454 upper = 0;
3abe9331 1455 } else if (base == "negativeInteger") {
1456 lower = (int) -(r - 1);
970ed795 1457 upper = -1;
3abe9331 1458 } else if (base == "nonNegativeInteger") {
970ed795 1459 lower = 0;
3abe9331 1460 upper = (int) (r - 1);
1461 } else if (base == "long" ||
970ed795
EL
1462 base == "unsignedLong" ||
1463 base == "int" ||
1464 base == "unsignedInt" ||
1465 base == "short" ||
1466 base == "unsignedShort" ||
1467 base == "byte" ||
3abe9331 1468 base == "unsignedByte") {
1469 lower = (int) -(r - 1);
1470 upper = (int) (r - 1);
1471 } else if (base == "decimal") {
1472 lower = (int) -(r - 1);
1473 upper = (int) (r - 1);
1474 } else {
970ed795
EL
1475 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1476 Mstring("Facet 'totalDigits' is not applicable for type '") + base + Mstring("'."));
1477 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1478 }
1479 }
3abe9331 1480 items_with_value.sort();
970ed795
EL
1481}
1482
3abe9331 1483void ValueType::printToFile(FILE * file) const {
970ed795
EL
1484 if (!modified) return;
1485 if (parent->getEnumeration().modified) return;
1486
3abe9331 1487 if (not_a_number) {
1488 fprintf(file, " ( not_a_number )");
970ed795
EL
1489 return;
1490 }
3abe9331 1491 if (!fixed_value.empty()) {
1492 //Base64binary and hexbyte does not supported
1493 Mstring type;
1494 if(isBuiltInType(parent->getType().originalValueWoPrefix)){
1495 type = parent->getType().originalValueWoPrefix;
1496 }else {
1497 type = getPrefixByNameSpace(parent, parent->getReference().get_uri()) + Mstring(":") + parent->getReference().get_val();
1498 }
1499 if(!isBuiltInType(type)){
1500 type = findBuiltInType(parent, type);
1501 }
1502 if (isStringType(type) || isTimeType(type) || isQNameType(type) || isAnyType(type)) {
1503 const Mstring& name = type.getValueWithoutPrefix(':');
1504 if (name != "hexBinary" && name != "base64Binary") {
1505 fprintf(file, " (\"%s\")", fixed_value.c_str());
1506 }
1507 } else if (isBooleanType(type)) {
1508 Mstring val;
1509 if (fixed_value == "1") {
1510 val = "true";
1511 } else if (fixed_value == "0") {
1512 val = "false";
1513 } else {
1514 val = fixed_value;
1515 }
1516 fprintf(file, " (%s)", val.c_str());
1517 } else {
1518 fprintf(file, " (%s)", fixed_value.c_str());
1519 }
1520 return;
1521 }
1522 if (!items_with_value.empty()) {
1523 fputs(" (\n", file);
1524 for (List<Mstring>::iterator itemWithValue = items_with_value.begin(); itemWithValue; itemWithValue = itemWithValue->Next) {
1525 fprintf(file, "\t%s", itemWithValue->Data.c_str());
1526 if (itemWithValue != items_with_value.end()) {
1527 fputs(",\n", file);
1528 } else {
1529 fputs("\n", file);
1530 }
970ed795
EL
1531 }
1532 fputc(')', file);
1533 return;
1534 }
1535
1536 if (lower == -DBL_MAX && upper == DBL_MAX) return;
1537
1538 fputs(" (", file);
1539
3abe9331 1540 if (isIntegerType(parent->getBuiltInBase())) {
970ed795
EL
1541 if (lowerExclusive) {
1542 fputc('!', file);
1543 }
1544
3abe9331 1545 if (lower == -DBL_MAX) {
970ed795 1546 fputs("-infinity", file);
3abe9331 1547 } else if (lower < 0) {
970ed795
EL
1548 long double temp_lower = -lower;
1549 fprintf(file, "-%.0Lf", temp_lower);
3abe9331 1550 } else {
970ed795
EL
1551 fprintf(file, "%.0Lf", lower);
1552 }
1553
1554 fputs(" .. ", file);
1555 if (upperExclusive) {
1556 fputc('!', file);
1557 }
1558
3abe9331 1559 if (upper == DBL_MAX) {
970ed795 1560 fputs("infinity", file);
3abe9331 1561 } else if (upper < 0) {
970ed795
EL
1562 long double temp_upper = -upper;
1563 fprintf(file, "-%.0Lf", temp_upper);
3abe9331 1564 } else {
970ed795
EL
1565 fprintf(file, "%.0Lf", upper);
1566 }
3abe9331 1567 } else if (isFloatType(parent->getBuiltInBase())) {
970ed795
EL
1568 if (lowerExclusive) {
1569 fputc('!', file);
1570 }
1571
3abe9331 1572 if (lower == -DBL_MAX) {
970ed795 1573 fputs("-infinity", file);
3abe9331 1574 } else {
970ed795
EL
1575 double intpart = 0;
1576 double fracpart = 0;
1577 fracpart = modf(lower, &intpart);
1578 if (fracpart == 0) {
1579 fprintf(file, "%.1Lf", lower);
3abe9331 1580 } else {
970ed795
EL
1581 fprintf(file, "%Lg", lower);
1582 }
1583 }
1584
1585 fputs(" .. ", file);
1586 if (upperExclusive) {
1587 fputc('!', file);
1588 }
1589
3abe9331 1590 if (upper == DBL_MAX) {
970ed795 1591 fputs("infinity", file);
3abe9331 1592 } else {
970ed795
EL
1593 double intpart = 0;
1594 double fracpart = 0;
1595 fracpart = modf(upper, &intpart);
1596 if (fracpart == 0) {
1597 fprintf(file, "%.1Lf", upper);
3abe9331 1598 } else {
970ed795
EL
1599 fprintf(file, "%Lg", upper);
1600 }
1601 }
1602 }
1603
1604 fputc(')', file);
1605}
This page took 0.093667 seconds and 5 git commands to generate.