Salome HOME
Issue #279 Give an ability for user to define the path to plugins
[modules/shaper.git] / src / Config / Config_XMLReader.cpp
1 /*
2  * Config_XMLReader.cpp
3  *
4  *  Created on: Mar 14, 2014
5  *      Author: sbh
6  */
7
8 #include <Config_XMLReader.h>
9 #include <Config_Keywords.h>
10 #include <Config_Common.h>
11 #include <Config_ValidatorMessage.h>
12 #include <Config_PropManager.h>
13
14 #include <Events_Loop.h>
15 #include <Events_Error.h>
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
18
19 #include <fstream>
20
21 #ifdef WIN32
22 #pragma warning(disable : 4996) // for getenv
23 #endif
24
25 #ifdef _DEBUG
26 #include <iostream>
27 #endif
28
29 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
30     : myXmlDoc(NULL)
31 {
32   std::string prefix = ""; 
33   Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
34   if (aProp)
35     prefix = aProp->value();
36   /*
37    * Get path to *.xml files (typically ./bin/../plugins/)
38
39    * the problem: application may be launched using python executable,
40    * to use environment variable (at least for the current moment)
41    */
42   if (prefix.empty()) {
43     char* anEnv = getenv("NEW_GEOM_CONFIG_FILE");
44     if (anEnv) {
45       prefix = std::string(anEnv);
46     }
47   }
48 #ifdef WIN32
49     prefix += "\\";
50 #else
51     prefix += "/";
52 #endif
53   myDocumentPath = prefix + theXmlFileName;
54   std::ifstream aTestFile(myDocumentPath);
55   if (!aTestFile) Events_Error::send("Unable to open " + myDocumentPath);
56   aTestFile.close();
57 }
58
59 Config_XMLReader::~Config_XMLReader()
60 {
61   xmlFreeDoc(myXmlDoc);
62 }
63
64 /*
65  * Read all nodes in associated xml file,
66  * recursively if processChildren(xmlNode) is true for the xmlNode.
67  * For each read node the processNode will be called.
68  */
69 void Config_XMLReader::readAll()
70 {
71   xmlNodePtr aRoot = findRoot();
72   readRecursively(aRoot);
73 }
74
75 /*
76  * Allows to customize reader's behavior for a node. Virtual.
77  * The default impl does nothing. (In debug mode prints
78  * some info)
79  */
80 void Config_XMLReader::processNode(xmlNodePtr theNode)
81 {
82   if (isNode(theNode, NODE_SOURCE, NULL)) {
83     std::string aSourceFile = getProperty(theNode, SOURCE_FILE);
84     Config_XMLReader aSourceReader = Config_XMLReader(aSourceFile);
85     readRecursively(aSourceReader.findRoot());
86 #ifdef _DEBUG
87     std::cout << "Config_XMLReader::sourced node: " << aSourceFile << std::endl;
88 #endif
89   } else if (isNode(theNode, NODE_VALIDATOR, NULL)) {
90     processValidator(theNode);
91   }
92 }
93
94 /*
95  * Defines which nodes should be processed recursively. Virtual.
96  * The default impl is to read all nodes.
97  */
98 bool Config_XMLReader::processChildren(xmlNodePtr aNode)
99 {
100   return true;
101 }
102
103 /*
104  *
105  */
106 xmlNodePtr Config_XMLReader::findRoot()
107 {
108   if (myXmlDoc == NULL) {
109     myXmlDoc = xmlParseFile(myDocumentPath.c_str());
110   }
111   if (myXmlDoc == NULL) {
112 #ifdef _DEBUG
113     std::cout << "Config_XMLReader::import: " << "Document " << myDocumentPath
114     << " is not parsed successfully." << std::endl;
115 #endif
116     return NULL;
117   }
118   xmlNodePtr aRoot = xmlDocGetRootElement(myXmlDoc);
119 #ifdef _DEBUG
120   if(aRoot == NULL) {
121     std::cout << "Config_XMLReader::import: " << "Error: empty document";
122   }
123 #endif
124   return aRoot;
125 }
126
127 /*
128  * Calls processNode() for each child (for some - recursively)
129  * of the given node.
130  * \sa ReadAll()
131  */
132 void Config_XMLReader::readRecursively(xmlNodePtr theParent)
133 {
134   if (!theParent)
135     return;
136   xmlNodePtr aNode = theParent->xmlChildrenNode;
137   for (; aNode; aNode = aNode->next) {
138     //Still no text processing in features...
139     if (!isElementNode(aNode)) {
140       continue;
141     }
142     processNode(aNode);
143     if (processChildren(aNode)) {
144       readRecursively(aNode);
145     }
146   }
147 }
148
149 /*
150  * void* -> xmlNodePtr
151  */
152 xmlNodePtr Config_XMLReader::node(void* theNode)
153 {
154   return static_cast<xmlNodePtr>(theNode);
155 }
156
157 std::string Config_XMLReader::getNodeName(xmlNodePtr theNode)
158 {
159   std::string result = "";
160   char* aPropChars = (char*) theNode->name;
161   if (!aPropChars || aPropChars[0] == 0)
162     return result;
163   result = std::string(aPropChars);
164   return result;
165 }
166
167 void Config_XMLReader::processValidator(xmlNodePtr theNode)
168 {
169   Events_ID aValidatoEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED);
170   Events_Loop* aEvLoop = Events_Loop::loop();
171   std::shared_ptr<Config_ValidatorMessage> 
172     aMessage(new Config_ValidatorMessage(aValidatoEvent, this));
173   std::string aValidatorId;
174   std::list<std::string> aValidatorParameters;
175   getValidatorInfo(theNode, aValidatorId, aValidatorParameters);
176   aMessage->setValidatorId(aValidatorId);
177   aMessage->setValidatorParameters(aValidatorParameters);
178   xmlNodePtr aFeatureOrWdgNode = theNode->parent;
179   if (isNode(aFeatureOrWdgNode, NODE_FEATURE, NULL)) {
180     aMessage->setFeatureId(getProperty(aFeatureOrWdgNode, _ID));
181   } else {
182     aMessage->setAttributeId(getProperty(aFeatureOrWdgNode, _ID));
183     aMessage->setFeatureId(myCurrentFeature);
184   }
185   aEvLoop->send(aMessage);
186 }