Salome HOME
Merge branch 'Dev_0.7.1' of newgeom:newgeom.git into Dev_0.7.1
[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_ValidatorMessage.h>
14 #include <Config_SelectionFilterMessage.h>
15 #include <Config_PropManager.h>
16
17 #include <Events_Loop.h>
18 #include <Events_Error.h>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
21
22 #include <fstream>
23
24 #ifdef WIN32
25 #pragma warning(disable : 4996) // for getenv
26 #endif
27
28 #ifdef _DEBUG
29 #include <iostream>
30 #endif
31
32 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
33     : myXmlDoc(NULL)
34 {
35   std::string prefix = ""; 
36   Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
37   if (aProp)
38     prefix = aProp->value();
39   /*
40    * Get path to *.xml files (typically ./bin/../plugins/)
41
42    * the problem: application may be launched using python executable,
43    * to use environment variable (at least for the current moment)
44    */
45   if (prefix.empty()) {
46     char* anEnv = getenv("NEW_GEOM_CONFIG_FILE");
47     if (anEnv) {
48       prefix = std::string(anEnv);
49     }
50   }
51 #ifdef WIN32
52     prefix += "\\";
53 #else
54     prefix += "/";
55 #endif
56   myDocumentPath = prefix + theXmlFileName;
57   std::ifstream aTestFile(myDocumentPath);
58   if (!aTestFile) Events_Error::send("Unable to open " + myDocumentPath);
59   aTestFile.close();
60 }
61
62 Config_XMLReader::~Config_XMLReader()
63 {
64   xmlFreeDoc(myXmlDoc);
65 }
66
67 /*!
68  * Read all nodes in associated xml file,
69  * recursively if processChildren(xmlNode) is true for the xmlNode.
70  * For each read node the processNode will be called.
71  */
72 void Config_XMLReader::readAll()
73 {
74   xmlNodePtr aRoot = findRoot();
75   readRecursively(aRoot);
76 }
77
78 /*!
79  * Allows to customize reader's behavior for a node. Virtual.
80  * The default impl does nothing. (In debug mode prints
81  * some info)
82  */
83 void Config_XMLReader::processNode(xmlNodePtr theNode)
84 {
85   if (isNode(theNode, NODE_SOURCE, NULL)) {
86     std::string aSourceFile = getProperty(theNode, SOURCE_FILE);
87     Config_XMLReader aSourceReader = Config_XMLReader(aSourceFile);
88     readRecursively(aSourceReader.findRoot());
89 #ifdef _DEBUG
90     std::cout << "Config_XMLReader::sourced node: " << aSourceFile << std::endl;
91 #endif
92   } else if (isNode(theNode, NODE_VALIDATOR, NULL)) {
93     processValidator(theNode);
94   } else if (isNode(theNode, NODE_SELFILTER, NULL)) {
95     processSelectionFilter(theNode);
96   }
97 }
98
99 /*!
100  * Defines which nodes should be processed recursively. Virtual.
101  * The default impl is to read all nodes.
102  */
103 bool Config_XMLReader::processChildren(xmlNodePtr aNode)
104 {
105   return true;
106 }
107
108 /*!
109  * Returns xmlNodePtr to the root of reader's document
110  * or NULL if not found
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 /*!
134  * Calls processNode() for each child (for some - recursively)
135  * of the given node.
136  * \sa ReadAll()
137  */
138 void Config_XMLReader::readRecursively(xmlNodePtr theParent)
139 {
140   if (!theParent)
141     return;
142   xmlNodePtr aNode = theParent->xmlChildrenNode;
143   for (; aNode; aNode = aNode->next) {
144     //Still no text processing in features...
145     if (!isElementNode(aNode)) {
146       continue;
147     }
148     processNode(aNode);
149     if (processChildren(aNode)) {
150       readRecursively(aNode);
151     }
152   }
153 }
154
155 /*!
156  * void* -> xmlNodePtr
157  */
158 xmlNodePtr Config_XMLReader::node(void* theNode)
159 {
160   return static_cast<xmlNodePtr>(theNode);
161 }
162
163 /*!
164  * Gets xml node name
165  */
166 std::string Config_XMLReader::getNodeName(xmlNodePtr theNode)
167 {
168   std::string result = "";
169   char* aPropChars = (char*) theNode->name;
170   if (!aPropChars || aPropChars[0] == 0)
171     return result;
172   result = std::string(aPropChars);
173   return result;
174 }
175
176 /*!
177  * Retrieves all the necessary info from the validator node.
178  * Sends ValidatorLoaded event
179  */
180 void Config_XMLReader::processValidator(xmlNodePtr theNode)
181 {
182   Events_ID aValidatoEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED);
183   Events_Loop* aEvLoop = Events_Loop::loop();
184   std::shared_ptr<Config_ValidatorMessage> 
185     aMessage(new Config_ValidatorMessage(aValidatoEvent, this));
186   std::string aValidatorId;
187   std::list<std::string> aParameters;
188   getParametersInfo(theNode, aValidatorId, aParameters);
189   aMessage->setValidatorId(aValidatorId);
190   aMessage->setValidatorParameters(aParameters);
191   xmlNodePtr aFeatureOrWdgNode = theNode->parent;
192   if (isNode(aFeatureOrWdgNode, NODE_FEATURE, NULL)) {
193     aMessage->setFeatureId(getProperty(aFeatureOrWdgNode, _ID));
194   } else {
195     aMessage->setAttributeId(getProperty(aFeatureOrWdgNode, _ID));
196     aMessage->setFeatureId(myCurrentFeature);
197   }
198   aEvLoop->send(aMessage);
199 }
200
201 /*!
202  * Retrieves all the necessary info from the SelectionFilter node.
203  * Sends SelectionFilterLoaded event
204  */
205 void Config_XMLReader::processSelectionFilter(xmlNodePtr theNode)
206 {
207   Events_ID aFilterEvent = Events_Loop::eventByName(EVENT_SELFILTER_LOADED);
208   Events_Loop* aEvLoop = Events_Loop::loop();
209   std::shared_ptr<Config_SelectionFilterMessage> aMessage =
210       std::make_shared<Config_SelectionFilterMessage>(aFilterEvent, this);
211   std::string aSelectionFilterId;
212   std::list<std::string> aParameters;
213   getParametersInfo(theNode, aSelectionFilterId, aParameters);
214   aMessage->setSelectionFilterId(aSelectionFilterId);
215   aMessage->setFilterParameters(aParameters);
216
217   xmlNodePtr aFeatureOrWdgNode = theNode->parent;
218   if (isNode(aFeatureOrWdgNode, NODE_FEATURE, NULL)) {
219     aMessage->setFeatureId(getProperty(aFeatureOrWdgNode, _ID));
220   } else {
221     aMessage->setAttributeId(getProperty(aFeatureOrWdgNode, _ID));
222     aMessage->setFeatureId(myCurrentFeature);
223   }
224   aEvLoop->send(aMessage);
225 }