Branch.cc
Go to the documentation of this file.
1 
11 #include <utl/Reader.h>
12 #include <utl/Branch.h>
13 #include <utl/XercesUtil.h>
14 
15 #include <utl/ErrorLogger.h>
16 #include <utl/UnitGrammar.h>
17 #include <utl/ExpressionParser.h>
18 #include <utl/AugerException.h>
19 #include <utl/UTCDateTime.h>
20 #include <utl/StringCompare.h>
21 
22 #include <utl/Function.h>
23 
24 #include <xercesc/util/XercesVersion.hpp>
25 #if _XERCES_VERSION >= 30000
26 # define HAVE_XERCES3
27 # include <xercesc/dom/DOMLSSerializer.hpp>
28 #else
29 # include <xercesc/framework/MemBufFormatTarget.hpp>
30 #endif
31 #include <xercesc/dom/DOMImplementation.hpp>
32 #include <xercesc/dom/DOMImplementationLS.hpp>
33 
34 // this is here only for the AsString function, which should be in a utils section
35 #include <utl/ReaderErrorReporter.h>
36 
37 #include <boost/tokenizer.hpp>
38 #include <boost/lexical_cast.hpp>
39 #include <boost/algorithm/string/trim.hpp>
40 #include <boost/lambda/lambda.hpp>
41 
42 using namespace utl;
43 using namespace xercesc;
44 using namespace std;
45 
46 
47 inline
48 void
50  const
51 {
52  if (*this)
53  return;
54 
55  WARNING(fWarning);
56  const string err = "Operating on null-Branch. " + fWarning;
57  ERROR(err);
58  throw XMLParseException(err);
59 }
60 
61 
62 Branch
64  const
65 {
66  ZeroBranchCheck();
67  const auto ownerDoc = GetDOMNode()->getOwnerDocument();
68  if (ownerDoc)
69  return Branch(fOwner, ownerDoc->getDocumentElement());
70  else {
71  Branch b(fOwner, nullptr);
72  b.SetWarning("Owner document (top branch) not found.");
73  return b;
74  }
75 }
76 
77 
78 Branch
80  const
81 {
82  ZeroBranchCheck();
83 
84  if (fDOMNode->getNodeType() != DOMNode::ELEMENT_NODE)
85  return Branch();
86  DOMNode* const parentNode = fDOMNode->getParentNode();
87  if (!parentNode || parentNode->getNodeType() != DOMNode::ELEMENT_NODE)
88  return Branch();
89  return Branch(fOwner, parentNode);
90 }
91 
92 
94 
97 Branch
99  const
100 {
101  ZeroBranchCheck();
102 
103  DOMNode* childNode = fDOMNode->getFirstChild();
104  while (childNode && childNode->getNodeType() != DOMNode::ELEMENT_NODE)
105  childNode = childNode->getNextSibling();
106 
107  Branch b(fOwner, childNode);
108  if (!childNode) {
109  ostringstream warn;
110  warn << "First child in branch '" << GetName() << "' not found.";
111  b.SetWarning(warn.str());
112  }
113  return b;
114 }
115 
116 
118 
123 Branch
124 Branch::GetChild(const string& requestedName,
125  AttributeMap requestedAttributeMap)
126  const
127 {
128  ZeroBranchCheck();
129 
130  requestedAttributeMap.erase("unit");
131  requestedAttributeMap.erase("UNIT");
132  requestedAttributeMap.erase("Unit");
133  requestedAttributeMap.erase("variables");
134  requestedAttributeMap.erase("VARIABLES");
135  requestedAttributeMap.erase("Variables");
136 
137  for (DOMNode* childNode = fDOMNode->getFirstChild();
138  childNode; childNode = childNode->getNextSibling())
139 
140  if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {
141 
142  const string foundName = AsString(childNode->getNodeName());
143 
144  if (foundName == requestedName) {
145 
146  // Get all the attributes into a map.
147  AttributeMap foundAttributeMap;
148  const DOMNamedNodeMap* const attributes = childNode->getAttributes();
149 
150  for (unsigned int i = 0; i < attributes->getLength(); ++i) {
151 
152  const DOMNode* const attr = attributes->item(i);
153 
154  foundAttributeMap.insert(make_pair(AsString(attr->getNodeName()),
155  AsString(attr->getNodeValue())));
156 
157  } // filled up foundAttributeMap
158 
159  // First, discard any unit attributes in either the found or requested maps.
160  // Units are treated as a special case.
161  foundAttributeMap.erase("unit");
162  foundAttributeMap.erase("UNIT");
163  foundAttributeMap.erase("Unit");
164  foundAttributeMap.erase("variables");
165  foundAttributeMap.erase("VARIABLES");
166  foundAttributeMap.erase("Variables");
167 
168  // Check for exact match between remaining attributes and attribute
169  // values in the requested and found maps
170  if (foundAttributeMap.size() == requestedAttributeMap.size()) {
171 
172  bool foundIt = true;
173 
174  // try to disqualify equality
175  for (auto foundIter = foundAttributeMap.begin();
176  foundIter != foundAttributeMap.end(); ++foundIter) {
177 
178  const auto requestedIter = requestedAttributeMap.find(foundIter->first);
179  if (requestedIter == requestedAttributeMap.end() ||
180  foundIter->second != requestedIter->second) {
181  foundIt = false;
182  break;
183  }
184 
185  }
186 
187  if (foundIt)
188  return Branch(fOwner, childNode);
189 
190  }
191 
192  } // same name
193 
194  } // condition ELEMENT_NODE
195 
196  Branch b;
197  ostringstream warn;
198  warn << "Child <" << requestedName << "> in branch <"
199  << GetName() << "> not found";
200  b.SetWarning(warn.str());
201  return b; // null-branch
202 }
203 
204 
206 
210 Branch
211 Branch::GetChild(const string& requestedName)
212  const
213 {
214  // don't ZeroBranchCheck() here
215  AttributeMap dummy;
216  return GetChild(requestedName, dummy);
217 }
218 
219 
220 Branch
221 Branch::GetChild(const string& requestedName, const string& att)
222  const
223 {
224  // don't ZeroBranchCheck() here
225 
226  using namespace boost;
227 
228  if (att.empty())
229  return GetChild(requestedName);
230 
231  char_separator<char> aSep(" ");
232  char_separator<char> kvSep("=");
233  typedef tokenizer<char_separator<char> > Tokenizer;
234  Tokenizer aTok(att, aSep);
235  AttributeMap attMap;
236  for (Tokenizer::const_iterator aIt = aTok.begin(); aIt != aTok.end(); ++aIt) {
237  string key;
238  string value;
239  Tokenizer kvTok(*aIt, kvSep);
240  Tokenizer::const_iterator kvIt = kvTok.begin();
241  if (kvIt != kvTok.end()) {
242  key = *kvIt;
243  ++kvIt;
244  if (kvIt != kvTok.end())
245  value = *kvIt;
246  }
247  attMap[key] = value;
248  }
249 
250  return GetChild(requestedName, attMap);
251 }
252 
253 
254 unsigned int
256  const
257 {
258  unsigned int i = 0;
259  for (Branch b = GetFirstChild(); b; ++b)
260  ++i;
261  return i;
262 }
263 
264 
268  const
269 {
270  ZeroBranchCheck();
271 
272  AttributeMap attrMap;
273 
274  const DOMNamedNodeMap* const attributes = fDOMNode->getAttributes();
275  for (unsigned int i = 0; i < attributes->getLength(); ++i) {
276  const DOMNode* const attr = attributes->item(i);
277  attrMap[AsString(attr->getNodeName())] = AsString(attr->getNodeValue());
278  }
279  return attrMap;
280 }
281 
282 
283 Branch
285  const
286 {
287  ZeroBranchCheck();
288 
289  DOMNode* siblingNode = fDOMNode->getNextSibling();
290 
291  while (siblingNode && siblingNode->getNodeType() != DOMNode::ELEMENT_NODE)
292  siblingNode = siblingNode->getNextSibling();
293 
294  Branch b(fOwner, siblingNode);
295  if (!siblingNode) {
296  ostringstream warn;
297  warn << "Next sibling of branch <" << GetName() << "> not found";
298  b.SetWarning(warn.str());
299  }
300  return b;
301 }
302 
303 
304 Branch
306  const
307 {
308  ZeroBranchCheck();
309 
310  DOMNode* siblingNode = fDOMNode->getPreviousSibling();
311 
312  while (siblingNode && siblingNode->getNodeType() != DOMNode::ELEMENT_NODE)
313  siblingNode = siblingNode->getPreviousSibling();
314 
315  Branch b(fOwner, siblingNode);
316  if (!siblingNode) {
317  ostringstream warn;
318  warn << "Next sibling of branch <" << GetName() << "> not found";
319  b.SetWarning(warn.str());
320  }
321  return b;
322 }
323 
324 
325 Branch
326 Branch::GetSibling(const string& requestedName, AttributeMap& attributeMap)
327  const
328 {
329  ZeroBranchCheck();
330 
331  // back up to the parent.
332  DOMNode* const parentNode = fDOMNode->getParentNode();
333 
334  Branch parentBranch(fOwner, parentNode);
335 
336  if (!parentNode) {
337  ostringstream warn;
338  warn << "Parent of branch <" << GetName() << "> not found";
339  parentBranch.SetWarning(warn.str());
340  }
341 
342  return parentBranch.GetChild(requestedName, attributeMap);
343 }
344 
345 
346 Branch
347 Branch::GetSibling(const string& requestedName)
348  const
349 {
350  // don't ZeroBranchCheck() here
351  AttributeMap dummy;
352  return GetSibling(requestedName, dummy);
353 }
354 
355 
357 
362 Branch
363 Branch::GetSibling(const string& requestedName, const string& id)
364  const
365 {
366  // don't ZeroBranchCheck() here
367  AttributeMap idMap;
368  idMap["id"] = id;
369  return GetSibling(requestedName, idMap);
370 }
371 
372 
373 string
375  const
376 {
377  ZeroBranchCheck();
378 
379  return AsString(fDOMNode->getNodeName());
380 }
381 
382 
383 // -------------------- GetData methods ------------------------------
384 
386 
389 string
391  const
392 {
393  ZeroBranchCheck();
394 
395  // Find the data residing beneath this tag
396  const DOMNodeList* const dataNodes = fDOMNode->getChildNodes();
397 
398  if (!dataNodes)
399  return string();
400 
401  string dataString;
402 
403  for (unsigned int k = 0; k < dataNodes->getLength(); ++k) {
404 
405  const DOMNode* const currentNode = dataNodes->item(k);
406 
407  // For TEXT nodes, postpend the node onto the dataString. NB if
408  // there are multiple TEXT nodes beneath this element, and they
409  // are, for example, separated by one or more sub- elements,
410  // these text nodes will be concatenated into a single data
411  // string.
412  if (currentNode->getNodeType() == DOMNode::TEXT_NODE)
413  dataString += AsString(currentNode->getNodeValue());
414 
415  }
416 
417  boost::trim(dataString);
418  return dataString;
419 }
420 
421 
423 
426 double
428  const
429 {
430  ZeroBranchCheck();
431 
432  double unit = 1;
433 
434  // Check for a unit attribute
435  const DOMNamedNodeMap* const attributes = fDOMNode->getAttributes();
436 
437  if (attributes) {
438 
439  string unitString;
440  for (unsigned int j = 0; j < attributes->getLength(); ++j) {
441  const DOMNode* const attribute = attributes->item(j);
442  const string name = AsString(attribute->getNodeName());
443  if (StringEquivalent(name, "unit")) {
444  unitString = AsString(attribute->getNodeValue());
445  break;
446  }
447  }
448 
449  // If found, convert the unit to the appropriate scale factor,
450  // otherwise set scale factor to 1.
451  if (!unitString.empty()) {
452  AugerUnitParser up;
453  unit = up.Evaluate(unitString);
454  }
455  }
456 
457  return unit;
458 }
459 
460 
462 vector<string>
463 Branch::GetListOfVariables() // for functions from XML attributes
464  const
465 {
466  ZeroBranchCheck();
467 
468  // Check for a unit attribute
469  const DOMNamedNodeMap* const attributes = fDOMNode->getAttributes();
470 
471  vector<string> variables;
472 
473  if (attributes) {
474  istringstream iss;
475  string word;
476  for (unsigned int i = 0; i < attributes->getLength(); ++i) {
477  const DOMNode* const attr = attributes->item(i);
478  const string nodeName = AsString(attr->getNodeName());
479  if (StringEquivalent(nodeName, "variables")) {
480  const string s = AsString(attr->getNodeValue());
481  iss.clear();
482  iss.str(s);
483  while (iss >> word)
484  variables.push_back(word);
485  }
486  }
487  }
488 
489  return variables;
490 }
491 
492 
495 {
496  /* Protect against self-assignment */
497  if (*this != b) {
498  // no need for ZeroBranchCheck(); zero-Branch is copyable
499  fDOMNode = b.fDOMNode;
500  fOwner = b.fOwner;
501  fWarning = b.fWarning;
502  }
503  return *this;
504 }
505 
506 
508 void
510  const
511 {
512  // don't ZeroBranchCheck() here
513 
514  // do not use castData, as in this case
515  // we want to return the ENTIRE string, including
516  // possible white space.
517  s = GetDataString();
518 }
519 
520 
521 // DV considered dangerous since user has to call free()
523 void
524 Branch::GetData(char*& /*c*/)
525  const
526 {
527  // do not use castData, as in this case
528  // we want to return the ENTIRE string, including
529  // possible white space. Do not forget to call free.
530 
531  /*const string s = GetDataString();
532  c = strdup(s.c_str());*/
533  ERROR("This method requires user to call free() after "
534  "done with the char*! Disabled for the moment.");
535  exit(1);
536 }
537 
538 
540 void
542  const
543 {
544  // don't ZeroBranchCheck() here
545  time = boost::lexical_cast<UTCDateTime>(GetDataString()).GetTimeStamp();
546 }
547 
548 
550 void
552  const
553 {
554  // don't ZeroBranchCheck() here
555  // DV why is vars not used anywhere?
556  /*utl::SymbolTable vars;
557  for (const auto &v : GetListOfVariables())
558  vars[v] = 0;*/
559  func = Function(GetDataString(), GetListOfVariables());
560 }
561 
562 
563 void
564 Branch::GetData(vector<TimeStamp>& vt)
565  const
566 {
567  // don't ZeroBranchCheck() here
568 
569  const string dataString = GetDataString();
570  istringstream iss(dataString);
571  string word;
572  while (iss >> word)
573  vt.push_back(boost::lexical_cast<UTCDateTime>(word).GetTimeStamp());
574 }
575 
576 
577 Branch
579  const
580 {
581  // no need for ZeroBranchCheck()
582 
583  if (fDOMNode) {
584  const ReaderStringInput readerInput(String());
585  const Reader r(readerInput);
586  return r.GetTopBranch();
587  }
588  return Branch();
589 }
590 
591 
592 string
594  const
595 {
596  // this method does the same thing as GetDataString() but in a different way
597  // we should consider removing duplicate functionalities.
598 
599  ZeroBranchCheck();
600 
601  DOMImplementationLS* const impl =
602  DOMImplementationRegistry::getDOMImplementation(
603  XercesPtrX(XMLString::transcode("LS")).Get()
604  );
605 #ifdef HAVE_XERCES3
606  XercesPtr<DOMLSSerializer> serializer(impl->createLSSerializer());
607  XercesPtrC dom(XMLString::transcode(serializer->writeToString(fDOMNode)));
608  const string res(dom.Get());
609  return res;
610 #else
611  XercesPtr<DOMWriter> writer(impl->createDOMWriter());
612  MemBufFormatTarget memForm;
613  writer->writeNode(&memForm, *fDOMNode);
614  return string((const char*)memForm.getRawBuffer());
615 #endif
616 }
617 
618 
619 void
621  const
622 {
623  const vector<double> x = GetChild("x").Get<vector<double>>();
624  vector<double> y = GetChild("y").Get<vector<double>>();
625  Branch scaleYB = GetChild("scaleY");
626  if (scaleYB) {
627  const double s = scaleYB.Get<double>();
628  transform(y.begin(), y.end(), y.begin(), [&s](const auto& elem) { return elem * s; });
629  }
630  tf.Clear();
631  for (unsigned int i = 0, n = x.size(); i < n; ++i)
632  tf.PushBack(x[i], y[i]);
633 }
634 
635 
636 #define UTL_BRANCH_GETDATA_WITH_CAST_ONLY(_Type_...) \
637 void \
638 Branch::GetData(_Type_& t) \
639  const \
640 { \
641  CastData(t); \
642 }
643 
649 
650 #undef UTL_BRANCH_GETDATA_WITH_CAST_ONLY
Branch GetTopBranch() const
Definition: Branch.cc:63
void SetWarning(const std::string &wrn)
Definition: Branch.h:279
Branch GetParent() const
Definition: Branch.cc:79
std::string AsString(const XMLCh *const xStr)
Definition: XercesUtil.h:77
std::string String() const
Dump the branch into a string.
Definition: Branch.cc:593
Class to hold collection (x,y) points and provide interpolation between them.
std::map< std::string, std::string > AttributeMap
Definition: Branch.h:24
std::vector< std::string > GetListOfVariables() const
Get the list of variables of a function.
Definition: Branch.cc:463
void PushBack(const double x, const double y)
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
int exit
Definition: dump1090.h:237
Exception for errors encountered when parsing XML.
bool StringEquivalent(const std::string &a, const std::string &b, Predicate p)
Utility to compare strings for equivalence. It takes a predicate to determine the equivalence of indi...
Definition: StringCompare.h:38
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
Branch GetTopBranch() const
Get the top Branch (represents same entity as document node)
Definition: Reader.h:45
AttributeMap GetAttributes() const
Get a map&lt;string, string&gt; containing all the attributes of this Branch.
Definition: Branch.cc:267
Branch GetNextSibling() const
Get next sibling of this branch.
Definition: Branch.cc:284
Branch & operator=(const Branch &b)
Definition: Branch.cc:494
Utility for parsing XML files.
Definition: Reader.h:25
Class representing a document branch.
Definition: Branch.h:107
xercesc::DOMNode * fDOMNode
Definition: Branch.h:336
constexpr double s
Definition: AugerUnits.h:163
This just defines a type which holds some character data to be parsed by the Reader.
Definition: Reader.h:88
unsigned int GetNChildren() const
Definition: Branch.cc:255
void ZeroBranchCheck() const
Definition: Branch.cc:49
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
std::string GetName() const
function to get the Branch name
Definition: Branch.cc:374
Evaluate functions given in a string. The real work is done by the ExpressionParser class...
Definition: Function.h:27
const double unit[npar]
Definition: UnivRec.h:76
std::string GetDataString() const
function to get the data inside an element as one big string
Definition: Branch.cc:390
Branch Clone() const
returns a clone of this branch.
Definition: Branch.cc:578
std::string fWarning
Definition: Branch.h:338
XercesPtr< XMLCh > XercesPtrX
Definition: XercesUtil.h:69
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
Branch GetFirstChild() const
Get first child of this Branch.
Definition: Branch.cc:98
Branch GetPreviousSibling() const
Get previous sibling of this branch.
Definition: Branch.cc:305
Branch GetSibling(const std::string &childName) const
Get sibling by name.
Definition: Branch.cc:347
boost::shared_ptr< BranchOwner > fOwner
Definition: Branch.h:334
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
#define UTL_BRANCH_GETDATA_WITH_CAST_ONLY(_Type_...)
Definition: Branch.cc:636
double GetUnit() const
Get the unit of the token.
Definition: Branch.cc:427

, generated on Tue Sep 26 2023.