Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / Config / Config_XMLReader.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <Config_XMLReader.h>
22 #include <Config_Keywords.h>
23 #include <Config_Common.h>
24 #include <Config_PropManager.h>
25 #include <Config_ModuleReader.h>
26
27 #include <Events_Loop.h>
28 #include <Events_InfoMessage.h>
29 #include <libxml/parser.h>
30 #include <libxml/tree.h>
31
32 #include <fstream>
33
34 #ifdef WIN32
35 #pragma warning(disable : 4996) // for getenv
36 #endif
37
38 #ifdef _DEBUG
39 #include <iostream>
40 #endif
41
42 #ifdef WIN32
43     static const char FSEP = '\\';
44 #else
45     static const char FSEP = '/';
46 #endif
47
48 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
49     : myXmlDoc(NULL)
50 {
51   std::string prefix = "";
52   Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
53   if (aProp)
54     prefix = aProp->value();
55   /*
56    * Get path to *.xml files (typically ./bin/../plugins/)
57
58    * the problem: application may be launched using python executable,
59    * to use environment variable (at least for the current moment)
60    */
61   if (prefix.empty())
62     prefix = pluginConfigFile();
63
64   myDocumentPath = prefix + FSEP + theXmlFileName;
65   std::ifstream aTestFile(myDocumentPath);
66   if (!aTestFile)
67     Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(myDocumentPath).send();
68   aTestFile.close();
69 }
70
71 Config_XMLReader::~Config_XMLReader()
72 {
73   xmlFreeDoc(myXmlDoc);
74 }
75
76 std::string Config_XMLReader::pluginConfigFile()
77 {
78   std::string aValue;
79   char* anEnv = getenv("SHAPER_ROOT_DIR");
80   if (anEnv) {
81     aValue = std::string(anEnv) +
82       FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
83   } else {
84     anEnv = getenv("OPENPARTS_ROOT_DIR");
85     if (anEnv) {
86       aValue = std::string(anEnv) + FSEP + "plugins";
87     }
88   }
89   return aValue;
90 }
91
92 void Config_XMLReader::readAll()
93 {
94   // to load external modules dependencies (like GEOm for Connector Feature
95   Config_ModuleReader::loadScript("salome.shaper.initConfig", false);
96
97   xmlNodePtr aRoot = findRoot();
98   readRecursively(aRoot);
99 }
100
101 void Config_XMLReader::processNode(xmlNodePtr theNode)
102 {
103   if (isNode(theNode, NODE_SOURCE, NULL)) {
104     std::string aSourceFile = getProperty(theNode, SOURCE_FILE);
105     Config_XMLReader aSourceReader = Config_XMLReader(aSourceFile);
106     readRecursively(aSourceReader.findRoot());
107 #ifdef _DEBUG
108     //std::cout << "Config_XMLReader::sourced node: " << aSourceFile << std::endl;
109 #endif
110   }
111 }
112
113 void Config_XMLReader::cleanup(xmlNodePtr)
114 {
115   // do nothing;
116 }
117
118 bool Config_XMLReader::processChildren(xmlNodePtr aNode)
119 {
120   return true;
121 }
122
123 xmlNodePtr Config_XMLReader::findRoot()
124 {
125   if (myXmlDoc == NULL) {
126     myXmlDoc = xmlParseFile(myDocumentPath.c_str());
127   }
128   if (myXmlDoc == NULL) {
129 #ifdef _DEBUG
130     std::cout << "Config_XMLReader::import: " << "Document " << myDocumentPath
131     << " is not parsed successfully." << std::endl;
132 #endif
133     return NULL;
134   }
135   xmlNodePtr aRoot = xmlDocGetRootElement(myXmlDoc);
136 #ifdef _DEBUG
137   if(aRoot == NULL) {
138     std::cout << "Config_XMLReader::import: " << "Error: empty document";
139   }
140 #endif
141   return aRoot;
142 }
143
144 void Config_XMLReader::readRecursively(xmlNodePtr theParent)
145 {
146   if (!theParent)
147     return;
148   xmlNodePtr aNode = theParent->xmlChildrenNode;
149   for (; aNode; aNode = aNode->next) {
150     //Still no text processing in features...
151     if (!isElementNode(aNode)) {
152       continue;
153     }
154     processNode(aNode);
155     if (processChildren(aNode)) {
156       readRecursively(aNode);
157     }
158     cleanup(aNode);
159   }
160 }
161
162 xmlNodePtr Config_XMLReader::node(void* theNode)
163 {
164   return static_cast<xmlNodePtr>(theNode);
165 }
166
167 std::string Config_XMLReader::getNodeName(xmlNodePtr theNode)
168 {
169   std::string result = "";
170   char* aPropChars = (char*) theNode->name;
171   if (!aPropChars || aPropChars[0] == 0)
172     return result;
173   result = std::string(aPropChars);
174   return result;
175 }
176
177 void Config_XMLReader::storeAttribute(xmlNodePtr theNode, const char* theAttribute, bool doClean)
178 {
179   std::string aKey = getNodeName(theNode) + ":" + std::string(theAttribute);
180   std::string aValue = getProperty(theNode, theAttribute);
181   if (doClean || !aValue.empty()) {
182     myCachedAttributes[aKey] = aValue;
183   }
184 }
185
186 std::string Config_XMLReader::restoreAttribute(xmlNodePtr theNode, const char* theAttribute)
187 {
188   return restoreAttribute(getNodeName(theNode).c_str(), theAttribute);
189 }
190
191 std::string Config_XMLReader::restoreAttribute(const char* theNodeName, const char* theAttribute)
192 {
193   std::string aKey = std::string(theNodeName) + ":" + std::string(theAttribute);
194   std::string result = "";
195   if(myCachedAttributes.find(aKey) != myCachedAttributes.end()) {
196     result = myCachedAttributes[aKey];
197   }
198   return result;
199 }
200
201 bool Config_XMLReader::cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute)
202 {
203   return cleanupAttribute(getNodeName(theNode).c_str(), theNodeAttribute);
204 }
205
206 bool Config_XMLReader::cleanupAttribute(const char* theNodeName, const char* theNodeAttribute)
207 {
208   std::string aKey = std::string(theNodeName) + ":" + std::string(theNodeAttribute);
209   bool result = false;
210   std::map<std::string, std::string>::iterator anEntry = myCachedAttributes.find(aKey);
211   if( anEntry != myCachedAttributes.end()) {
212     myCachedAttributes.erase(anEntry);
213     result = true;
214   }
215   return result;
216 }
217
218 const char* Config_XMLReader::encoding() const
219 {
220   return (const char*) myXmlDoc->encoding;
221 }