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