EMANE  1.2.1
layerconfiguration.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 - Adjacent Link LLC, Bridgewater, New Jersey
3  * Copyright (c) 2009-2010 - DRS CenGen, LLC, Columbia, Maryland
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of DRS CenGen, LLC nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "layerconfiguration.h"
35 #include "configurationparser.h"
36 
37 #include "emane/exception.h"
39 
40 #include <cstdlib>
41 #include <memory>
42 #include <libxml/xmlstring.h>
43 
44 
46  sType_{sType}
47 { }
48 
49 
50 void
52  const std::string & sURI)
53 {
54  setPathAndFile(sURI);
55 
56  xmlDocPtr pDoc{ConfigurationParser{}.parse(sURI)};
57 
58  xmlNodePtr pRoot{xmlDocGetRootElement(pDoc)};
59 
60  if (!xmlStrEqual(pRoot->name, reinterpret_cast<const xmlChar *>(pszName)))
61  {
62  xmlFreeDoc(pDoc);
63 
64  throw makeException<ParseException>(
65  "Failed to parse document in %s.\n\n"
66  "Possible reason(s):\n"
67  " * %s: Document root node is not '%s'\n",
68  sURI.c_str(),
69  sURI.c_str(),
70  pszName);
71  }
72 
73  // Allow derived-class to extract info from root
75 
76  sName_ = getAttrVal(pRoot, "name");
77 
78  doProcessChildren(pRoot, params_);
79 
80  xmlFreeDoc(pDoc);
81 }
82 
83 
84 
85 void
87 {
88  //default: do nothing
89 }
90 
91 
92 void
94  ParamMap & paramMap)
95 {
96  // process children
97  xmlNodePtr pNode = pParent->children;
98 
99  while (pNode)
100  {
101  if (pNode->type == XML_ELEMENT_NODE)
102  {
103  if (xmlStrEqual(pNode->name,
104  reinterpret_cast<const xmlChar*>("param")))
105  {
106  doProcessParam(paramMap, pNode);
107  }
108  else if(xmlStrEqual(pNode->name,
109  reinterpret_cast<const xmlChar*>("paramlist")))
110  {
111  doProcessParamlist(paramMap, pNode);
112  }
113  else
114  {
115  doProcessChildNode(pNode);
116  }
117  }
118 
119  pNode = pNode->next;
120  }
121 }
122 
123 
124 void
126 {
127  //default: do nothing
128 }
129 
130 
131 void
133  xmlNodePtr pParamNode)
134 {
135  std::string sItemName{getAttrVal(pParamNode, "name")};
136 
137  if(paramMap.find(sItemName) != paramMap.end())
138  {
139  throw makeException<ParseException>(
140  "Failed to parse configuration document.\n\n"
141  "Possible reason(s):\n"
142  " * Duplicate configuration item '%s'\n",
143  sItemName.c_str());
144  }
145 
146  paramMap.insert(
147  std::make_pair(sItemName,
148  ParamStringValues{getAttrVal(pParamNode, "value")}));
149 }
150 
151 
152 void
154  xmlNodePtr pParamlistNode)
155 {
156  std::string sItemName{getAttrVal(pParamlistNode, "name")};
157 
158  if(paramMap.find(sItemName) != paramMap.end())
159  {
160  throw makeException<ParseException>(
161  "Failed to parse configuration document.\n\n"
162  "Possible reason(s):\n"
163  " * Duplicate configuration item '%s'\n",
164  sItemName.c_str());
165  }
166 
167  paramMap.insert(std::make_pair(sItemName, ParamStringValues{}));
168 
169  xmlNodePtr pItem = pParamlistNode->children;
170 
171  // DTD validation enforces at least one item element here
172  while(pItem)
173  {
174  if(xmlStrEqual(pItem->name, reinterpret_cast<const xmlChar*>("item")))
175  {
176  paramMap[sItemName].push_back(getAttrVal(pItem, "value"));
177  }
178 
179  pItem = pItem->next;
180  }
181 }
182 
183 
184 std::string
186  const char * attributename)
187 {
188  std::string sVal{};
189 
190  xmlChar * pxzVal =
191  xmlGetProp(pNode, reinterpret_cast<const xmlChar*>(attributename));
192 
193  if(pxzVal)
194  {
195  sVal = reinterpret_cast<const char*>(pxzVal);
196 
197  xmlFree(pxzVal);
198  }
199 
200  return sVal;
201 }
202 
203 
204 std::uint16_t
206  const char * attributename)
207 {
209  getAttrVal(pNode, attributename)}.toUINT16();
210 }
211 
212 
213 void
215 {
216  ParamMap localParamMap{};
217 
218  doProcessChildren(pRoot, localParamMap);
219 
220  for(auto param : localParamMap)
221  {
222  ParamMapIter pos{params_.find(param.first)};
223  if(pos != params_.end())
224  {
225  params_.erase(pos);
226  }
227  params_.insert(param);
228  }
229 }
230 
231 
234 {
235  ConfigurationUpdateRequest request{};
236 
237  for (auto param : params_)
238  {
239  request.push_back(std::make_pair(param.first, param.second));
240  }
241 
242  return request;
243 }
244 
245 
246 std::string
248 {
249  return sType_;
250 }
251 
252 
253 std::string
255 {
256  return sLibrary_;
257 }
258 
259 
260 std::string
262 {
263  return sDefinitionPath_;
264 }
265 
266 
267 std::string
269 {
270  return sDefinitionFile_;
271 }
272 
273 
274 void
276 {
277  /* Eval location and name */
278  size_t pos = sURI.npos;
279 
280  if ((pos = sURI.rfind("/")) != sURI.npos)
281  {
282  /* *nix */
283  sDefinitionPath_ = sURI.substr(0, pos+1); //includes the '/'
284  sDefinitionFile_ = sURI.substr(pos+1); //to the end
285  }
286  else if ( (pos = sURI.rfind("\\")) != sURI.npos)
287  {
288  /* windoze */
289  sDefinitionPath_ = sURI.substr(0, pos+1); //includes the '\'
290  sDefinitionFile_ = sURI.substr(pos+1); //to the end
291  }
292  else
293  {
294  sDefinitionPath_ = "";
295  sDefinitionFile_ = sURI;
296  }
297 }
virtual void doProcessChildNode(xmlNodePtr pNode)
virtual void doProcessChildren(xmlNodePtr pParent, ParamMap &paramMap)
std::string getDefinitionPath() const
std::string getLibrary() const
Wrapper around the libxml2 XML parsing capabilities for EMANE.
xmlDocPtr parse(const std::string &sURI)
std::uint16_t getAttrValNumeric(xmlNodePtr pNode, const char *attributename)
void doProcessParam(ParamMap &paramMap, xmlNodePtr pParamNode)
std::string getDefinitionFile() const
void processDefinition(const char *pxzName, const std::string &sURI)
const ConfigurationUpdateRequest getConfigurationUpdateRequest()
void overlayParams(xmlNodePtr pNode)
LayerConfiguration(std::string sType)
std::vector< ConfigurationNameStringValues > ConfigurationUpdateRequest
virtual void doProcessRootAttributes(xmlNodePtr pRoot)
void setPathAndFile(const std::string sURI)
Parameter conversion class with range checks.
std::string getAttrVal(xmlNodePtr pNode, const char *attributename)
void doProcessParamlist(ParamMap &paramMap, xmlNodePtr pParamlistNode)