Updated license
[anna.git] / source / app / Component.cpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #include <algorithm>
38
39 #include <anna/core/tracing/Logger.hpp>
40
41 #include <anna/app/Component.hpp>
42 #include <anna/app/functions.hpp>
43
44 #include <anna/xml/Node.hpp>
45 #include <anna/xml/Attribute.hpp>
46
47 using namespace std;
48 using namespace anna;
49
50 app::Component::Component(const char* className) :
51   a_className(className),
52   a_state(State::Stopped) {
53   Application& app(app::functions::getApp());
54
55   if(app.a_running == false) {
56     try {
57       app.attach(this);
58     } catch(RuntimeException& ex) {
59       ex.trace();
60     }
61   } else if(Logger::isActive(Logger::Warning) == true) {
62     string msg(asString());
63     msg += " | Not connected to applicatino yet";
64     Logger::warning(msg, ANNA_FILE_LOCATION);
65   }
66 }
67
68 app::Component::~Component() {
69   try {
70     functions::getApp().detach(this);
71   } catch(RuntimeException& ex) {
72     ex.trace();
73   }
74 }
75
76 void app::Component::addPredecessor(const char* componentName)
77 throw() {
78   const std::string name(componentName);
79
80   if((find(begin(), end(), name)) != end())
81     return;
82
83   a_predecessors.push_back(name);
84   LOGDEBUG(
85     string msg("anna::app::Component::addPredecessor | ");
86     msg += asString();
87     msg += " | Requires: ";
88     msg += name;
89     Logger::debug(msg, ANNA_FILE_LOCATION);
90   );
91 }
92
93 void app::Component::initialize()
94 throw(RuntimeException) {
95   if(a_state == State::Running)
96     return;
97
98   a_state = State::Starting;
99   Application& app = functions::getApp();
100   Component* predecessor;
101
102   try {
103     for(iterator ii = begin(), maxii = end(); ii != maxii; ii ++) {
104       const std::string& name = data(ii);
105
106       if((predecessor = app.find(name.c_str())) == NULL) {
107         string msg("anna::app::Component::initialize | ");
108         msg += asString();
109         msg += " | Requires component '";
110         msg += name;
111         msg += "' undefined";
112         throw RuntimeException(msg, ANNA_FILE_LOCATION);
113       }
114
115       if(predecessor->a_state == State::Starting) {
116         string msg("anna::app::Component::initialize | ");
117         msg += asString();
118         msg += " | Cyclic dependency with '";
119         msg += name;
120         msg += "'";
121         throw RuntimeException(msg, ANNA_FILE_LOCATION);
122       }
123
124       predecessor->initialize();
125     }
126
127     do_initialize();
128     a_state = State::Running;
129   } catch(RuntimeException&) {
130     a_state = State::Stopped;
131     throw;
132   }
133 }
134
135 void app::Component::attach()
136 throw(RuntimeException) {
137   app::functions::getApp().attach(this);
138 }
139
140 std::string app::Component::asString() const
141 throw() {
142   std::string result("app::Component { Name: ");
143   result += a_className;
144   result += " | Reference: ";
145   result += functions::asHexString(anna_ptrnumber_cast(this));
146   return result += " }";
147 }
148
149 xml::Node* app::Component::asXML(xml::Node* parent) const
150 throw() {
151   xml::Node* result = parent->createChild("app.Component");
152   result->createAttribute("Name", a_className);
153   result->createAttribute("Reference", functions::asHexString(anna_ptrnumber_cast(this)));
154   return result;
155 }
156