Add error condition when building image
[anna.git] / source / app / Component.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #include <algorithm>
10
11 #include <anna/core/tracing/Logger.hpp>
12
13 #include <anna/app/Component.hpp>
14 #include <anna/app/functions.hpp>
15
16 #include <anna/xml/Node.hpp>
17 #include <anna/xml/Attribute.hpp>
18
19 using namespace std;
20 using namespace anna;
21
22 app::Component::Component(const char* className) :
23   anna::Component(className),
24   a_state(State::Stopped) {
25   Application& app(app::functions::getApp());
26
27   if(app.a_running == false) {
28     try {
29       app.attach(this);
30     } catch(RuntimeException& ex) {
31       ex.trace();
32     }
33   } else if(Logger::isActive(Logger::Warning) == true) {
34     string msg(asString());
35     msg += " | Application already running. You may initialize this component manually (lazy initialization)";
36     Logger::warning(msg, ANNA_FILE_LOCATION);
37   }
38 }
39
40 app::Component::~Component() {
41   try {
42     functions::getApp().detach(this);
43   } catch(RuntimeException& ex) {
44     ex.trace();
45   }
46 }
47
48 void app::Component::addPredecessor(const char* componentName)
49 throw() {
50   const std::string name(componentName);
51
52   if((find(begin(), end(), name)) != end())
53     return;
54
55   a_predecessors.push_back(name);
56   LOGDEBUG(
57     string msg("anna::app::Component::addPredecessor | ");
58     msg += asString();
59     msg += " | Requires: ";
60     msg += name;
61     Logger::debug(msg, ANNA_FILE_LOCATION);
62   );
63 }
64
65 void app::Component::initialize()
66 throw(RuntimeException) {
67   if(a_state == State::Running)
68     return;
69
70   a_state = State::Starting;
71   Application& app = functions::getApp();
72   Component* predecessor;
73
74   try {
75     for(iterator ii = begin(), maxii = end(); ii != maxii; ii ++) {
76       const std::string& name = data(ii);
77
78       if((predecessor = app.find(name.c_str())) == NULL) {
79         string msg("anna::app::Component::initialize | ");
80         msg += asString();
81         msg += " | Requires component '";
82         msg += name;
83         msg += "' undefined";
84         throw RuntimeException(msg, ANNA_FILE_LOCATION);
85       }
86
87       if(predecessor->a_state == State::Starting) {
88         string msg("anna::app::Component::initialize | ");
89         msg += asString();
90         msg += " | Cyclic dependency with '";
91         msg += name;
92         msg += "'";
93         throw RuntimeException(msg, ANNA_FILE_LOCATION);
94       }
95
96       predecessor->initialize();
97     }
98
99     do_initialize();
100     a_state = State::Running;
101   } catch(RuntimeException&) {
102     a_state = State::Stopped;
103     throw;
104   }
105 }
106
107 void app::Component::attach()
108 throw(RuntimeException) {
109   app::functions::getApp().attach(this);
110 }
111
112 std::string app::Component::asString() const
113 throw() {
114   return anna::Component::asString();
115 }
116
117 xml::Node* app::Component::asXML(xml::Node* parent) const
118 throw() {
119   return anna::Component::asXML(parent);
120 }
121