Salome HOME
Fix for the issue #2031
[modules/shaper.git] / src / Config / Config_XMLReader.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 /*
4  * Config_XMLReader.cpp
5  *
6  *  Created on: Mar 14, 2014
7  *      Author: sbh
8  */
9
10 #include <Config_XMLReader.h>
11 #include <Config_Keywords.h>
12 #include <Config_Common.h>
13 #include <Config_PropManager.h>
14 #include <Config_ModuleReader.h>
15
16 #include <Events_Loop.h>
17 #include <Events_InfoMessage.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
20
21 #include <fstream>
22
23 #ifdef WIN32
24 #pragma warning(disable : 4996) // for getenv
25 #endif
26
27 #ifdef _DEBUG
28 #include <iostream>
29 #endif
30
31 #ifdef WIN32
32     static const char FSEP = '\\';
33 #else
34     static const char FSEP = '/';
35 #endif
36
37 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
38     : myXmlDoc(NULL)
39 {
40   std::string prefix = "";
41   Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
42   if (aProp)
43     prefix = aProp->value();
44   /*
45    * Get path to *.xml files (typically ./bin/../plugins/)
46
47    * the problem: application may be launched using python executable,
48    * to use environment variable (at least for the current moment)
49    */
50   if (prefix.empty())
51     prefix = pluginConfigFile();
52
53   myDocumentPath = prefix + FSEP + theXmlFileName;
54   std::ifstream aTestFile(myDocumentPath);
55   if (!aTestFile)
56     Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(myDocumentPath).send();
57   aTestFile.close();
58 }
59
60 Config_XMLReader::~Config_XMLReader()
61 {
62   xmlFreeDoc(myXmlDoc);
63 }
64
65 std::string Config_XMLReader::pluginConfigFile()
66 {
67   std::string aValue;
68   char* anEnv = getenv("SHAPER_ROOT_DIR");
69   if (anEnv) {
70     aValue = std::string(anEnv) +
71       FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
72   } else {
73     anEnv = getenv("OPENPARTS_ROOT_DIR");
74     if (anEnv) {
75       aValue = std::string(anEnv) + FSEP + "plugins";
76     }
77   }
78   return aValue;
79 }
80
81 void Config_XMLReader::readAll()
82 {
83   // to load external modules dependencies (like GEOm for Connector Feature
84   Config_ModuleReader::loadScript("salome.shaper.initConfig", false);
85
86   xmlNodePtr aRoot = findRoot();
87   readRecursively(aRoot);
88 }
89
90 void Config_XMLReader::processNode(xmlNodePtr theNode)
91 {
92   if (isNode(theNode, NODE_SOURCE, NULL)) {
93     std::string aSourceFile = getProperty(theNode, SOURCE_FILE);
94     Config_XMLReader aSourceReader = Config_XMLReader(aSourceFile);
95     readRecursively(aSourceReader.findRoot());
96 #ifdef _DEBUG
97     //std::cout << "Config_XMLReader::sourced node: " << aSourceFile << std::endl;
98 #endif
99   }
100 }
101
102 void Config_XMLReader::cleanup(xmlNodePtr)
103 {
104   // do nothing;
105 }
106
107 bool Config_XMLReader::processChildren(xmlNodePtr aNode)
108 {
109   return true;
110 }
111
112 xmlNodePtr Config_XMLReader::findRoot()
113 {
114   if (myXmlDoc == NULL) {
115     myXmlDoc = xmlParseFile(myDocumentPath.c_str());
116   }
117   if (myXmlDoc == NULL) {
118 #ifdef _DEBUG
119     std::cout << "Config_XMLReader::import: " << "Document " << myDocumentPath
120     << " is not parsed successfully." << std::endl;
121 #endif
122     return NULL;
123   }
124   xmlNodePtr aRoot = xmlDocGetRootElement(myXmlDoc);
125 #ifdef _DEBUG
126   if(aRoot == NULL) {
127     std::cout << "Config_XMLReader::import: " << "Error: empty document";
128   }
129 #endif
130   return aRoot;
131 }
132
133 void Config_XMLReader::readRecursively(xmlNodePtr theParent)
134 {
135   if (!theParent)
136     return;
137   xmlNodePtr aNode = theParent->xmlChildrenNode;
138   for (; aNode; aNode = aNode->next) {
139     //Still no text processing in features...
140     if (!isElementNode(aNode)) {
141       continue;
142     }
143     processNode(aNode);
144     if (processChildren(aNode)) {
145       readRecursively(aNode);
146     }
147     cleanup(aNode);
148   }
149 }
150
151 xmlNodePtr Config_XMLReader::node(void* theNode)
152 {
153   return static_cast<xmlNodePtr>(theNode);
154 }
155
156 std::string Config_XMLReader::getNodeName(xmlNodePtr theNode)
157 {
158   std::string result = "";
159   char* aPropChars = (char*) theNode->name;
160   if (!aPropChars || aPropChars[0] == 0)
161     return result;
162   result = std::string(aPropChars);
163   return result;
164 }
165
166 void Config_XMLReader::storeAttribute(xmlNodePtr theNode, const char* theAttribute, bool doClean)
167 {
168   std::string aKey = getNodeName(theNode) + ":" + std::string(theAttribute);
169   std::string aValue = getProperty(theNode, theAttribute);
170   if (doClean || !aValue.empty()) {
171     myCachedAttributes[aKey] = aValue;
172   }
173 }
174
175 std::string Config_XMLReader::restoreAttribute(xmlNodePtr theNode, const char* theAttribute)
176 {
177   return restoreAttribute(getNodeName(theNode).c_str(), theAttribute);
178 }
179
180 std::string Config_XMLReader::restoreAttribute(const char* theNodeName, const char* theAttribute)
181 {
182   std::string aKey = std::string(theNodeName) + ":" + std::string(theAttribute);
183   std::string result = "";
184   if(myCachedAttributes.find(aKey) != myCachedAttributes.end()) {
185     result = myCachedAttributes[aKey];
186   }
187   return result;
188 }
189
190 bool Config_XMLReader::cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute)
191 {
192   return cleanupAttribute(getNodeName(theNode).c_str(), theNodeAttribute);
193 }
194
195 bool Config_XMLReader::cleanupAttribute(const char* theNodeName, const char* theNodeAttribute)
196 {
197   std::string aKey = std::string(theNodeName) + ":" + std::string(theNodeAttribute);
198   bool result = false;
199   std::map<std::string, std::string>::iterator anEntry = myCachedAttributes.find(aKey);
200   if( anEntry != myCachedAttributes.end()) {
201     myCachedAttributes.erase(anEntry);
202     result = true;
203   }
204   return result;
205 }
206
207 const char* Config_XMLReader::encoding() const
208 {
209   return (const char*) myXmlDoc->encoding;
210 }