DABC (Data Acquisition Backbone Core)  2.9.9
ConfigIO.cxx
Go to the documentation of this file.
1 // $Id: ConfigIO.cxx 4476 2020-04-15 14:12:38Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "dabc/ConfigIO.h"
17 
18 #include "dabc/Configuration.h"
19 #include "dabc/Manager.h"
20 
21 #include <fnmatch.h>
22 #include <cstring>
23 
25  fCfg(cfg),
26  fCurrItem(0),
27  fCurrChld(0),
28  fCurrStrict(true),
29  fCgfId(id)
30 {
31 }
32 
34  fCfg(src.fCfg),
35  fCurrItem(src.fCurrItem),
36  fCurrChld(src.fCurrChld),
37  fCurrStrict(src.fCurrStrict),
38  fCgfId(src.fCgfId)
39 {
40 }
41 
42 bool dabc::ConfigIO::FindItem(const char* name)
43 {
44  if (fCurrItem==0) return false;
45 
46  if (fCurrChld==0)
47  fCurrChld = Xml::GetChild(fCurrItem);
48  else
49  fCurrChld = Xml::GetNext(fCurrChld);
50 
51  while (fCurrChld!=0) {
52  if (fCfg->IsNodeName(fCurrChld, name)) {
53  fCurrItem = fCurrChld;
54  fCurrChld = 0;
55  return true;
56  }
57  fCurrChld = Xml::GetNext(fCurrChld);
58  }
59 
60  return false;
61 }
62 
63 bool dabc::ConfigIO::CheckAttr(const char* name, const char* value)
64 {
65  // make extra check - if fCurrChld!=0 something was wrong already
66  if ((fCurrChld!=0) || (fCurrItem==0)) return false;
67 
68  bool res = true;
69 
70  if (value==0) {
71  res = Xml::HasAttr(fCurrItem, name);
72  } else {
73  const char* attr = Xml::GetAttr(fCurrItem, name);
74 
75  std::string sattr = attr ? fCfg->ResolveEnv(attr) : std::string("");
76 
77  if (fCurrStrict) {
78  res = sattr.empty() ? false : (sattr == value);
79  } else {
80  if (!sattr.empty()) {
81  res = (sattr == value);
82  if (!res) res = fnmatch(sattr.c_str(), value, FNM_NOESCAPE) == 0;
83  }
84  }
85  }
86 
87  // if attribute was not identified in the structure,
88  // current node pointer automatically ralled-back to parent that
89  // Worker::Find() method could try to find next item with probably correct attribute
90 
91  if (!res) {
92  fCurrChld = fCurrItem;
93  fCurrItem = Xml::GetParent(fCurrItem);
94  }
95 
96  return res;
97 }
98 
100 {
101  // make hack for the objects, which are not registered in the object manager,
102  // but which are want to use config files. Make special case:
103 
104  if ((obj!=0) && (obj->GetParent()==0) && (lvl==1) && (obj!=dabc::mgr())) return dabc::mgr();
105 
106  if (lvl==0) return obj;
107 
108  while ((obj!=0) && (lvl-->0)) obj = obj->GetParent();
109  return obj;
110 }
111 
113 {
114  if ((node==0) || (name==0) || (strlen(name)==0)) return node;
115 
116  const char* pos = strchr(name, '/');
117  if (pos==0) return fCfg->FindChild(node, name);
118 
119  std::string subname(name, pos-name);
120  return FindSubItem(fCfg->FindChild(node, subname.c_str()), pos+1);
121 }
122 
123 std::string dabc::ConfigIO::ResolveEnv(const char* value)
124 {
125  if ((value==0) || (*value==0)) return std::string();
126 
127  if ((strstr(value,"${")==0) || (fCfg==0)) return std::string(value);
128 
129  return fCfg->ResolveEnv(value, fCgfId);
130 }
131 
132 bool dabc::ConfigIO::ReadRecordField(Object* obj, const std::string &itemname, RecordField* field, RecordFieldsMap* fieldsmap)
133 {
134  // here we search all nodes in config file which are compatible with for specified object
135  // and config name. From all places we reconstruct all fields and attributes which can belong
136  // to the record
137 
138  if ((fCfg==0) || (obj==0)) return false;
139 
140  int maxlevel = 0;
141  Object* prnt = 0;
142  while ((prnt = GetObjParent(obj, maxlevel)) != 0) {
143  if (prnt==dabc::mgr()) break;
144  maxlevel++;
145  // if object want to be on the top xml level, count maxlevel+1 to add manager as artificial top parent
146  if (prnt->IsTopXmlLevel()) break;
147  }
148  // TODO: could we read objects which are not in manager?
149  if (prnt==0) return false;
150 
151  DOUT3("Start reading of obj %s item %s maxlevel %d", obj->ItemName().c_str(), itemname.c_str(), maxlevel);
152 
153  bool isany = false;
154 
155  // DOUT0("Start read of record maxlvl %d", maxlevel);
156 
157  // first loop - strict syntax in the selected context
158  // second loop - wildcard syntax in all contexts
159 
160  for (int dcnt=0;dcnt<2;dcnt++) {
161 
162  DOUT3("Switch to search mode %d", dcnt);
163 
164  // only in first case we skipping context node
165  int max_depth = 0;
166  fCurrItem = 0;
167  fCurrStrict = true;
168 
169  switch (dcnt) {
170  case 0:
171  fCurrItem = fCfg->fSelected;
172  max_depth = maxlevel - 1;
173  fCurrStrict = true;
174  break;
175  case 1:
176  fCurrItem = fCfg->RootNode();
177  max_depth = maxlevel;
178  fCurrStrict = false;
179  break;
180  default: EOUT("INTERNAL ERROR"); break;
181  }
182 
183  fCurrChld = 0;
184  int level = max_depth;
185 
186  while (level >= 0) {
187  // maximal level is manager itself, all other is several parents (if any)
188  prnt = (level==maxlevel) ? dabc::mgr() : GetObjParent(obj, level);
189 
190  DOUT3("Search with loop %d path level = %d obj = %s class %s", dcnt, level, DNAME(prnt), (prnt ? prnt->ClassName() : "---"));
191 
192 // DOUT3("Search with level = %d prnt = %p %s", level, prnt, DNAME(prnt));
193 
194  if (prnt == 0) return false;
195 
196  // DOUT0("+++ Search parent %s class %s level %d", prnt->GetName(), prnt->ClassName(), level);
197 
198  XMLNodePointer_t curr = fCurrItem;
199  // DOUT0("Search for parent %s level %d loop = %d", prnt->GetName(), level, dcnt);
200 
201  if (prnt->Find(*this)) {
202  DOUT3("Find parent of level:%d", level);
203  if (level-->0) continue;
204 
205  // in case of single field (configuration) we either check attribute in node itself
206  // or "value" attribute in child node in provided name
207 
208  XMLNodePointer_t itemnode = FindSubItem(fCurrItem, itemname.c_str());
209 
210  if (field!=0) {
211  const char* attrvalue = 0;
212  if (itemnode!=0) attrvalue = Xml::GetAttr(itemnode, "value");
213  if (attrvalue==0) attrvalue = Xml::GetAttr(fCurrItem, itemname.c_str());
214 
215  if (attrvalue!=0) {
216  field->SetStr(ResolveEnv(attrvalue));
217  DOUT3("For item %s find value %s", itemname.c_str(), attrvalue);
218  return true;
219  } else {
220  // try to find array of items
221  std::vector<std::string> arr;
222 
223  for (XMLNodePointer_t child = Xml::GetChild(itemnode); child!=0; child = Xml::GetNext(child)) {
224  if (strcmp(Xml::GetNodeName(child), "item")!=0) continue;
225  const char* arritemvalue = Xml::GetAttr(child,"value");
226  if (arritemvalue!=0)
227  arr.push_back(ResolveEnv(arritemvalue));
228  }
229 
230  if (arr.size()>0) {
231  field->SetStrVect(arr);
232  return true;
233  }
234  }
235  } else
236  if ((fieldsmap!=0) && (itemnode!=0)) {
237  isany = true;
238 
239  for (XMLAttrPointer_t attr = Xml::GetFirstAttr(itemnode); attr!=0; attr = Xml::GetNextAttr(attr)) {
240  const char* attrname = Xml::GetAttrName(attr);
241  const char* attrvalue = Xml::GetAttrValue(attr);
242  if ((attrname==0) || (attrvalue==0)) continue;
243 
244  if (!fieldsmap->HasField(attrname))
245  fieldsmap->Field(attrname).SetStr(ResolveEnv(attrvalue));
246  }
247 
248  for (XMLNodePointer_t child = Xml::GetChild(itemnode); child!=0; child = Xml::GetNext(child)) {
249 
250  if (strcmp(Xml::GetNodeName(child), "dabc:field")!=0) continue;
251 
252  const char* attrname = Xml::GetAttr(child,"name");
253  const char* attrvalue = Xml::GetAttr(child,"value");
254  if ((attrname==0) || (attrvalue==0)) continue;
255 
256  if (!fieldsmap->HasField(attrname))
257  fieldsmap->Field(attrname).SetStr(ResolveEnv(attrvalue));
258  }
259  }
260 
261  fCurrChld = 0;
262  } else
263  if ((curr != fCurrItem) || (fCurrChld != 0)) {
264  EOUT("FIXME: should not happen");
265  EOUT("FIXME: problem in hierarchy search for %s lvl %d prnt %s", obj->ItemName().c_str(), level, prnt->GetName());
266  EOUT("fCurrChld %p curr %p fCurrItem %p", fCurrChld, curr, fCurrItem);
267  break;
268  } else {
269  // FIX from 13.05.2015.
270  // Here was code to skip application node, now it is gone
271  // break;
272  }
273 
274  level++;
275 
276  if (level > max_depth) break;
277 
278  fCurrChld = fCurrItem;
279  fCurrItem = Xml::GetParent(fCurrItem);
280 
281  if (fCurrItem==0) {
282  EOUT("FIXME: Wrong hierarchy search level = %d maxlevel = %d chld %p item %p dcnt = %d", level, maxlevel, fCurrChld, fCurrItem, dcnt);
283  break;
284  }
285 
286  } // while (level >= 0) {
287 
288 // DOUT3("End of level loop");
289  }
290 
291  return isany;
292 }
293 
Interface class between xml configuration and dabc objects.
Definition: ConfigIO.h:38
bool FindItem(const char *name)
Definition: ConfigIO.cxx:42
std::string ResolveEnv(const char *value)
Definition: ConfigIO.cxx:123
bool ReadRecordField(Object *obj, const std::string &name, RecordField *field, RecordFieldsMap *fieldsmap)
Definition: ConfigIO.cxx:132
XMLNodePointer_t FindSubItem(XMLNodePointer_t node, const char *name)
Definition: ConfigIO.cxx:112
ConfigIO(Configuration *cfg, int id=-1)
Definition: ConfigIO.cxx:24
bool CheckAttr(const char *name, const char *value)
Check if item, found by FindItem routine, has attribute with specified value.
Definition: ConfigIO.cxx:63
static Object * GetObjParent(Object *obj, int lvl)
Definition: ConfigIO.cxx:99
Full-functional class to reading configuration from xml files.
Definition: Configuration.h:34
Base class for most of the DABC classes.
Definition: Object.h:116
bool IsTopXmlLevel() const
Return true if object should be searched in the top level of the xml file, thread safe
Definition: Object.cxx:185
std::string ItemName(bool compact=true) const
Produce string, which can be used as name argument in dabc::mgr.FindItem(name) call.
Definition: Object.cxx:1076
Object * GetParent() const
Returns pointer on parent object, thread safe
Definition: Object.h:286
const char * GetName() const
Returns name of the object, thread safe
Definition: Object.h:295
virtual const char * ClassName() const
Returns class name of the object instance.
Definition: Object.h:419
virtual bool Find(ConfigIO &cfg)
Method to locate object in xml file.
Definition: Object.cxx:929
bool SetStr(const std::string &v)
Definition: Record.cxx:1127
bool SetStrVect(const std::vector< std::string > &vect)
Definition: Record.cxx:1162
bool HasField(const std::string &name) const
Definition: Record.cxx:1382
RecordField & Field(const std::string &name)
Direct access to the fields.
Definition: Record.h:401
#define DOUT3(args ...)
Definition: logging.h:176
#define EOUT(args ...)
Definition: logging.h:150
#define DNAME(arg)
Definition: logging.h:193
bool HasAttr(XMLNodePointer_t xmlnode, const char *name)
Definition: XmlEngine.cxx:397
XMLAttrPointer_t GetFirstAttr(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:518
const char * GetAttrValue(XMLAttrPointer_t xmlattr)
Definition: XmlEngine.cxx:553
XMLNodePointer_t GetNext(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:925
XMLNodePointer_t GetParent(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:917
const char * GetAttr(XMLNodePointer_t xmlnode, const char *name)
Definition: XmlEngine.cxx:411
const char * GetNodeName(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:885
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:906
const char * GetAttrName(XMLAttrPointer_t xmlattr)
Definition: XmlEngine.cxx:542
XMLAttrPointer_t GetNextAttr(XMLAttrPointer_t xmlattr)
Definition: XmlEngine.cxx:532
void * XMLAttrPointer_t
Definition: XmlEngine.h:27
void * XMLNodePointer_t
Definition: XmlEngine.h:25
ManagerRef mgr
Definition: Manager.cxx:42