Salome HOME
Merge branch 'master' into cgt/devCEA
[modules/shaper.git] / src / Config / Config_Common.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_Common.h"
22 #include <Config_Keywords.h>
23
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26
27 #include <sstream> // for stringstream
28
29 #include <string>
30 #include <algorithm> // for std::transform
31 #include <vector>
32
33 bool isElementNode(xmlNodePtr theNode)
34 {
35   if (!theNode)
36     return false;
37   return theNode->type == XML_ELEMENT_NODE;
38 }
39
40 bool isNode(xmlNodePtr theNode, const char* theNodeName, ...)
41 {
42   const xmlChar* aName = theNode->name;
43   if (!aName || !isElementNode(theNode)) {
44     return false;
45   }
46   if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) {
47     return true;
48   }
49   va_list args;  // define argument list variable
50   va_start(args, theNodeName);  // init list; point to last defined argument
51   while (true) {
52     char *anArg = va_arg (args, char*);  // get next argument
53     if (anArg == NULL)
54       break;
55     if (!xmlStrcmp(aName, (const xmlChar *) anArg)) {
56       va_end(args);  // cleanup the system stack
57       return true;
58     }
59   }
60   va_end(args);  // cleanup the system stack
61   return false;
62 }
63
64 bool isAttributeNode(xmlNodePtr theNode)
65 {
66   if(!isElementNode(theNode))
67     return false;
68   // it's parent is "feature" or "source" or page ("case" or "box")
69   if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE,
70                          WDG_GROUP, WDG_OPTIONALBOX,
71                          WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL))
72     return false;
73
74   //it should not be a "source" or a "validator" node
75   bool isLogical = isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NULL);
76   // here must be only widgets not connected to attributes
77   bool isPagedContainer = isNode(theNode, WDG_TOOLBOX_BOX,
78                                           WDG_GROUP,
79                                           WDG_SWITCH_CASE,  NULL);
80   return !isLogical && !isPagedContainer;
81 }
82
83 bool isWidgetNode(xmlNodePtr theNode)
84 {
85   if(!isElementNode(theNode))
86     return false;
87   // it's parent is "feature" or "source" or a page ("box", "case")
88   if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, WDG_GROUP, WDG_OPTIONALBOX,
89                          WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL))
90     return false;
91
92   //it should not be a "source" or a "validator" node
93   return !isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NULL);
94 }
95
96 // widget api?
97 bool isCaseNode(xmlNodePtr theNode)
98 {
99   if(!isElementNode(theNode))
100     return false;
101
102   return isNode(theNode, WDG_OPTIONALBOX, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL);
103 }
104
105 bool hasChild(xmlNodePtr theNode)
106 {
107   xmlNodePtr aNode = theNode->children;
108   for (; aNode; aNode = aNode->next) {
109     if (isElementNode(theNode)) {
110       return true;
111     }
112   }
113   return false;
114 }
115
116 bool hasParent(xmlNodePtr theNode)
117 {
118   xmlNodePtr aNode = theNode->parent;
119   if (!aNode) {
120     return false;
121   }
122   for (; aNode; aNode = aNode->next) {
123     if (isElementNode(theNode)) {
124       return true;
125     }
126   }
127   return false;
128 }
129
130 bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...)
131 {
132   if (!hasParent(theNode)) {
133     return false; // have no parents at all
134   }
135   xmlNodePtr aNode = theNode->parent;
136   const xmlChar* aName = aNode->name;
137   if (!aName || !isElementNode(aNode)) {
138     return false;
139   }
140   if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) {
141     return true;
142   }
143   va_list args;  // define argument list variable
144   va_start(args, theNodeName);  // init list; point to last defined argument
145   while (true) {
146     char *anArg = va_arg (args, char*);  // get next argument
147     if (anArg == NULL)
148       break;
149     if (!xmlStrcmp(aName, (const xmlChar *) anArg)) {
150       va_end(args);  // cleanup the system stack
151       return true;
152     }
153   }
154   va_end(args);  // cleanup the system stack
155   return false;
156 }
157
158 xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const std::vector<const char*>& theNodeNames)
159 {
160   if (!hasParent(theNode)) {
161     return 0; // have no parents at all
162   }
163   xmlNodePtr aNode = theNode->parent;
164   const xmlChar* aName = aNode->name;
165   if (!aName || !isElementNode(aNode)) {
166     return 0;
167   }
168   for (size_t anIndex = 0; anIndex < theNodeNames.size(); ++anIndex) {
169     if (!xmlStrcmp(aName, (const xmlChar *) theNodeNames[anIndex]))
170       return aNode;
171   }
172   return hasParentRecursive(aNode, theNodeNames);
173 }
174
175 xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...)
176 {
177   std::vector<const char*> aNodeNames;
178   va_list args;  // define argument list variable
179   va_start(args, theNodeName);  // init list; point to last defined argument
180   aNodeNames.push_back(theNodeName);
181   while (true) {
182     char *anArg = va_arg (args, char*);  // get next argument
183     if (anArg == NULL)
184       break;
185     aNodeNames.push_back(anArg);
186   }
187   va_end(args);  // cleanup the system stack
188   return hasParentRecursive(theNode, aNodeNames);
189 }
190
191 bool getParametersInfo(xmlNodePtr theNode, std::string& outPropertyId,
192                       std::list<std::string>& outValidatorParameters)
193 {
194   //Property id:
195   char* anIdProp = (char*) xmlGetProp(theNode, BAD_CAST _ID);
196   if (!anIdProp || anIdProp[0] == 0) {
197     return false;
198   }
199   outPropertyId = std::string(anIdProp);
200
201   //Property parameters:
202   char* aParamProp = (char*) xmlGetProp(theNode, BAD_CAST _PARAMETERS);
203   if (aParamProp && aParamProp[0] != 0) {
204     std::string aPropString = std::string(aParamProp);
205     std::stringstream aPropStringStream(aPropString);
206     char COMMA_DELIM = ',';
207     std::string aParameter;
208     while (std::getline(aPropStringStream, aParameter, ',')) {
209       outValidatorParameters.push_back(aParameter);
210     }
211   }
212   return true;
213 }
214
215 std::string library(const std::string& theLibName)
216 {
217   if(theLibName.empty())
218     return std::string();
219   std::string aLibName = theLibName;
220 #ifndef WIN32
221   static std::string aLibExt( ".so" );
222   if (aLibName.size() < 3 || aLibName.substr(0, 3) !="lib") {
223     aLibName = "lib" + aLibName;
224   }
225 #else
226   static std::string aLibExt(".dll");
227 #endif
228   std::string anExt = aLibName.substr(aLibName.size() - 4);
229   if (anExt != aLibExt)
230     aLibName += aLibExt;
231
232   return aLibName;
233 }
234
235 bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
236
237 std::string getProperty(xmlNodePtr theNode, const char* thePropName)
238 {
239   std::string result = "";
240   xmlChar* aPropChars = xmlGetProp(theNode, BAD_CAST thePropName);
241   if (!aPropChars || aPropChars[0] == 0)
242     return result;
243   result = std::string((char*)aPropChars);
244   xmlFree(aPropChars);
245
246   std::string::iterator new_end = std::unique(result.begin(), result.end(), BothAreSpaces);
247   result.erase(new_end, result.end());
248
249   return result;
250 }
251
252 std::string getContent(xmlNodePtr theNode)
253 {
254   std::string result = "";
255   xmlChar* aContent = xmlNodeGetContent(theNode);
256   if (!aContent || aContent[0] == 0)
257     return result;
258   result = std::string((char*)aContent);
259   xmlFree(aContent);
260   return result;
261 }
262
263 std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName)
264 {
265   return normalize(getProperty(theNode, thePropName));
266 }
267
268 bool getBooleanAttribute(xmlNodePtr theNode, const char* theAttributeName, bool theDefault)
269 {
270   std::string prop = normalize(getProperty(theNode, theAttributeName));
271   bool result = theDefault;
272   if (prop == "true" || prop == "1") {
273     result = true;
274   } else if (prop == "false" || prop == "0") {
275     result = false;
276   }
277   return result;
278 }
279
280 CONFIG_EXPORT std::string normalize(const char* theString)
281 {
282   if (!theString)
283     return std::string();
284   return normalize(std::string(theString));
285 }
286
287 CONFIG_EXPORT std::string normalize(const std::string& theString)
288 {
289   std::string result = theString;
290   std::transform(result.begin(), result.end(), result.begin(), ::tolower);
291   return result;
292 }