Skip to content

Commit

Permalink
Implement Alignment initialization from MEF XML
Browse files Browse the repository at this point in the history
Intializer class learns the Alignment construction and validation.

Issue #153
  • Loading branch information
rakhimov committed Aug 10, 2017
1 parent 34ca4bd commit 8ba9319
Show file tree
Hide file tree
Showing 17 changed files with 173 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/alignment.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class Alignment : public Element, private boost::noncopyable {
ElementTable<PhasePtr> phases_; ///< The partitioning of the alignment.
};

using AlignmentPtr = std::unique_ptr<Alignment>; ///< Unique model alignments.

} // namespace mef
} // namespace scram

Expand Down
48 changes: 48 additions & 0 deletions src/initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <boost/filesystem.hpp>
#include <boost/range/algorithm.hpp>

#include "alignment.h"
#include "cycle.h"
#include "env.h"
#include "error.h"
Expand Down Expand Up @@ -137,6 +138,21 @@ xmlpp::NodeSet GetNonAttributeElements(const xmlpp::Element* xml_element) {
return xml_element->find("./*[name() != 'attributes' and name() != 'label']");
}

template <>
PhasePtr ConstructElement<Phase>(const xmlpp::Element* xml_element) {
std::string name = GetAttributeValue(xml_element, "name");
double fraction = CastAttributeValue<double>(xml_element, "time-fraction");
PhasePtr element;
try {
element = std::make_unique<Phase>(std::move(name), fraction);
} catch (InvalidArgument& err) {
err.msg(GetLine(xml_element) + err.msg());
throw;
}
AttachLabelAndAttributes(xml_element, element.get());
return element;
}

} // namespace

Initializer::Initializer(const std::vector<std::string>& xml_files,
Expand Down Expand Up @@ -386,6 +402,10 @@ void Initializer::ProcessInputFile(const std::string& xml_file) {
Register<CcfGroup>(XmlElement(node), "", RoleSpecifier::kPublic);
}

for (const xmlpp::Node* node : root->find("./define-alignment")) {
DefineAlignment(XmlElement(node));
}

for (const xmlpp::Node* node : root->find("./model-data")) {
ProcessModelData(XmlElement(node));
}
Expand Down Expand Up @@ -604,6 +624,34 @@ void Initializer::RegisterFaultTreeData(const xmlpp::Element* ft_node,
}
}

void Initializer::DefineAlignment(const xmlpp::Element* xml_node) {
AlignmentPtr alignment = ConstructElement<Alignment>(xml_node);
for (const xmlpp::Node* node : xml_node->find("./define-phase")) {
try {
PhasePtr phase = ConstructElement<Phase>(XmlElement(node));
std::vector<SetHouseEvent*> instructions;
for (const xmlpp::Node* arg : node->find("./set-house-event")) {
instructions.push_back(
static_cast<SetHouseEvent*>(GetInstruction(XmlElement(arg))));
}
phase->instructions(std::move(instructions));
alignment->Add(std::move(phase));
} catch (InvalidArgument& err) {
throw ValidationError(err.msg());
} catch (DuplicateArgumentError& err) {
err.msg(GetLine(node) + err.msg());
throw;
}
}
try {
alignment->Validate();
} catch (ValidationError& err) {
err.msg(GetLine(xml_node) + err.msg());
throw;
}
Register(std::move(alignment), xml_node);
}

