Commit 4999ad2e authored by ebensza's avatar ebensza
Browse files

xsd2ttcn: fixed error when reading XMLSchema.xsd (Bug 495653)


Signed-off-by: default avatarebensza <bence.janos.szabo@ericsson.com>
parent 6f35ed15
/*******************************************************************************
* Copyright (c) 2000-2016 Ericsson Telecom AB
*
* XSD to TTCN-3 Translator version: CRL 113 200/5 R4A
*
* 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
*******************************************************************************/
//
// File: http_www_example_org_2001_XMLSchema_e.ttcn
// Description:
// References:
// Rev:
// Prodnr:
// Updated: Mon Jun 13 09:08:10 2015
// Contact: http://ttcn.ericsson.se
//
////////////////////////////////////////////////////////////////////////////////
// Generated from file(s):
// - MyXMLSchema.xsd
// /* xml version = "1.0" encoding = "UTF-8" */
// /* targetnamespace = "http://www.example.org/2001/XMLSchema/e" */
////////////////////////////////////////////////////////////////////////////////
// Modification header(s):
//-----------------------------------------------------------------------------
// Modified by:
// Modification date:
// Description:
// Modification contact:
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
module http_www_example_org_2001_XMLSchema {
import from XSD all;
type record AttrDecls
{
record of union {
XSD.String attribute,
XSD.String attributeGroup
} choice_list
}
with {
variant "untagged";
variant (choice_list) "untagged";
variant (choice_list[-]) "untagged";
};
type record OpenAttrs
{
record of XSD.String attr optional
}
with {
variant "name as uncapitalized";
variant (attr) "anyAttributes except unqualified, 'http://www.example.org/2001/XMLSchema'";
};
type record Annotated
{
record of XSD.String attr optional,
XSD.String asd optional
}
with {
variant "name as uncapitalized";
variant (attr) "anyAttributes except unqualified, 'http://www.example.org/2001/XMLSchema'";
};
type union TypeDefParticle
{
XSD.String group_
}
with {
variant "untagged";
variant (group_) "name as 'group'";
};
type record RestrictionType
{
record of XSD.String attr optional,
XSD.String asd optional,
union {
TypeDefParticle typeDefParticle
} choice optional,
record of union {
XSD.String attribute,
XSD.String attributeGroup
} choice_list
}
with {
variant "name as uncapitalized";
variant (attr) "anyAttributes except unqualified, 'http://www.example.org/2001/XMLSchema'";
variant (choice) "untagged";
variant (choice_list) "untagged";
variant (choice_list[-]) "untagged";
};
type record ComplexRestrictionType
{
record of XSD.String attr optional,
union {
TypeDefParticle typeDefParticle
} choice,
record of union {
XSD.String attribute,
XSD.String attributeGroup
} choice_list
}
with {
variant "name as uncapitalized";
variant (attr) "anyAttributes except unqualified, 'http://www.example.org/2001/XMLSchema'";
variant (choice) "untagged";
variant (choice_list) "untagged";
variant (choice_list[-]) "untagged";
};
}
with {
encode "XML";
variant "namespace as 'http://www.example.org/2001/XMLSchema' prefix 'a'";
variant "controlNamespace 'http://www.w3.org/2001/XMLSchema-instance' prefix 'xsi'";
variant "elementFormQualified";
}
......@@ -164,6 +164,7 @@
<File path="../xsd/included_without_namespace.xsd" />
<File path="../xsd/list_complextype.xsd" />
<File path="../xsd/enumeration_restriction3.xsd" />
<File path="../xsd/MyXMLSchema.xsd" />
</File_Group>
<File_Group name="XmlTest_xsds" >
<File path="../XmlTest_xsds/XmlTest_boolean.xsd" />
......@@ -398,6 +399,7 @@
<File path="../XmlTest_expectedTtcns/www_example_org_including_module_e.ttcn" />
<File path="../XmlTest_expectedTtcns/www_example_org_list_complextype_e.ttcn" />
<File path="../XmlTest_expectedTtcns/www_example_org_enumeration_restriction3_e.ttcn" />
<File path="../XmlTest_expectedTtcns/http_www_example_org_2001_XMLSchema_e.ttcn" />
</File_Group>
<File_Group name="XmlTest_src" >
<File path="xmlTest_Shell.ttcn" />
......
......@@ -1598,6 +1598,16 @@ group ComplexType {
}
}//tc_
testcase tc_xmlschema() runs on xmlTest_CT {
f_shellCommandWithVerdict("xsd2ttcn MyXMLSchema.xsd","",c_shell_successWithoutWarningAndError)
if(getverdict==pass) {
f_compareFiles(
"http_www_example_org_2001_XMLSchema_e.ttcn",
"http_www_example_org_2001_XMLSchema.ttcn", c_numOfDiff_headerModNameAndNamespace);
}
}//tc_
testcase tc_complex_restriction_encDec() runs on xmlTest_CT
{
var MySubjects4Restriction vl_pdu:={
......@@ -2650,6 +2660,7 @@ control {
execute(tc_complex_nillable());
execute(tc_nillable_fixed());
execute(tc_no_ns_connector());
execute(tc_xmlschema());
......
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.example.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:a="http://www.example.org/2001/XMLSchema">
<xs:group name="attrDecls">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="attribute" type="xs:string"/>
<xs:element name="attributeGroup" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="openAttrs">
<xs:complexContent>
<xs:restriction base="xs:anyType">
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="annotated">
<xs:complexContent>
<xs:extension base="a:openAttrs">
<xs:sequence>
<xs:element type="xs:string" name="asd" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:group name="typeDefParticle">
<xs:choice>
<xs:element name="group" type="xs:string"/>
</xs:choice>
</xs:group>
<xs:complexType name="restrictionType">
<xs:complexContent>
<xs:extension base="a:annotated">
<xs:sequence>
<xs:choice minOccurs="0">
<xs:group ref="a:typeDefParticle"/>
</xs:choice>
<xs:group ref="a:attrDecls"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="complexRestrictionType">
<xs:complexContent>
<xs:restriction base="a:restrictionType">
<xs:sequence>
<xs:choice minOccurs="1">
<xs:group ref="a:typeDefParticle"/>
</xs:choice>
<xs:group ref="a:attrDecls"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:schema>
......@@ -120,20 +120,20 @@ void AttributeType::applyUseAttribute() {
}
switch (useVal) {
case optional:
minOccurs = 0;
maxOccurs = 1;
setMinOccurs(0);
setMaxOccurs(1);
break;
case required:
minOccurs = 1;
maxOccurs = 1;
setMinOccurs(1);
setMaxOccurs(1);
break;
case prohibited:
minOccurs = 0;
maxOccurs = 0;
setMinOccurs(0);
setMaxOccurs(0);
setInvisible();
break;
}
isOptional = isOptional || (minOccurs == 0 && maxOccurs == 1);
isOptional = isOptional || (getMinOccurs() == 0 && getMaxOccurs() == 1);
}
void AttributeType::applyNamespaceAttribute(VariantMode varLabel) {
......@@ -194,8 +194,8 @@ void AttributeType::applyNamespaceAttribute(VariantMode varLabel) {
}
void AttributeType::applyMinMaxOccursAttribute(unsigned long long min, unsigned long long max) {
minOccurs = min;
maxOccurs = max;
setMinOccurs(min);
setMaxOccurs(max);
}
void AttributeType::dump(unsigned int depth) const {
......@@ -203,7 +203,7 @@ void AttributeType::dump(unsigned int depth) const {
name.originalValueWoPrefix.c_str(), name.convertedValue.c_str(), (const void*) this);
fprintf(stderr, "%*s %s Type: \n", depth * 2, "", type.convertedValue.c_str());
fprintf(stderr, "%*s type %s \n", (depth + 1) * 2, "", type.convertedValue.c_str());
fprintf(stderr, "%*s (%llu .. %llu)\n", (depth + 1) * 2, "", minOccurs, maxOccurs);
fprintf(stderr, "%*s (%llu .. %llu)\n", (depth + 1) * 2, "", getMinOccurs(), getMaxOccurs());
fprintf(stderr, "%*s %d variants: ", (depth + 1) * 2, "", (int) variant.size());
for (List<Mstring>::iterator var = variant.begin(); var; var = var->Next) {
fprintf(stderr, "%s, ", var->Data.c_str());
......
......@@ -733,15 +733,16 @@ void ComplexType::applyReference(const SimpleType & other, const bool on_attribu
type.convertedValue = other.getType().convertedValue;
type.originalValueWoPrefix = other.getType().convertedValue.getValueWithoutPrefix(':');
if (other.getMinOccurs() > minOccurs || other.getMaxOccurs() < maxOccurs) {
if (other.getMinOccurs() > getMinOccurs() ||
other.getMaxOccurs() < getMaxOccurs()) {
if (!on_attributes) {
expstring_t temp = memptystr();
temp = mputprintf(
temp,
"The occurrence range (%llu .. %llu) of the element (%s) is not compatible "
"with the occurrence range (%llu .. %llu) of the referenced element.",
minOccurs,
maxOccurs,
getMinOccurs(),
getMaxOccurs(),
name.originalValueWoPrefix.c_str(),
other.getMinOccurs(),
other.getMaxOccurs());
......@@ -751,8 +752,8 @@ void ComplexType::applyReference(const SimpleType & other, const bool on_attribu
TTCN3ModuleInventory::getInstance().incrNumErrors();
}
} else {
minOccurs = llmax(minOccurs, other.getMinOccurs());
maxOccurs = llmin(maxOccurs, other.getMaxOccurs());
setMinOccurs(llmax(getMinOccurs(), other.getMinOccurs()));
setMaxOccurs(llmin(getMaxOccurs(), other.getMaxOccurs()));
}
for (List<Mstring>::iterator var = other.getVariantRef().begin(); var; var = var->Next) {
......@@ -929,7 +930,7 @@ void ComplexType::setFieldPaths(Mstring path) {
if (path.empty()) {
if (!top) {
Mstring field_prefix = empty_string;
if(parent->minOccurs == 0 && parent->maxOccurs == ULLONG_MAX){
if(parent->getMinOccurs() == 0 && parent->getMaxOccurs() == ULLONG_MAX){
field_prefix = "[-].";
}
path = field_prefix + getName().convertedValue;
......@@ -959,14 +960,14 @@ void ComplexType::finalModification2() {
SimpleType::finalModification();
//Set isOptional field
isOptional = isOptional || (minOccurs == 0 && maxOccurs == 1);
isOptional = isOptional || (getMinOccurs() == 0 && getMaxOccurs() == 1);
//
List<Mstring> enumNames;
for (List<ComplexType*>::iterator field = complexfields.begin(), nextField; field; field = nextField) {
nextField = field->Next;
//Remove invisible fields
if ((field->Data->minOccurs == 0 && field->Data->maxOccurs == 0) || !field->Data->isVisible()) {
if ((field->Data->getMinOccurs() == 0 && field->Data->getMaxOccurs() == 0) || !field->Data->isVisible()) {
delete field->Data;
field->Data = NULL;
complexfields.remove(field);
......@@ -1252,7 +1253,7 @@ void ComplexType::collectVariants(List<Mstring>& container) {
if (top) {
bool useUnionVariantWhenMainTypeIsRecordOf = false;
for (List<Mstring>::iterator var = variant.end(); var; var = var->Prev) {
if ((minOccurs != 1 || maxOccurs != 1) && (var->Data == "\"useUnion\"")) { // main type is a record of
if ((getMinOccurs() != 1 || getMaxOccurs() != 1) && (var->Data == "\"useUnion\"")) { // main type is a record of
useUnionVariantWhenMainTypeIsRecordOf = true; // TR HL15893
} else {
container.push_back(Mstring("variant ") + Mstring(var->Data.c_str()) + Mstring(";\n"));
......@@ -1389,7 +1390,7 @@ void ComplexType::dump(unsigned int depth) const {
for (List<Mstring>::iterator field = enumfields.begin(); field; field = field->Next) {
fprintf(stderr, "%*s enum: %s\n", depth * 2 + depth, "", field->Data.c_str());
}
fprintf(stderr, "%*s (%llu .. %llu) | Optional:%s | List:%s\n", (depth + 1) * 2, "", minOccurs, maxOccurs, isOptional ? "true" : "false", name.list_extension ? "true" : "false");
fprintf(stderr, "%*s (%llu .. %llu) | Optional:%s | List:%s\n", (depth + 1) * 2, "", getMinOccurs(), getMaxOccurs(), isOptional ? "true" : "false", name.list_extension ? "true" : "false");
fprintf(stderr, "%*s %d variants: ", (depth + 1) * 2, "", (int) variant.size());
for (List<Mstring>::iterator var = variant.begin(); var; var = var->Next) {
fprintf(stderr, "%s, ", var->Data.c_str());
......@@ -1403,8 +1404,8 @@ void ComplexType::setMinMaxOccurs(const unsigned long long min, const unsigned l
if (min != 1 || max != 1) {
if (xsdtype == n_choice) {
minOccurs = min;
maxOccurs = max;
setMinOccurs(min);
setMaxOccurs(max);
addVariant(V_untagged);
first_child = false;
} else if (xsdtype == n_sequence) {
......@@ -1414,17 +1415,17 @@ void ComplexType::setMinMaxOccurs(const unsigned long long min, const unsigned l
rec->setXsdtype(n_sequence);
rec->addVariant(V_untagged);
rec->addVariant(V_untagged);
rec->minOccurs = min;
rec->maxOccurs = max;
rec->setMinOccurs(min);
rec->setMaxOccurs(max);
complexfields.push_back(rec);
actfield = rec;
if ((rec->minOccurs == 0 && rec->maxOccurs > 1) || rec->minOccurs > 0) {
if ((rec->getMinOccurs() == 0 && rec->getMaxOccurs() > 1) || rec->getMinOccurs() > 0) {
rec->name.list_extension = true;
}
} else {
minOccurs = min;
maxOccurs = max;
if ((minOccurs == 0 && maxOccurs > 1) || minOccurs > 0) {
setMinOccurs(min);
setMaxOccurs(max);
if ((getMinOccurs() == 0 && getMaxOccurs() > 1) || getMinOccurs() > 0) {
if (generate_list_postfix) {
name.list_extension = true;
}
......@@ -1432,7 +1433,7 @@ void ComplexType::setMinMaxOccurs(const unsigned long long min, const unsigned l
if (parent != NULL && parent->getXsdtype() == n_choice) {
name.list_extension = true;
if ((parent != NULL && parent->getXsdtype() == n_choice)) {
if (parent->first_child == false && minOccurs == 0) {
if (parent->first_child == false && getMinOccurs() == 0) {
parent->first_child = true;
with_union = true;
first_child = false;
......@@ -1445,7 +1446,7 @@ void ComplexType::setMinMaxOccurs(const unsigned long long min, const unsigned l
}
}
if (maxOccurs > 1 && generate_list_postfix) {
if (getMaxOccurs() > 1 && generate_list_postfix) {
name.list_extension = true;
}
}
......@@ -1691,7 +1692,7 @@ void ComplexType::resolveGroup(SimpleType *st) {
ct->getModule()->getTargetNamespace() != "NoTargetNamespace") {
addNameSpaceas = true;
}
if (ct->getXsdtype() == n_sequence && minOccurs == 1 && maxOccurs == 1 && (parent->getXsdtype() == n_complexType || parent->getXsdtype() == n_sequence)) {
if (ct->getXsdtype() == n_sequence && getMinOccurs() == 1 && getMaxOccurs() == 1 && (parent->getXsdtype() == n_complexType || parent->getXsdtype() == n_sequence)) {
for (List<ComplexType*>::iterator c = ct->complexfields.begin(); c; c = c->Next) {
ComplexType * newField = new ComplexType(*c->Data);
parent->complexfields.push_back(newField);
......@@ -1705,7 +1706,7 @@ void ComplexType::resolveGroup(SimpleType *st) {
//If the parent optional, then every field is optional
for (List<ComplexType*>::iterator c = ct->complexfields.begin(); c; c = c->Next) {
ComplexType* f = new ComplexType(*c->Data);
if (minOccurs == 0 && !f->enumerated) {
if (getMinOccurs() == 0 && !f->enumerated) {
f->isOptional = true;
}
((ComplexType*) parent)->complexfields.push_back(f);
......@@ -1916,8 +1917,8 @@ void ComplexType::resolveComplexTypeExtension() {
field->applyReference(*f->Data);
field->type.upload(ct->getName().convertedValue + Mstring(".") + f->Data->getName().convertedValue);
field->type.no_replace = true;
field->minOccurs = f->Data->minOccurs;
field->maxOccurs = f->Data->maxOccurs;
field->setMinOccurs(f->Data->getMinOccurs());
field->setMaxOccurs(f->Data->getMaxOccurs());
complexfields.push_front(field);
setParent(this, field);
}
......@@ -1951,7 +1952,10 @@ void ComplexType::resolveComplexTypeRestriction() {
List<ComplexType*>::iterator field2 = ct->complexfields.begin();
for (; field2; field2 = field2->Next) {
if (field->Data->getName().convertedValue == field2->Data->getName().convertedValue &&
field->Data->getType().convertedValue == field2->Data->getType().convertedValue) {
field->Data->getType().convertedValue == field2->Data->getType().convertedValue &&
field->Data->complexfields.size() <= field2->Data->complexfields.size() &&
hasMatchingFields(field->Data->complexfields, field2->Data->complexfields)) {
// TODO: better algorithm to find matching fields
field->Data->applyReference(*field2->Data, false);
break;
}
......@@ -1964,6 +1968,25 @@ void ComplexType::resolveComplexTypeRestriction() {
}
}
bool ComplexType::hasMatchingFields(const List<ComplexType*>& mainList, const List<ComplexType*>& subList) const {
List<ComplexType*>::iterator field = mainList.begin();
for (; field; field = field->Next){
List<ComplexType*>::iterator field2 = subList.begin();
bool found = false;
for (; field2; field2 = field2->Next) {
if(field->Data->getName().convertedValue == field2->Data->getName().convertedValue &&
field->Data->getType().convertedValue == field2->Data->getType().convertedValue) {
found = true;
break;
}
}
if(!found) {
return false;
}
}
return true;
}
void ComplexType::resolveUnion(SimpleType *st) {
if (parent != NULL && parent->with_union && xsdtype == n_simpleType && !outside_reference.empty()) {
if (st->getXsdtype() != n_NOTSET) {
......
......@@ -111,6 +111,7 @@ private:
void resolveComplexTypeExtension();
void resolveComplexTypeRestriction();
void resolveUnion(SimpleType *st);
bool hasMatchingFields(const List<ComplexType*>& a, const List<ComplexType*>& b) const;
void printVariant(FILE * file);
......
......@@ -21,15 +21,17 @@ RootType::RootType(XMLParser * a_parser, TTCN3Module * a_module, const Construct
, module(a_module)
, name()
, type()
, minOccurs(1)
, maxOccurs(1)
, variant()
, variant_ref()
, comment()
, construct(a_construct)
, origin(from_unknown)
, visible(true)
, nameDepList() {
, nameDepList()
, minOccurs(1)
, maxOccurs(1)
, min_mod(false)
, max_mod(false){
switch (a_construct) {
case c_schema:
case c_annotation:
......
......@@ -112,8 +112,6 @@ protected:
NameType name;
NameType type;
unsigned long long int minOccurs;
unsigned long long int maxOccurs;
List<Mstring> variant;
List<Mstring> variant_ref;
List<Mstring> hidden_variant;
......@@ -126,7 +124,13 @@ protected:
/// List of types that depend on this one.
/// Used to propagate the effect of name conversion to the dependents
List<SimpleType*> nameDepList; // no responsibility for elements
private:
unsigned long long int minOccurs;
unsigned long long int maxOccurs;
bool min_mod;
bool max_mod;
public:
RootType(XMLParser * a_parser, TTCN3Module * a_module, const ConstructType a_construct);
......@@ -175,6 +179,24 @@ public:
void setVisible() {
visible = true;
}
void setMinOccurs(const unsigned long long int min) {
minOccurs = min;
min_mod = true;
}
void setMaxOccurs(const unsigned long long int max) {
maxOccurs = max;
max_mod = true;
}
const bool getMinMod() const {
return min_mod;
}
const bool getMaxMod() const {
return max_mod;
}
const NameType & getName() const {
return name;
......
......@@ -89,8 +89,8 @@ void SimpleType::loadWithValues() {
case n_list:
type.upload(atts.itemType);
setReference(atts.itemType);
minOccurs = 0;
maxOccurs = ULLONG_MAX;
setMinOccurs(0);
setMaxOccurs(ULLONG_MAX);
addVariant(V_list);
mode = listMode;
break;
......@@ -133,8 +133,8 @@ void SimpleType::loadWithValues() {
}
case n_length:
if (mode == listMode) {
minOccurs = strtoull(atts.value.c_str(), NULL, 0);
maxOccurs = strtoull(atts.value.c_str(), NULL, 0);
setMinOccurs(strtoull(atts.value.c_str(), NULL, 0));
setMaxOccurs(strtoull(atts.value.c_str(), NULL, 0));
break;
}
length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
......@@ -143,7 +143,7 @@ void SimpleType::loadWithValues() {