Skip to content

Commit

Permalink
fixed ValidateChoices function for optional choices
Browse files Browse the repository at this point in the history
  • Loading branch information
RlanderRISCSW committed Jan 17, 2024
1 parent 4482751 commit ad853e1
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 25 deletions.
44 changes: 40 additions & 4 deletions src/lib/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,16 +1063,52 @@ namespace tigl {
cpp << "true // " << f.fieldName() << " is optional in choice";
}

void operator()(const Choice& c) {
void operator()(const Choice& ch) {
cpp << "(";
{
Scope s(cpp);
for (const auto& cc : c.options) {
(*this)(cc, c);
if (&cc != &c.options.back())
boost::optional<Scope> additionalScope;

if (ch.minOccurs == 0) {
cpp << "// all uninitialized is valid since choice is optional!";
cpp << "!(";
{
Scope s(cpp);

RecursiveColletor parentCollector;
parentCollector(ch);
auto& allIndices = parentCollector.indices;

auto unique = [](std::vector<std::size_t>& v) {
std::sort(std::begin(v), std::end(v));
const auto it = std::unique(std::begin(v), std::end(v));
v.erase(it, std::end(v));
};
unique(allIndices);

for (const auto& i : allIndices) {
writeIsFieldThere(cpp, c.fields[i]);
if (&i != &allIndices.back())
cpp << "||";
}
}
cpp << ")";
cpp << "||";
cpp << "(";
additionalScope.emplace(cpp);
}

for (const auto &ces : ch.options) {
(*this)(ces, ch);
if (&ces != &ch.options.back())
cpp << "+";
}
cpp << "== 1";

if (additionalScope) {
additionalScope.reset();
cpp << ")";
}
}
cpp << ")";
}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/SchemaParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ namespace tigl {
// </choice>
Choice ch;
ch.xpath = xpath;

// minOccurs
if (!document.checkAttribute(xpath, "minOccurs"))
ch.minOccurs = 1;
else {
const auto minOccurs = document.textAttribute(xpath, "minOccurs");
const auto minOccursInt = std::stoi(minOccurs);
if (minOccursInt < 0)
throw std::runtime_error("minOccurs is negative: " + xpath);
else if (minOccursInt > 1)
throw std::runtime_error("support for minOccurs>1 not implemented for choices yet: " + xpath);
ch.minOccurs = minOccursInt;
}

document.forEachChild(xpath, "xsd:element", [&](const std::string& xpath) {
ch.elements.push_back(readElement(xpath, containingTypeName));
});
Expand Down
1 change: 1 addition & 0 deletions src/lib/SchemaParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace tigl {

struct Choice : XSDElement {
std::vector<Variant<Element, Group, Choice, Sequence, Any>> elements;
unsigned int minOccurs;
};

struct SimpleContent : XSDElement {
Expand Down
1 change: 1 addition & 0 deletions src/lib/TypeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ namespace tigl {
const auto countBefore = members.size();

Choice choice;
choice.minOccurs = c.minOccurs;
for (const auto& v : c.elements | boost::adaptors::indexed(1)) {
// collect members of one choice
auto indices = choiceIndices;
Expand Down
1 change: 1 addition & 0 deletions src/lib/TypeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ namespace tigl {
using ChoiceElements = std::vector<boost::variant<ChoiceElement, boost::recursive_wrapper<Choice>>>;

struct Choice {
unsigned int minOccurs;
std::vector<ChoiceElements> options;
};

Expand Down
44 changes: 23 additions & 21 deletions test/data/optionalchoice/ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,34 +158,36 @@ namespace generated
{
return
(
// all uninitialized is valid since choice is optional
!(
m_a_choice1.is_initialized()
||
m_b_choice2.is_initialized()
)
||
(
(
// mandatory elements of this choice must be there
// all uninitialized is valid since choice is optional!
!(
m_a_choice1.is_initialized()
&&
// elements of other choices must not be there
!(
m_b_choice2.is_initialized()
)
||
m_b_choice2.is_initialized()
)
+
||
(
// mandatory elements of this choice must be there
m_b_choice2.is_initialized()
&&
// elements of other choices must not be there
!(
(
// mandatory elements of this choice must be there
m_a_choice1.is_initialized()
&&
// elements of other choices must not be there
!(
m_b_choice2.is_initialized()
)
)
+
(
// mandatory elements of this choice must be there
m_b_choice2.is_initialized()
&&
// elements of other choices must not be there
!(
m_a_choice1.is_initialized()
)
)
== 1
)
== 1
)
)
;
Expand Down

0 comments on commit ad853e1

Please sign in to comment.