void Initializer::ProcessModelData(const xmlpp::Element* model_data) {
for (const xmlpp::Node* node : model_data->find("./define-house-event")) {
Register<HouseEvent>(XmlElement(node), "", RoleSpecifier::kPublic);
Expand Down
7 changes: 7 additions & 0 deletions src/initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ class Initializer : private boost::noncopyable {
const std::string& base_path,
Component* component);

/// Defines the model alignment from the xml element.
///
/// @param[in] xml_node The XML element with alignment data.
///
/// @throws ValidationError Invalid alignment definition.
void DefineAlignment(const xmlpp::Element* xml_node);

/// Processes model data with definitions of events and analysis.
///
/// @param[in] model_data XML node with model data description.
Expand Down
5 changes: 5 additions & 0 deletions src/model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ void Model::Add(FaultTreePtr fault_tree) {
"Redefinition of fault tree: ");
}

void Model::Add(AlignmentPtr alignment) {
mef::AddElement<RedefinitionError>(std::move(alignment), &alignments_,
"Redefinition of alignment: ");
}

void Model::Add(ParameterPtr parameter) {
mef::AddElement<RedefinitionError>(std::move(parameter), &parameters_,
"Redefinition of parameter: ");
Expand Down
4 changes: 4 additions & 0 deletions src/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <boost/noncopyable.hpp>

#include "alignment.h"
#include "ccf_group.h"
#include "element.h"
#include "event.h"
Expand Down Expand Up @@ -86,6 +87,7 @@ class Model : public Element, private boost::noncopyable {
const ElementTable<SequencePtr>& sequences() const { return sequences_; }
const ElementTable<RulePtr>& rules() const { return rules_; }
const ElementTable<FaultTreePtr>& fault_trees() const { return fault_trees_; }
const ElementTable<AlignmentPtr>& alignments() const { return alignments_; }
const IdTable<ParameterPtr>& parameters() const { return parameters_; }
const MissionTime& mission_time() const { return *mission_time_; }
MissionTime& mission_time() { return *mission_time_; }
Expand All @@ -107,6 +109,7 @@ class Model : public Element, private boost::noncopyable {
void Add(SequencePtr element);
void Add(RulePtr element);
void Add(FaultTreePtr element);
void Add(AlignmentPtr element);
void Add(ParameterPtr element);
void Add(HouseEventPtr element);
void Add(BasicEventPtr element);
Expand Down Expand Up @@ -158,6 +161,7 @@ class Model : public Element, private boost::noncopyable {
ElementTable<SequencePtr> sequences_;
ElementTable<RulePtr> rules_;
ElementTable<FaultTreePtr> fault_trees_;
ElementTable<AlignmentPtr> alignments_;
IdTable<GatePtr> gates_;
IdTable<HouseEventPtr> house_events_;
IdTable<BasicEventPtr> basic_events_;
Expand Down
32 changes: 32 additions & 0 deletions tests/initializer_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,38 @@ TEST(InitializerTest, NonOrphanTopEvent) {
core::Settings()));
}

TEST(InitializerTest, CorrectModelInputs) {
std::string dir = "./share/scram/input/model/";
const char* correct_inputs[] = {
"valid_alignment.xml",
"valid_sum_alignment.xml",
"private_phases.xml"};

for (const auto& input : correct_inputs) {
EXPECT_NO_THROW(Initializer({dir + input}, core::Settings()))
<< " Filename: " << input;
}
}

TEST(InitializerTest, IncorrectModelInputs) {
std::string dir = "./share/scram/input/model/";

const char* incorrect_inputs[] = {
"duplicate_phases.xml",
"invalid_phase_fraction.xml",
"zero_phase_fraction.xml",
"negative_phase_fraction.xml",
"duplicate_alignment.xml",
"empty_alignment.xml",
"excess_alignment.xml",
"incomplete_alignment.xml"};

for (const auto& input : incorrect_inputs) {
EXPECT_THROW(Initializer({dir + input}, core::Settings()), ValidationError)
<< " Filename: " << input;
}
}

} // namespace test
} // namespace mef
} // namespace scram
9 changes: 9 additions & 0 deletions tests/input/model/duplicate_alignment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="1"/>
</define-alignment>
<define-alignment name="one">
<define-phase name="phase-two" time-fraction="1"/>
</define-alignment>
</opsa-mef>
7 changes: 7 additions & 0 deletions tests/input/model/duplicate_phases.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="0.5"/>
<define-phase name="phase-one" time-fraction="0.5"/>
</define-alignment>
</opsa-mef>
4 changes: 4 additions & 0 deletions tests/input/model/empty_alignment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one"/>
</opsa-mef>
7 changes: 7 additions & 0 deletions tests/input/model/excess_alignment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="0.1"/>
<define-phase name="phase-two" time-fraction="1"/>
</define-alignment>
</opsa-mef>
6 changes: 6 additions & 0 deletions tests/input/model/incomplete_alignment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="0.1"/>
</define-alignment>
</opsa-mef>
6 changes: 6 additions & 0 deletions tests/input/model/invalid_phase_fraction.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="1.1"/>
</define-alignment>
</opsa-mef>
6 changes: 6 additions & 0 deletions tests/input/model/negative_phase_fraction.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="-1"/>
</define-alignment>
</opsa-mef>
9 changes: 9 additions & 0 deletions tests/input/model/private_phases.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="1"/>
</define-alignment>
<define-alignment name="two">
<define-phase name="phase-one" time-fraction="1"/>
</define-alignment>
</opsa-mef>
6 changes: 6 additions & 0 deletions tests/input/model/valid_alignment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="1"/>
</define-alignment>
</opsa-mef>
9 changes: 9 additions & 0 deletions tests/input/model/valid_sum_alignment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="0.1"/>
<define-phase name="phase-two" time-fraction="0.2"/>
<define-phase name="phase-three" time-fraction="0.3"/>
<define-phase name="phase-four" time-fraction="0.4"/>
</define-alignment>
</opsa-mef>
6 changes: 6 additions & 0 deletions tests/input/model/zero_phase_fraction.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<opsa-mef>
<define-alignment name="one">
<define-phase name="phase-one" time-fraction="0"/>
</define-alignment>
</opsa-mef>

0 comments on commit 8ba9319

Please sign in to comment.