Line data Source code
1 : #include <alma/ASDMBinaries/SDMDataObjectParser.h>
2 : #include <iostream>
3 : #include <sstream>
4 : #include <string>
5 : #include <algorithm>
6 : #include <vector>
7 : #include <iterator>
8 :
9 : using namespace AtmPhaseCorrectionMod;
10 : using namespace AxisNameMod;
11 : using namespace BasebandNameMod;
12 : using namespace CorrelationModeMod;
13 : using namespace CorrelatorTypeMod;
14 : using namespace NetSidebandMod;
15 : using namespace PrimitiveDataTypeMod;
16 : using namespace ProcessorTypeMod;
17 : using namespace SpectralResolutionTypeMod;
18 : using namespace StokesParameterMod;
19 :
20 : using namespace std;
21 :
22 : namespace asdmbinaries {
23 :
24 : // Names of XML elements/attributes in an sdmDataHeader.
25 :
26 : const std::regex HeaderParser::PROJECTPATH3("([0-9]+)/([0-9]+)/([0-9]+)/");
27 : const string HeaderParser::SDMDATAHEADER = "sdmDataHeader";
28 : const string HeaderParser::SCHEMAVERSION = "schemaVersion";
29 : const string HeaderParser::BYTEORDER = "byteOrder";
30 : const string HeaderParser::PROJECTPATH = "projectPath";
31 : const string HeaderParser::STARTTIME = "startTime";
32 : const string HeaderParser::DATAOID = "dataOID";
33 : const string HeaderParser::XLINKHREF = "href";
34 : const string HeaderParser::XLINKTITLE = "title";
35 : const string HeaderParser::DIMENSIONALITY = "dimensionality";
36 : const string HeaderParser::NUMTIME = "numTime";
37 : const string HeaderParser::EXECBLOCK = "execBlock";
38 : const string HeaderParser::EXECBLOCKNUM = "execBlockNum";
39 : const string HeaderParser::SCANNUM = "scanNum";
40 : const string HeaderParser::SUBSCANNUM = "subscanNum";
41 : const string HeaderParser::NUMANTENNA = "numAntenna";
42 : const string HeaderParser::CORRELATIONMODE = "correlationMode";
43 : const string HeaderParser::SPECTRALRESOLUTION = "spectralResolution";
44 : const string HeaderParser::PROCESSORTYPE = "processorType";
45 : const string HeaderParser::DATASTRUCT = "dataStruct";
46 : const string HeaderParser::APC = "apc";
47 : const string HeaderParser::REF = "ref";
48 : const string HeaderParser::BASEBAND = "baseband";
49 : const string HeaderParser::NAME = "name";
50 : const string HeaderParser::SPECTRALWINDOW = "spectralWindow";
51 : const string HeaderParser::SW = "sw";
52 : const string HeaderParser::SWBB = "swbb";
53 : const string HeaderParser::CROSSPOLPRODUCTS = "crossPolProducts";
54 : const string HeaderParser::SDPOLPRODUCTS = "sdPolProducts";
55 : const string HeaderParser::SCALEFACTOR = "scaleFactor";
56 : const string HeaderParser::NUMSPECTRALPOINT = "numSpectralPoint";
57 : const string HeaderParser::NUMBIN = "numBin";
58 : const string HeaderParser::SIDEBAND = "sideband";
59 : const string HeaderParser::IMAGE = "image";
60 : const string HeaderParser::FLAGS = "flags";
61 : const string HeaderParser::ACTUALTIMES = "actualTimes";
62 : const string HeaderParser::ACTUALDURATIONS = "actualDurations";
63 : const string HeaderParser::ZEROLAGS = "zeroLags";
64 : const string HeaderParser::CORRELATORTYPE = "correlatorType";
65 : const string HeaderParser::CROSSDATA = "crossData";
66 : const string HeaderParser::AUTODATA = "autoData";
67 : const string HeaderParser::NORMALIZED = "normalized";
68 : const string HeaderParser::SIZE = "size";
69 : const string HeaderParser::AXES = "axes";
70 : const string HeaderParser::TYPE = "type";
71 :
72 :
73 : // Names of XML elements/attributes in an sdmSubsetDataHeader with dimensionality==1 (Correlator)
74 :
75 : const std::regex SDMDataObjectParser::PROJECTPATH3("([0-9]+)/([0-9]+)/([0-9]+)/");
76 : const std::regex SDMDataObjectParser::PROJECTPATH4("([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)/");
77 : const std::regex SDMDataObjectParser::PROJECTPATH5("([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)/");
78 :
79 :
80 : const string CorrSubsetHeaderParser::SDMDATASUBSETHEADER = "sdmDataSubsetHeader";
81 : const string CorrSubsetHeaderParser::PROJECTPATH = "projectPath";
82 : const string CorrSubsetHeaderParser::SCHEDULEPERIODTIME = "schedulePeriodTime";
83 : const string CorrSubsetHeaderParser::TIME = "time";
84 : const string CorrSubsetHeaderParser::INTERVAL = "interval";
85 : const string CorrSubsetHeaderParser::DATASTRUCT = "dataStruct";
86 : const string CorrSubsetHeaderParser::REF = "ref";
87 : const string CorrSubsetHeaderParser::ABORTOBSERVATION = "abortObservation";
88 : const string CorrSubsetHeaderParser::ABORTTIME = "stopTime";
89 : const string CorrSubsetHeaderParser::ABORTREASON = "abortReason";
90 : const string CorrSubsetHeaderParser::XLINKHREF = "href";
91 : const string CorrSubsetHeaderParser::DATAREF = "dataRef";
92 : const string CorrSubsetHeaderParser::FLAGSREF = "flags";
93 : const string CorrSubsetHeaderParser::ACTUALTIMESREF = "actualTimes";
94 : const string CorrSubsetHeaderParser::ACTUALDURATIONSREF = "actualDurations";
95 : const string CorrSubsetHeaderParser::ZEROLAGSREF = "zeroLags";
96 : const string CorrSubsetHeaderParser::CROSSDATAREF = "crossData";
97 : const string CorrSubsetHeaderParser::AUTODATAREF = "autoData";
98 : const string CorrSubsetHeaderParser::TYPE = "type";
99 :
100 : // Names of XML elements/attributes in an sdmSubsetDataHeader with dimensionality==0 (TP)
101 : const std::regex TPSubsetHeaderParser::PROJECTPATH3("([0-9]+)/([0-9]+)/([0-9]+)/");
102 : const string TPSubsetHeaderParser::SDMDATASUBSETHEADER = "sdmDataSubsetHeader";
103 : const string TPSubsetHeaderParser::PROJECTPATH = "projectPath";
104 : const string TPSubsetHeaderParser::SCHEDULEPERIODTIME = "schedulePeriodTime";
105 : const string TPSubsetHeaderParser::TIME = "time";
106 : const string TPSubsetHeaderParser::INTERVAL = "interval";
107 : const string TPSubsetHeaderParser::DATASTRUCT = "dataStruct";
108 : const string TPSubsetHeaderParser::REF = "ref";
109 : const string TPSubsetHeaderParser::DATAREF = "dataRef";
110 : const string TPSubsetHeaderParser::XLINKHREF = "href";
111 : const string TPSubsetHeaderParser::FLAGSREF = "flags";
112 : const string TPSubsetHeaderParser::ACTUALTIMESREF = "actualTimes";
113 : const string TPSubsetHeaderParser::ACTUALDURATIONSREF = "actualDurations";
114 : const string TPSubsetHeaderParser::AUTODATAREF = "autoData";
115 :
116 : // HeaderParser methods.
117 936 : HeaderParser::HeaderParser(){
118 936 : doc = NULL;
119 936 : }
120 :
121 936 : HeaderParser::~HeaderParser() {
122 936 : if (doc != NULL) xmlFreeDoc(doc);
123 936 : }
124 :
125 0 : void HeaderParser::parseFile(const string& filename, SDMDataObject& sdmDataObject){
126 0 : if (doc != NULL) xmlFreeDoc(doc);
127 0 : doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOBLANKS);
128 0 : if (doc == NULL) {
129 0 : throw SDMDataObjectParserException("The file '"+filename+"' could not be transformed into a DOM structure");
130 : }
131 :
132 0 : xmlNode* root_element = xmlDocGetRootElement(doc);
133 0 : parseSDMDataHeader(root_element, sdmDataObject);
134 0 : }
135 :
136 2955 : void HeaderParser::parseMemory(const string& buffer, SDMDataObject& sdmDataObject) {
137 2955 : if (doc != NULL) xmlFreeDoc(doc);
138 2955 : doc = xmlReadMemory(buffer.data(), buffer.size(), "SDMDataHeader.xml", NULL, XML_PARSE_NOBLANKS );
139 2955 : if (doc == NULL) {
140 0 : throw SDMDataObjectParserException("The buffer containing the XML document could not be transformed into a DOM structure");
141 : }
142 :
143 2955 : xmlNode* root_element = xmlDocGetRootElement(doc);
144 2955 : parseSDMDataHeader(root_element, sdmDataObject);
145 2955 : }
146 :
147 0 : void HeaderParser::reset() {
148 0 : if (doc)
149 0 : xmlFreeDoc(doc);
150 :
151 0 : doc = NULL;
152 0 : }
153 :
154 2955 : void HeaderParser::parseSDMDataHeader(xmlNode* a_node, SDMDataObject& sdmDataObject){
155 : //cout << "Entering parseSDMDataHeader" << endl;
156 : // Look up for the <sdmDataHeader ... element.
157 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::SDMDATAHEADER);
158 :
159 : // And parse some of its attributes.
160 2955 : sdmDataObject.schemaVersion_ = SDMDataObjectParser::parseIntAttr(a_node, HeaderParser::SCHEMAVERSION);
161 2955 : sdmDataObject.byteOrder_ = SDMDataObjectParser::parseByteOrderAttr(a_node, HeaderParser::BYTEORDER);
162 :
163 :
164 : // Look up for its projectPath attribute
165 : // and determine execBlockNum, scanNum and subscanNum from its projectPath attribute.
166 2955 : vector<unsigned int> v = SDMDataObjectParser::parseProjectPath(a_node, 3);
167 2955 : sdmDataObject.execBlockNum_ = v.at(0);
168 2955 : sdmDataObject.scanNum_ = v.at(1);
169 2955 : sdmDataObject.subscanNum_ = v.at(2);
170 :
171 : // Traverse the children.
172 2955 : xmlNode* child = a_node->children;
173 :
174 : // Look up for the <startTime... child
175 2955 : sdmDataObject.startTime(parseStartTime(child));
176 :
177 : // Look up for the <dataOID... child
178 2955 : child = child->next;
179 2955 : sdmDataObject.dataOID(parseDataOID(child));
180 :
181 : // ...and its title attribute
182 2955 : sdmDataObject.title(SDMDataObjectParser::parseStringAttr(child, HeaderParser::XLINKTITLE));
183 :
184 : // Look up for the <dimensionality...
185 2955 : child = child->next;
186 2955 : unsigned int dimensionality = parseDimensionality(child);
187 2955 : sdmDataObject.dimensionality(dimensionality);
188 :
189 2955 : if ( dimensionality == 0 ) {
190 : // Look up for numTime... only if dimensionality == 0
191 884 : sdmDataObject.numTime((unsigned int) parseNumTime(child) );
192 : }
193 :
194 : // Look up for the <execBlock... child
195 2955 : child = child->next;
196 2955 : parseExecBlock(child, sdmDataObject);
197 :
198 : // Look up for the <numAntenna... child
199 2955 : child = child->next;
200 2955 : int numAntenna = parseNumAntenna(child); //cout << child->name << "=" << numAntenna << endl;
201 2955 : sdmDataObject.numAntenna((unsigned int) numAntenna);
202 :
203 : // Look up for the <correlationMode> ... child
204 2955 : child = child->next;
205 2955 : parseCorrelationMode(child, sdmDataObject);
206 :
207 : // Look up for the <spectralResolution> ... child
208 2955 : child = child->next;
209 2955 : parseSpectralResolution(child, sdmDataObject);
210 :
211 : // Look up for child <processorType> ... child
212 2955 : child = child->next;
213 2955 : parseProcessorType(child, sdmDataObject);
214 :
215 : // Look up for the <dataStruct> ... child
216 2955 : child = child->next;
217 2955 : parseDataStruct(child, sdmDataObject);
218 :
219 : //cout << "Exiting parseSDMDataHeader" << endl;
220 2955 : }
221 :
222 : // void HeaderParser::parseProjectPath(xmlNode* a_node, SDMDataObject& sdmDataObject) {
223 : // string projectPath = SDMDataObjectParser::parseStringAttr(a_node, HeaderParser::PROJECTPATH);
224 :
225 : // std::cmatch what;
226 :
227 : // if (std::regex_match(projectPath.c_str(), what,PROJECTPATH3) && what[0].matched) {
228 : // sdmDataObject.execBlockNum(::atoi(what[1].first));
229 : // sdmDataObject.scanNum(::atoi(what[2].first));
230 : // sdmDataObject.subscanNum(::atoi(what[3].first));
231 : // }
232 : // else
233 : // throw SDMDataObjectParserException("HeaderParser::parseProjectPath: Invalid string for projectPath '" + projectPath + "'");
234 : // }
235 :
236 2955 : long long HeaderParser::parseStartTime(xmlNode* a_node){
237 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::STARTTIME);
238 2955 : return SDMDataObjectParser::parseLongLong(a_node->children);
239 : }
240 :
241 2955 : string HeaderParser::parseDataOID(xmlNode* a_node) {
242 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::DATAOID);
243 :
244 : // Look for attribute
245 2955 : string dataOID = SDMDataObjectParser::parseStringAttr(a_node, HeaderParser::XLINKHREF);
246 2955 : return dataOID;
247 : }
248 :
249 2955 : int HeaderParser::parseDimensionality(xmlNode* a_node) {
250 : //cout << "Entering parseDimensionality with " << a_node->name << endl;
251 2955 : if (SDMDataObjectParser::testElement(a_node, HeaderParser::DIMENSIONALITY)) {
252 2071 : return SDMDataObjectParser::parseInt(a_node->children);
253 : }
254 : else
255 884 : return 0;
256 : }
257 :
258 884 : int HeaderParser::parseNumTime(xmlNode* a_node) {
259 884 : SDMDataObjectParser::isElement(a_node, HeaderParser::NUMTIME);
260 884 : return SDMDataObjectParser::parseInt(a_node->children);
261 : }
262 :
263 2955 : void HeaderParser::parseExecBlock(xmlNode* a_node, SDMDataObject& sdmDataObject){
264 : //cout << "Entering parseExecBlock with " << a_node << endl;
265 :
266 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::EXECBLOCK);
267 :
268 : // Look up for the execBlockUID attribute.
269 2955 : sdmDataObject.execBlockUID(SDMDataObjectParser::parseStringAttr(a_node, HeaderParser::XLINKHREF));
270 2955 : }
271 :
272 0 : int HeaderParser::parseExecBlockNum(xmlNode* a_node){
273 0 : SDMDataObjectParser::isElement(a_node, HeaderParser::EXECBLOCKNUM);
274 0 : return SDMDataObjectParser::parseInt(a_node->children);
275 : }
276 :
277 0 : int HeaderParser::parseScanNum(xmlNode* a_node){
278 0 : SDMDataObjectParser::isElement(a_node, HeaderParser::SCANNUM);
279 0 : return SDMDataObjectParser::parseInt(a_node->children);
280 : }
281 :
282 0 : int HeaderParser::parseSubscanNum(xmlNode* a_node){
283 0 : SDMDataObjectParser::isElement(a_node, HeaderParser::SUBSCANNUM);
284 0 : return SDMDataObjectParser::parseInt(a_node->children);
285 : }
286 :
287 2955 : int HeaderParser::parseNumAntenna(xmlNode* a_node){
288 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::NUMANTENNA);
289 2955 : return SDMDataObjectParser::parseInt(a_node->children);
290 : }
291 :
292 2955 : void HeaderParser::parseCorrelationMode(xmlNode* a_node, SDMDataObject& sdmDataObject) {
293 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::CORRELATIONMODE);
294 2955 : sdmDataObject.correlationMode_ = SDMDataObjectParser::parseLiteral<CorrelationMode, CCorrelationMode>(a_node->children);
295 2955 : }
296 :
297 2955 : void HeaderParser::parseSpectralResolution(xmlNode* a_node, SDMDataObject& sdmDataObject) {
298 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::SPECTRALRESOLUTION);
299 2955 : sdmDataObject.spectralResolutionType_ = SDMDataObjectParser::parseLiteral<SpectralResolutionType, CSpectralResolutionType>(a_node->children);
300 2955 : }
301 :
302 2955 : void HeaderParser::parseProcessorType(xmlNode* a_node, SDMDataObject& sdmDataObject) {
303 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::PROCESSORTYPE);
304 2955 : sdmDataObject.processorType_ = SDMDataObjectParser::parseLiteral<ProcessorType, CProcessorType>(a_node->children);
305 2955 : }
306 :
307 2955 : void HeaderParser::parseDataStruct(xmlNode* a_node, SDMDataObject& sdmDataObject){
308 : //cout << "Entering parseDataStruct with " << a_node->name << endl;
309 2955 : SDMDataObjectParser::isElement(a_node, HeaderParser::DATASTRUCT);
310 :
311 2955 : SDMDataObject::DataStruct dataStruct;
312 :
313 2955 : switch (sdmDataObject.correlationMode()) {
314 2148 : case AUTO_ONLY:
315 2148 : break;
316 :
317 807 : case CROSS_ONLY:
318 : case CROSS_AND_AUTO:
319 807 : dataStruct.apc_ = SDMDataObjectParser::parseStringsAttr<AtmPhaseCorrection, CAtmPhaseCorrection>(a_node, HeaderParser::APC);
320 807 : break;
321 : }
322 :
323 : // Traverse the children
324 :
325 : // BaseBands...
326 2955 : xmlNode* child = a_node->children;
327 5910 : vector <SDMDataObject::Baseband> basebands;
328 11635 : while (SDMDataObjectParser::testElement(child, HeaderParser::BASEBAND)) {
329 8680 : basebands.push_back(parseBaseband(child, sdmDataObject ));
330 8680 : child = child->next;
331 : }
332 :
333 2955 : dataStruct.basebands_ = (basebands);
334 :
335 : // Now that all the spectral windows are read set the associations between spectral windows.
336 : // We have recorded the id and image attributes when they are present in private strings in each spectralWindow.
337 : //
338 :
339 : // I want a map to associate a string of the form "<int>_<int>" to a string of the form "<int>_<int>"
340 : // and I define an entry in this map for each spectralWindow with an strSw_ non empty, the value
341 : // associated is of the form <int>_<int> where the two integers are the coordinates
342 : // (baseband index, spectralWindow index in the baseband)
343 : //
344 5910 : map<string, string> id2int_int;
345 5910 : ostringstream oss;
346 :
347 5910 : string key, value;
348 11635 : for (unsigned int ibb = 0; ibb < dataStruct.basebands_.size(); ibb++) {
349 8680 : vector<SDMDataObject::SpectralWindow>& spws = dataStruct.basebands_.at(ibb).spectralWindows_;
350 17719 : for (unsigned int ispw = 0; ispw < spws.size(); ispw++) {
351 :
352 9039 : oss.str("");
353 9039 : oss << ibb << " " << ispw;
354 9039 : value = oss.str();
355 :
356 9039 : oss.str("");
357 9039 : oss << ibb << " " << spws.at(ispw).strSw();
358 9039 : key = oss.str();
359 :
360 9039 : id2int_int[key] = value;
361 :
362 : }
363 : }
364 :
365 :
366 : // Now re scan all the spectralWindows and look for the ones with an strImage_ non empty.
367 : // and define the associations.
368 : //
369 5910 : istringstream iss;
370 2955 : map<string, string>::iterator iter;
371 : int ibbImage, ispwImage;
372 11635 : for (unsigned int ibb = 0; ibb < dataStruct.basebands_.size(); ibb++) {
373 8680 : vector<SDMDataObject::SpectralWindow>& spws = dataStruct.basebands_.at(ibb).spectralWindows_;
374 17719 : for (unsigned int ispw = 0; ispw < spws.size(); ispw++) {
375 9039 : string image = spws.at(ispw).strImage();
376 9039 : if (image.size() > 0) {
377 0 : oss.str("");
378 0 : oss << ibb << " " << image;
379 0 : key = oss.str();
380 0 : if ((iter = id2int_int.find(key)) != id2int_int.end()) {
381 0 : iss.str(iter->second);
382 0 : iss >> ibbImage;
383 0 : iss >> ispwImage;
384 0 : dataStruct.imageSPW(ibb, ispw, ispwImage);
385 : }
386 : else {
387 0 : oss.str("");
388 0 : oss << "In baseband #" << ibb << " the spectral window #" << ispw << " refers to non defined image ('" << image << "')";
389 0 : throw SDMDataObjectParserException(oss.str());
390 : }
391 : }
392 9039 : }
393 : }
394 :
395 : // Metadata attachments.
396 :
397 : // flags (optional)
398 2955 : if (SDMDataObjectParser::testElement(child, HeaderParser::FLAGS)) {
399 2786 : dataStruct.flags_ = (parseBinaryPart(child, HeaderParser::FLAGS));
400 2786 : child = child->next;
401 : }
402 :
403 : // actualTimes (optional)
404 2955 : if (SDMDataObjectParser::testElement(child, HeaderParser::ACTUALTIMES)) {
405 1997 : dataStruct.actualTimes_ = (parseBinaryPart(child, HeaderParser::ACTUALTIMES));
406 1997 : child = child->next;
407 : }
408 :
409 : // actualDurations (optional)
410 2955 : if (SDMDataObjectParser::testElement(child, HeaderParser::ACTUALDURATIONS)) {
411 1997 : dataStruct.actualDurations_ = (parseBinaryPart(child, HeaderParser::ACTUALDURATIONS));
412 1997 : child = child->next;
413 : }
414 :
415 : // Binary attachments elements...
416 2955 : switch (sdmDataObject.correlationMode()) {
417 74 : case CROSS_ONLY :
418 74 : dataStruct.crossData_ = (parseBinaryPart(child, HeaderParser::CROSSDATA));
419 74 : child = child->next;
420 74 : break;
421 :
422 2148 : case AUTO_ONLY :
423 2148 : dataStruct.autoData_ = (parseAutoDataBinaryPart(child, HeaderParser::AUTODATA));
424 2148 : child = child->next;
425 2148 : break;
426 :
427 733 : case CROSS_AND_AUTO :
428 733 : dataStruct.crossData_ = (parseBinaryPart(child, HeaderParser::CROSSDATA));
429 733 : child = child->next;
430 733 : dataStruct.autoData_ = (parseAutoDataBinaryPart(child, HeaderParser::AUTODATA));
431 733 : child = child->next;
432 733 : break;
433 : }
434 :
435 : /*
436 : // zeroLags (mandatory in FULL_RESOLUTION)
437 : if (sdmDataObject.spectralResolutionType() == FULL_RESOLUTION) {
438 : dataStruct.zeroLags_ = (parseBinaryPart(child, HeaderParser::ZEROLAGS));
439 : child = child->next;
440 : }
441 : // (and optional in CHANNEL_AVERAGE)
442 : else if (sdmDataObject.spectralResolutionType() == CHANNEL_AVERAGE) {
443 : if (SDMDataObjectParser::testElement(child, HeaderParser::ZEROLAGS)) {
444 : dataStruct.zeroLags_ = (parseBinaryPart(child, HeaderParser::ZEROLAGS));
445 : child = child->next;
446 : }
447 : }
448 : */
449 :
450 : // zeroLags are allowed only with a non FX correlator.
451 2955 : if (SDMDataObjectParser::testElement(child, HeaderParser::ZEROLAGS)) {
452 : // Reject zeroLags if the context does not allow them
453 463 : if (sdmDataObject.processorType_ != CORRELATOR)
454 0 : throw SDMDataObjectParserException("zeroLags are not expected with the declared processor type ('" +
455 0 : CProcessorType::name(sdmDataObject.processorType_) + "')");
456 :
457 :
458 463 : dataStruct.zeroLags_ = (parseZeroLagsBinaryPart(child, HeaderParser::ZEROLAGS));
459 :
460 : // Reject zeroLags if the context does not allow them ... again
461 :
462 463 : if (dataStruct.zeroLags_.correlatorType_ == FX)
463 0 : throw SDMDataObjectParserException ("zeroLags are not expected with the declared correlator type ('" +
464 0 : CCorrelatorType::name(dataStruct.zeroLags_.correlatorType_) + "')");
465 :
466 463 : child = child->next;
467 : }
468 :
469 2955 : sdmDataObject.dataStruct_ = (dataStruct);
470 2955 : }
471 :
472 8680 : SDMDataObject::Baseband HeaderParser::parseBaseband(xmlNode* a_node, SDMDataObject& sdmDataObject){
473 8680 : SDMDataObject::Baseband bb;
474 8680 : SDMDataObjectParser::isElement(a_node, HeaderParser::BASEBAND);
475 :
476 8680 : bb.name_ = (SDMDataObjectParser::parseStringAttr<BasebandName, CBasebandName>(a_node, HeaderParser::NAME));
477 :
478 : // Traverse the children (spectralWindow).
479 8680 : xmlNode* child = a_node->children;
480 8680 : vector<SDMDataObject::SpectralWindow> spw;
481 8680 : parseSpectralWindow(child, sdmDataObject, spw);
482 8680 : bb.spectralWindows(spw);
483 :
484 17360 : return bb;
485 8680 : }
486 :
487 8680 : void HeaderParser::parseSpectralWindow(xmlNode* a_node, SDMDataObject& sdmDataObject , vector<SDMDataObject::SpectralWindow>& spectralWindow){
488 17719 : for (xmlNode* cur_node = a_node; cur_node; cur_node = cur_node->next) {
489 9039 : SDMDataObjectParser::isElement(a_node, HeaderParser::SPECTRALWINDOW);
490 :
491 : //Look for attributes
492 9039 : vector<StokesParameter> crossPolProducts;
493 9039 : vector<StokesParameter> sdPolProducts;
494 : float scaleFactor;
495 : int numSpectralPoint;
496 : int numBin;
497 : NetSideband sideband;
498 :
499 9039 : SDMDataObject::SpectralWindow spw;
500 :
501 :
502 9039 : string dummy = SDMDataObjectParser::parseStringAttr(cur_node, HeaderParser::SWBB);
503 :
504 9039 : switch (sdmDataObject.correlationMode()) {
505 :
506 74 : case CROSS_ONLY:
507 74 : crossPolProducts = SDMDataObjectParser::parseStringsAttr<StokesParameter, CStokesParameter>(cur_node, HeaderParser::CROSSPOLPRODUCTS );
508 74 : scaleFactor = SDMDataObjectParser::parseFloatAttr(cur_node, HeaderParser::SCALEFACTOR );
509 74 : numSpectralPoint = SDMDataObjectParser::parseIntAttr(cur_node, HeaderParser::NUMSPECTRALPOINT );
510 74 : numBin = SDMDataObjectParser::parseIntAttr(cur_node, HeaderParser::NUMBIN );
511 74 : sideband = SDMDataObjectParser::parseStringAttr<NetSideband, CNetSideband>(cur_node, HeaderParser::SIDEBAND);
512 148 : spw = SDMDataObject::SpectralWindow(crossPolProducts,
513 : scaleFactor,
514 : (unsigned int)numSpectralPoint,
515 : (unsigned int)numBin,
516 74 : sideband);
517 74 : break;
518 :
519 5940 : case AUTO_ONLY:
520 5940 : sdPolProducts = SDMDataObjectParser::parseStringsAttr<StokesParameter, CStokesParameter>(cur_node, HeaderParser::SDPOLPRODUCTS );
521 5940 : numSpectralPoint = SDMDataObjectParser::parseIntAttr(cur_node, HeaderParser::NUMSPECTRALPOINT );
522 5940 : numBin = SDMDataObjectParser::parseIntAttr(cur_node, HeaderParser::NUMBIN );
523 5940 : sideband = SDMDataObjectParser::parseStringAttr<NetSideband, CNetSideband>(cur_node, HeaderParser::SIDEBAND);
524 11880 : spw = SDMDataObject::SpectralWindow(sdPolProducts,
525 : (unsigned int)numSpectralPoint,
526 : (unsigned int)numBin,
527 5940 : sideband);
528 5940 : break;
529 :
530 3025 : case CROSS_AND_AUTO:
531 3025 : crossPolProducts = SDMDataObjectParser::parseStringsAttr<StokesParameter, CStokesParameter>(cur_node, HeaderParser::CROSSPOLPRODUCTS );
532 3025 : sdPolProducts = SDMDataObjectParser::parseStringsAttr<StokesParameter, CStokesParameter>(cur_node, HeaderParser::SDPOLPRODUCTS );
533 3025 : scaleFactor = SDMDataObjectParser::parseFloatAttr(cur_node, HeaderParser::SCALEFACTOR );
534 3025 : numSpectralPoint = SDMDataObjectParser::parseIntAttr(cur_node, HeaderParser::NUMSPECTRALPOINT );
535 3025 : numBin = SDMDataObjectParser::parseIntAttr(cur_node, HeaderParser::NUMBIN );
536 3025 : sideband = SDMDataObjectParser::parseStringAttr<NetSideband, CNetSideband>(cur_node, HeaderParser::SIDEBAND);
537 6050 : spw = SDMDataObject::SpectralWindow(crossPolProducts,
538 : sdPolProducts,
539 : scaleFactor,
540 : (unsigned int)numSpectralPoint,
541 : (unsigned int)numBin,
542 3025 : sideband);
543 3025 : break;
544 : }
545 :
546 9039 : spw.strSw(SDMDataObjectParser::parseStringAttr(cur_node, HeaderParser::SW));
547 9039 : if (SDMDataObjectParser::hasAttr(cur_node, HeaderParser::IMAGE))
548 0 : spw.strImage(SDMDataObjectParser::parseStringAttr(cur_node, HeaderParser::IMAGE));
549 :
550 9039 : spectralWindow.push_back(spw);
551 :
552 9039 : }
553 8680 : }
554 :
555 7587 : SDMDataObject::BinaryPart HeaderParser::parseBinaryPart(xmlNode* a_node, const string& attachmentName) {
556 7587 : SDMDataObjectParser::isElement(a_node, attachmentName);
557 :
558 7587 : return SDMDataObject::BinaryPart(SDMDataObjectParser::parseIntAttr(a_node, HeaderParser::SIZE),
559 22761 : SDMDataObjectParser::parseStringsAttr<AxisName, CAxisName>(a_node, HeaderParser::AXES));
560 : }
561 :
562 2881 : SDMDataObject::AutoDataBinaryPart HeaderParser::parseAutoDataBinaryPart(xmlNode* a_node, const string& attachmentName) {
563 2881 : SDMDataObjectParser::isElement(a_node, attachmentName);
564 :
565 2881 : return SDMDataObject::AutoDataBinaryPart(SDMDataObjectParser::parseIntAttr(a_node, HeaderParser::SIZE),
566 2881 : SDMDataObjectParser::parseStringsAttr<AxisName, CAxisName>(a_node, HeaderParser::AXES),
567 8643 : SDMDataObjectParser::parseBoolAttr(a_node, HeaderParser::NORMALIZED));
568 : }
569 :
570 463 : SDMDataObject::ZeroLagsBinaryPart HeaderParser::parseZeroLagsBinaryPart(xmlNode* a_node, const string& attachmentName) {
571 463 : SDMDataObjectParser::isElement(a_node, attachmentName);
572 :
573 463 : return SDMDataObject::ZeroLagsBinaryPart(SDMDataObjectParser::parseIntAttr(a_node, HeaderParser::SIZE),
574 463 : SDMDataObjectParser::parseStringsAttr<AxisName, CAxisName>(a_node, HeaderParser::AXES),
575 1389 : SDMDataObjectParser::parseStringAttr<CorrelatorType, CCorrelatorType>(a_node, HeaderParser::CORRELATORTYPE));
576 : }
577 :
578 : // CorrSubsetHeaderParser methods.
579 :
580 936 : CorrSubsetHeaderParser::CorrSubsetHeaderParser() {
581 936 : doc = NULL;
582 936 : }
583 :
584 936 : CorrSubsetHeaderParser::~CorrSubsetHeaderParser() {
585 936 : if (doc != NULL) xmlFreeDoc(doc);
586 936 : }
587 :
588 :
589 0 : void CorrSubsetHeaderParser::parseFile(const string& filename, SDMDataSubset& sdmCorrDataSubset){
590 0 : if (doc != NULL) xmlFreeDoc(doc);
591 0 : doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOBLANKS);
592 0 : if (doc == NULL) {
593 0 : throw SDMDataObjectParserException("The file '"+filename+"' could not be transformed into a DOM structure");
594 : }
595 :
596 0 : xmlNode* root_element = xmlDocGetRootElement(doc);
597 0 : parseSDMDataSubsetHeader(root_element, sdmCorrDataSubset);
598 0 : }
599 :
600 41282 : void CorrSubsetHeaderParser::parseMemory(const string& buffer, SDMDataSubset& sdmCorrDataSubset) {
601 41282 : if (doc != NULL) xmlFreeDoc(doc);
602 41282 : doc = xmlReadMemory(buffer.data(), buffer.size(), "SDMDataHeader.xml", NULL, XML_PARSE_NOBLANKS);
603 41282 : if (doc == NULL) {
604 0 : throw SDMDataObjectParserException("The buffer containing the XML document could not be transformed into a DOM structure");
605 : }
606 :
607 41282 : xmlNode* root_element = xmlDocGetRootElement(doc);
608 41282 : parseSDMDataSubsetHeader(root_element, sdmCorrDataSubset );
609 41282 : };
610 :
611 41282 : void CorrSubsetHeaderParser::parseSDMDataSubsetHeader(xmlNode* a_node, SDMDataSubset& sdmCorrDataSubset) {
612 : // Look up for <sdmSubsetDataHeader...
613 41282 : SDMDataObjectParser::isElement(a_node, SDMDATASUBSETHEADER);
614 :
615 : // Project path.
616 41282 : vector<unsigned int> v;
617 41282 : v = SDMDataObjectParser::parseProjectPath(a_node); // v should contain 4 (integration) or 5 (subintegration) elements.
618 :
619 : // Check conformity of execBlockNum, scanNum and subscanNum.
620 :
621 41282 : if (v.at(0) != sdmCorrDataSubset.owner()->execBlockNum()
622 41282 : || v.at(1) != sdmCorrDataSubset.owner()->scanNum()
623 82564 : || v.at(2) != sdmCorrDataSubset.owner()->subscanNum())
624 0 : throw SDMDataObjectParserException("The project path of this data subset '"
625 0 : +SDMDataObjectParser::parseStringAttr(a_node, PROJECTPATH)
626 0 : +"' is not compatible with the project path announced in the global header"
627 0 : +" '"+sdmCorrDataSubset.owner()->projectPath()+"'");
628 :
629 : // Determine integrationNum [, subintegrationNum]
630 41282 : sdmCorrDataSubset.integrationNum_ = v.at(3);
631 41282 : sdmCorrDataSubset.subintegrationNum_ = (v.size() == 5) ? v.at(4) : 0;
632 :
633 : // Traverse the children .
634 41282 : xmlNode* child = a_node->children;
635 :
636 : // <schedulePeriodTime...
637 41282 : parseSchedulePeriodTime(child, sdmCorrDataSubset);
638 :
639 : // <dataStruct...
640 41282 : child = child->next;
641 41282 : SDMDataObjectParser::isElement(child, CorrSubsetHeaderParser::DATASTRUCT);
642 41282 : sdmCorrDataSubset.dataStruct_ = SDMDataObjectParser::parseStringAttr(child, CorrSubsetHeaderParser::REF);
643 :
644 41282 : child = child->next;
645 41282 : if (SDMDataObjectParser::testElement(child, CorrSubsetHeaderParser::ABORTOBSERVATION)) {
646 : // Is it a cancelling [sub]integration ?
647 0 : sdmCorrDataSubset.aborted_ = true;
648 0 : parseAbortObservation(child, sdmCorrDataSubset);
649 : }
650 : else {
651 : // ... or a sequence of attachments description.
652 41282 : if (SDMDataObjectParser::testElement(child, FLAGSREF)) {
653 9424 : sdmCorrDataSubset.flagsREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
654 9424 : child = child->next;
655 : }
656 :
657 :
658 41282 : if (SDMDataObjectParser::testElement(child, ACTUALTIMESREF)) {
659 1468 : sdmCorrDataSubset.actualTimesREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
660 1468 : child = child->next;
661 : }
662 :
663 :
664 41282 : if (SDMDataObjectParser::testElement(child, ACTUALDURATIONSREF)) {
665 1468 : sdmCorrDataSubset.actualDurationsREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
666 1468 : child = child->next;
667 : }
668 :
669 41282 : switch (sdmCorrDataSubset.owner()->correlationMode()) {
670 112 : case CROSS_ONLY:
671 112 : SDMDataObjectParser::isElement(child, CROSSDATAREF);
672 112 : sdmCorrDataSubset.crossDataREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
673 112 : sdmCorrDataSubset.crossDataType_ = SDMDataObjectParser::parseStringAttr<PrimitiveDataType, CPrimitiveDataType>(child, CorrSubsetHeaderParser::TYPE);
674 112 : child = child->next;
675 112 : break;
676 :
677 13370 : case AUTO_ONLY:
678 13370 : SDMDataObjectParser::isElement(child, AUTODATAREF);
679 13370 : sdmCorrDataSubset.autoDataREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
680 13370 : child = child->next;
681 13370 : break;
682 :
683 27800 : case CROSS_AND_AUTO:
684 27800 : SDMDataObjectParser::isElement(child, CROSSDATAREF);
685 27800 : sdmCorrDataSubset.crossDataREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
686 27800 : sdmCorrDataSubset.crossDataType_ = SDMDataObjectParser::parseStringAttr<PrimitiveDataType, CPrimitiveDataType>(child, CorrSubsetHeaderParser::TYPE);
687 27800 : child = child->next;
688 :
689 27800 : SDMDataObjectParser::isElement(child, AUTODATAREF);
690 27800 : sdmCorrDataSubset.autoDataREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
691 27800 : child = child->next;
692 27800 : break;
693 : }
694 : /*
695 : if (sdmCorrDataSubset.owner()->spectralResolutionType() != CHANNEL_AVERAGE) {
696 : SDMDataObjectParser::isElement(child, ZEROLAGSREF);
697 : sdmCorrDataSubset.zeroLagsREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
698 : child = child->next;
699 : }
700 : */
701 :
702 : // zeroLags are optional in any case. Michel Caillat. 24 Jul 2008
703 41282 : if (SDMDataObjectParser::testElement(child, ZEROLAGSREF)) {
704 22312 : sdmCorrDataSubset.zeroLagsREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
705 22312 : child = child->next;
706 : }
707 : }
708 41282 : }
709 :
710 : // void CorrSubsetHeaderParser::parseProjectPath (xmlNode* a_node, SDMDataSubset& sdmCorrDataSubset) {
711 : // string projectPath = SDMDataObjectParser::parseStringAttr(a_node,CorrSubsetHeaderParser::PROJECTPATH);
712 :
713 : // std::cmatch what;
714 : // unsigned int execBlockNum = 0;
715 : // unsigned int scanNum = 0;
716 : // unsigned int subscanNum = 0;
717 : // switch (sdmCorrDataSubset.owner()->spectralResolutionType()) {
718 : // case FULL_RESOLUTION:
719 : // if (std::regex_match(projectPath.c_str(), what, SDMDataObjectParser::PROJECTPATH4) && what[0].matched) {
720 : // execBlockNum = ::atoi(what[1].first);
721 : // scanNum = ::atoi(what[2].first);
722 : // subscanNum = ::atoi(what[3].first);
723 : // sdmCorrDataSubset.integrationNum_ = ::atoi(what[4].first);
724 : // }
725 : // else
726 : // throw SDMDataObjectParserException("Invalid string for projectPath '" + projectPath + "'");
727 : // break;
728 :
729 : // case CHANNEL_AVERAGE:
730 : // if (std::regex_match(projectPath.c_str(), what, SDMDataObjectParser::PROJECTPATH5) && what[0].matched) {
731 : // execBlockNum = ::atoi(what[1].first);
732 : // scanNum = ::atoi(what[2].first);
733 : // subscanNum = ::atoi(what[3].first);
734 : // sdmCorrDataSubset.integrationNum_ = ::atoi(what[4].first);
735 : // sdmCorrDataSubset.subintegrationNum_ = ::atoi(what[5].first);
736 : // }
737 : // else
738 : // throw SDMDataObjectParserException("Invalid string for projectPath '" + projectPath + "'");
739 : // break;
740 :
741 : // case BASEBAND_WIDE:
742 : // throw SDMDataObjectParserException("'"+CSpectralResolutionType::name(BASEBAND_WIDE)+"' cannot appear in this context.");
743 : // break;
744 : // }
745 :
746 : // if (execBlockNum != sdmCorrDataSubset.owner()->execBlockNum()
747 : // || scanNum != sdmCorrDataSubset.owner()->scanNum()
748 : // || subscanNum != sdmCorrDataSubset.owner()->subscanNum())
749 : // throw SDMDataObjectParserException("The project path of this data subset '"
750 : // +projectPath
751 : // +"' is not compatible with the project path announced in the global header"
752 : // +" '"+sdmCorrDataSubset.owner()->projectPath()+"'");
753 : // }
754 :
755 41282 : void CorrSubsetHeaderParser::parseSchedulePeriodTime(xmlNode* a_node, SDMDataSubset& sdmCorrDataSubset) {
756 41282 : SDMDataObjectParser::isElement(a_node, CorrSubsetHeaderParser::SCHEDULEPERIODTIME);
757 :
758 41282 : xmlNode* child = a_node->children;
759 : // <time...
760 41282 : sdmCorrDataSubset.time_ = parseTime(child);
761 :
762 : // <interval...
763 41282 : child = child->next;
764 41282 : sdmCorrDataSubset.interval_ = parseInterval(child);
765 41282 : }
766 :
767 41282 : long long CorrSubsetHeaderParser::parseTime(xmlNode* a_node) {
768 41282 : SDMDataObjectParser::isElement(a_node, CorrSubsetHeaderParser::TIME);
769 41282 : return SDMDataObjectParser::parseLongLong(a_node->children);
770 : }
771 :
772 :
773 41282 : long long CorrSubsetHeaderParser::parseInterval(xmlNode* a_node) {
774 41282 : SDMDataObjectParser::isElement(a_node, CorrSubsetHeaderParser::INTERVAL);
775 41282 : return SDMDataObjectParser::parseLongLong(a_node->children);
776 : }
777 :
778 :
779 0 : void CorrSubsetHeaderParser::parseAbortObservation(xmlNode* a_node, SDMDataSubset& sdmCorrDataSubset) {
780 0 : xmlNode* child = a_node->children;
781 :
782 : // <abortTime...
783 0 : SDMDataObjectParser::isElement(child, CorrSubsetHeaderParser::ABORTTIME);
784 0 : sdmCorrDataSubset.abortTime_ = SDMDataObjectParser::parseLongLong(child->children);
785 :
786 : // <abortReason...
787 0 : child = child->next;
788 0 : SDMDataObjectParser::isElement(child, CorrSubsetHeaderParser::ABORTREASON);
789 0 : sdmCorrDataSubset.abortReason_ = SDMDataObjectParser::parseString(child->children);
790 0 : }
791 :
792 0 : void CorrSubsetHeaderParser::parseCrossDataType(xmlNode* a_node, SDMDataSubset& sdmCorrDataSubset) {
793 0 : SDMDataObjectParser::isElement(a_node, CorrSubsetHeaderParser::TYPE);
794 0 : sdmCorrDataSubset.crossDataType(SDMDataObjectParser::parseLiteral<PrimitiveDataType, CPrimitiveDataType>(a_node->children));
795 0 : }
796 :
797 :
798 0 : void CorrSubsetHeaderParser::reset() {
799 0 : if (doc)
800 0 : xmlFreeDoc(doc);
801 :
802 0 : doc = NULL;
803 0 : }
804 :
805 :
806 : // TPSubsetHeaderParser methods.
807 :
808 936 : TPSubsetHeaderParser::TPSubsetHeaderParser() {
809 936 : doc = NULL;
810 936 : }
811 :
812 936 : TPSubsetHeaderParser::~TPSubsetHeaderParser() {
813 936 : if (doc != NULL) xmlFreeDoc(doc);
814 936 : }
815 :
816 :
817 0 : void TPSubsetHeaderParser::parseFile(const string& filename, SDMDataSubset& sdmTPDataSubset){
818 0 : if (doc != NULL) xmlFreeDoc(doc);
819 0 : doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOBLANKS);
820 0 : if (doc == NULL) {
821 0 : throw SDMDataObjectParserException("The file '"+filename+"' could not be transformed into a DOM structure");
822 : }
823 :
824 0 : xmlNode* root_element = xmlDocGetRootElement(doc);
825 0 : parseSDMDataSubsetHeader(root_element, sdmTPDataSubset);
826 :
827 0 : }
828 :
829 884 : void TPSubsetHeaderParser::parseMemory(const string& buffer, SDMDataSubset& sdmTPDataSubset) {
830 884 : if (doc != NULL) xmlFreeDoc(doc);
831 884 : doc = xmlReadMemory(buffer.data(), buffer.size(), "SDMDataHeader.xml", NULL, XML_PARSE_NOBLANKS);
832 884 : if (doc == NULL) {
833 0 : throw SDMDataObjectParserException("The buffer containing the XML document could not be transformed into a DOM structure");
834 : }
835 :
836 884 : xmlNode* root_element = xmlDocGetRootElement(doc);
837 884 : parseSDMDataSubsetHeader(root_element, sdmTPDataSubset);
838 884 : }
839 :
840 884 : void TPSubsetHeaderParser::parseSDMDataSubsetHeader(xmlNode* a_node, SDMDataSubset& sdmTPDataSubset) {
841 : // Look up for <sdmSubsetDataHeader...
842 884 : SDMDataObjectParser::isElement(a_node, TPSubsetHeaderParser::SDMDATASUBSETHEADER);
843 :
844 : // Project path.
845 884 : int pathLen = (sdmTPDataSubset.owner()->dimensionality() == 0) ? 3 : 4;
846 884 : vector<unsigned int> v = SDMDataObjectParser::parseProjectPath(a_node, pathLen);
847 :
848 : // Check conformity of execBlockNum, scanNum and subscanNum.
849 884 : if (v.at(0) != sdmTPDataSubset.owner()->execBlockNum()
850 884 : || v.at(1) != sdmTPDataSubset.owner()->scanNum()
851 1768 : || v.at(2) != sdmTPDataSubset.owner()->subscanNum())
852 0 : throw SDMDataObjectParserException("The project path of this data subset '"
853 0 : +SDMDataObjectParser::parseStringAttr(a_node, PROJECTPATH)
854 0 : +"' is not compatible with the project path announced in the global header"
855 0 : +" '"+sdmTPDataSubset.owner()->projectPath()+"'");
856 :
857 884 : if (pathLen == 4)
858 0 : sdmTPDataSubset.integrationNum_ = v.at(3);
859 :
860 : // Traverse the children...
861 884 : xmlNode* child = a_node->children;
862 :
863 : // <schedulePeriodTime...
864 884 : parseSchedulePeriodTime(child, sdmTPDataSubset);
865 :
866 : // <dataStruct...
867 884 : child = child->next;
868 884 : SDMDataObjectParser::isElement(child, TPSubsetHeaderParser::DATASTRUCT);
869 884 : sdmTPDataSubset.dataStruct_ = (SDMDataObjectParser::parseStringAttr(child, TPSubsetHeaderParser::REF));
870 :
871 884 : child = child->next;
872 : // Optional flags attachments.
873 884 : if (SDMDataObjectParser::testElement(child, FLAGSREF)) {
874 715 : sdmTPDataSubset.flagsREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
875 715 : child = child->next;
876 : }
877 :
878 884 : if (SDMDataObjectParser::testElement(child, ACTUALTIMESREF)) {
879 169 : sdmTPDataSubset.actualTimesREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
880 169 : child = child->next;
881 : }
882 :
883 884 : if (SDMDataObjectParser::testElement(child, ACTUALDURATIONSREF)) {
884 861 : sdmTPDataSubset.actualDurationsREF_ = SDMDataObjectParser::parseStringAttr(child, XLINKHREF);
885 861 : child = child->next;
886 : }
887 :
888 : // Look for mandatory autoData element.
889 884 : SDMDataObjectParser::isElement(child, AUTODATAREF);
890 884 : sdmTPDataSubset.autoDataREF_ = (SDMDataObjectParser::parseStringAttr(child, TPSubsetHeaderParser::XLINKHREF ));
891 884 : }
892 :
893 0 : void TPSubsetHeaderParser::parseProjectPath(xmlNode* a_node, SDMDataSubset& sdmTPDataSubset) {
894 0 : string projectPath = SDMDataObjectParser::parseStringAttr(a_node,TPSubsetHeaderParser::PROJECTPATH);
895 :
896 0 : std::cmatch what;
897 0 : unsigned int execBlockNum = 0;
898 0 : unsigned int scanNum = 0;
899 0 : unsigned int subscanNum = 0;
900 :
901 0 : if (std::regex_match(projectPath.c_str(), what, PROJECTPATH3) && what[0].matched) {
902 0 : execBlockNum = ::atoi(what[1].first);
903 0 : scanNum = ::atoi(what[2].first);
904 0 : subscanNum = ::atoi(what[3].first);
905 : }
906 : else
907 0 : throw SDMDataObjectParserException("Invalid string for projectPath '" + projectPath + "'");
908 :
909 0 : if (execBlockNum != sdmTPDataSubset.owner()->execBlockNum()
910 0 : || scanNum != sdmTPDataSubset.owner()->scanNum()
911 0 : || subscanNum != sdmTPDataSubset.owner()->subscanNum())
912 0 : throw SDMDataObjectParserException("The project path of this data subset '"
913 0 : +projectPath
914 0 : +"' is not compatible with the project path announced in the global header"
915 0 : +" '"+sdmTPDataSubset.owner()->projectPath()+"'");
916 0 : }
917 :
918 884 : void TPSubsetHeaderParser::parseSchedulePeriodTime(xmlNode* a_node, SDMDataSubset& sdmTPDataSubset) {
919 884 : SDMDataObjectParser::isElement(a_node, TPSubsetHeaderParser::SCHEDULEPERIODTIME);
920 :
921 884 : xmlNode* child = a_node->children;
922 : // <time...
923 884 : sdmTPDataSubset.time_ = parseTime(child);
924 :
925 : // <interval...
926 884 : child = child->next;
927 884 : sdmTPDataSubset.interval_ = parseInterval(child);
928 884 : }
929 :
930 884 : long long TPSubsetHeaderParser::parseTime(xmlNode* a_node) {
931 884 : SDMDataObjectParser::isElement(a_node, TPSubsetHeaderParser::TIME);
932 884 : return SDMDataObjectParser::parseLongLong(a_node->children);
933 : }
934 :
935 :
936 884 : long long TPSubsetHeaderParser::parseInterval(xmlNode* a_node) {
937 884 : SDMDataObjectParser::isElement(a_node, TPSubsetHeaderParser::INTERVAL);
938 884 : return SDMDataObjectParser::parseLongLong(a_node->children);
939 : }
940 : // SDMDataObject::TPSubsetHeaderParser:: methods.
941 :
942 :
943 : // SDMDataObjectHeaderParser:: methods.
944 336925 : void SDMDataObjectParser::isElement(xmlNode* a_node, const string& elementName) {
945 : //cout << "Entering isElement for " << a_node->name << endl;
946 673850 : if ((a_node == NULL) ||
947 673850 : (a_node->type != XML_ELEMENT_NODE) ||
948 336925 : (elementName.compare((const char*)a_node->name) != 0)) {
949 0 : ostringstream oss;
950 0 : oss << "Could not find '<" << elementName << "...";
951 0 : if ((a_node != NULL) && (a_node->type == XML_ELEMENT_NODE))
952 0 : oss << " ( I was given '<" << a_node->name <<"...')";
953 : else
954 0 : oss << " ( node is not an xml element ) " << endl;
955 :
956 0 : throw SDMDataObjectParserException(oss.str());
957 0 : }
958 : //cout << "Exiting isElement" << endl;
959 336925 : }
960 :
961 235472 : bool SDMDataObjectParser::testElement(xmlNode* a_node, const string& elementName) {
962 : //cout << "Entering testElement with " << elementName << " against " << a_node->name << endl;
963 214010 : bool result = ((a_node != NULL) &&
964 449482 : (a_node->type == XML_ELEMENT_NODE) &&
965 214010 : (elementName.compare((const char*)a_node->name) == 0));
966 235472 : return result;
967 : }
968 :
969 0 : void SDMDataObjectParser::inElements(xmlNode* a_node, const vector<string>& elementNames) {
970 0 : if (find(elementNames.begin(), elementNames.end(), string((char*) a_node->name)) == elementNames.end()) {
971 0 : ostringstream message;
972 0 : copy(elementNames.begin(), elementNames.end(), ostream_iterator<string>(message, " "));
973 0 : throw SDMDataObjectParserException("Could not find any of elements '" + message.str()+"' in " + string((const char*) a_node->name));
974 0 : }
975 0 : }
976 :
977 340447 : xmlAttr* SDMDataObjectParser::hasAttr(xmlNode* a_node, const string& attrName) {
978 340447 : xmlAttr* result = 0;
979 687772 : for (struct _xmlAttr* attr = a_node->properties; attr; attr = attr->next) {
980 678733 : if (attrName.compare((const char*) attr->name) == 0) {
981 331408 : result = attr;
982 331408 : break;
983 : }
984 : }
985 340447 : return result;
986 : }
987 :
988 23802 : void SDMDataObjectParser::tokenize(const string& str,
989 : vector<string>& tokens,
990 : const string& delimiters) {
991 : // Skip delimiters at beginning.
992 23802 : string::size_type lastPos = str.find_first_not_of(delimiters, 0);
993 : // Find first "non-delimiter".
994 23802 : string::size_type pos = str.find_first_of(delimiters, lastPos);
995 :
996 85452 : while (string::npos != pos || string::npos != lastPos) {
997 : // Found a token, add it to the vector.
998 61650 : tokens.push_back(str.substr(lastPos, pos - lastPos));
999 : // Skip delimiters. Note the "not_of"
1000 61650 : lastPos = str.find_first_not_of(delimiters, pos);
1001 : // Find next "non-delimiter"
1002 61650 : pos = str.find_first_of(delimiters, lastPos);
1003 : }
1004 23802 : }
1005 :
1006 :
1007 0 : void SDMDataObjectParser::tokenize(const string& str,
1008 : set<string>& tokens,
1009 : const string& delimiters) {
1010 : // Skip delimiters at beginning.
1011 0 : string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1012 : // Find first "non-delimiter".
1013 0 : string::size_type pos = str.find_first_of(delimiters, lastPos);
1014 :
1015 0 : while (string::npos != pos || string::npos != lastPos) {
1016 : // Found a token, add it to the vector.
1017 0 : tokens.insert(str.substr(lastPos, pos - lastPos));
1018 : // Skip delimiters. Note the "not_of"
1019 0 : lastPos = str.find_first_not_of(delimiters, pos);
1020 : // Find next "non-delimiter"
1021 0 : pos = str.find_first_of(delimiters, lastPos);
1022 : }
1023 0 : }
1024 :
1025 55325 : string SDMDataObjectParser::substring(const string &s, int a, int b) {
1026 55325 : return s.substr(a,(b - a));
1027 : }
1028 :
1029 55325 : string SDMDataObjectParser::trim(const string& s) {
1030 55325 : unsigned int i = 0;
1031 55325 : while (s.at(i) == ' ' && i < s.length())
1032 0 : ++i;
1033 55325 : if (i == s.length())
1034 0 : return "";
1035 55325 : unsigned int j = s.length() - 1;
1036 55325 : while (s.at(j) == ' ' && j > i)
1037 0 : --j;
1038 55325 : return substring(s,i,j + 1);
1039 : }
1040 :
1041 0 : string SDMDataObjectParser::parseString(xmlNode* a_node) {
1042 0 : if ((a_node != NULL) && (a_node->next == NULL))
1043 0 : return string((const char*) a_node->content);
1044 :
1045 0 : throw SDMDataObjectParserException("Invalid node , can't be parsed into a long long");
1046 :
1047 : }
1048 :
1049 87287 : long long SDMDataObjectParser::parseLongLong(xmlNode* a_node) {
1050 87287 : if ((a_node != NULL) && (a_node->next == NULL)) {
1051 87287 : istringstream in;
1052 87287 : in.str((const char*) a_node->content);
1053 : long long x;
1054 87287 : in >> x;
1055 87287 : if (in.rdstate() == istream::failbit)
1056 0 : throw SDMDataObjectParserException("failed to parse '"+string((const char*)a_node->content)+"' as a long long in" + string((const char*)a_node->parent->name));
1057 87287 : return x;
1058 87287 : }
1059 :
1060 0 : throw SDMDataObjectParserException("Invalid node , can't be parsed into a long long");
1061 : }
1062 :
1063 37874 : int SDMDataObjectParser::parseInt(xmlNode* a_node) {
1064 : //cout << "Entering parseInt with " << a_node->content << endl;
1065 37874 : if ((a_node != NULL) && (a_node->next == NULL)) {
1066 37874 : const std::regex UINT("[0-9]+");
1067 37874 : std::cmatch what;
1068 37874 : if (std::regex_match((char*)a_node->content, what, UINT)) {
1069 75748 : return (::atoi(what[0].first));
1070 : }
1071 : else
1072 0 : throw SDMDataObjectParserException("failed to parse '"+string((const char*)a_node->content)+"' as an int in " + string((const char*)a_node->parent->name));
1073 37874 : }
1074 :
1075 0 : throw SDMDataObjectParserException("Invalid node , can't be parsed into an int");
1076 : }
1077 :
1078 2881 : bool SDMDataObjectParser::parseBool(xmlNode* a_node) {
1079 2881 : if ((a_node != NULL) && (a_node->next == NULL)) {
1080 2881 : const std::regex TORF("true|false");
1081 2881 : std::cmatch what;
1082 2881 : if (std::regex_match((char*)a_node->content, what, TORF)) {
1083 5762 : return ( *(what[0].first) == 't') ? true:false;
1084 : }
1085 : else
1086 0 : throw SDMDataObjectParserException("failed to parse '"+string((const char*)a_node->content)+"' as an int in " + string((const char*)a_node->parent->name));
1087 2881 : }
1088 :
1089 0 : throw SDMDataObjectParserException("Invalid node , can't be parsed into an bool");
1090 : }
1091 :
1092 3099 : float SDMDataObjectParser::parseFloat(xmlNode* a_node) {
1093 3099 : if ((a_node != NULL) && (a_node->next == NULL)) {
1094 3099 : istringstream in;
1095 3099 : in.str((const char*) a_node->content);
1096 : float x;
1097 3099 : in >> x;
1098 3099 : if (in.rdstate() == istream::failbit)
1099 0 : throw SDMDataObjectParserException("failed to parse '"+string((const char*)a_node->content)+"' as a float in " + string((const char*)a_node->parent->name));
1100 3099 : return x;
1101 3099 : }
1102 :
1103 0 : throw SDMDataObjectParserException("Invalid node , can't be parsed into an float");
1104 : }
1105 :
1106 31964 : int SDMDataObjectParser::parseIntAttr(xmlNode* a_node, const string& attrName) {
1107 31964 : xmlAttr* attr = 0;
1108 :
1109 31964 : if ((attr = hasAttr(a_node, attrName))) {
1110 31964 : int result =parseInt(attr->children);
1111 31964 : return result;
1112 : }
1113 0 : else throw SDMDataObjectParserException("could not find attribute '" + attrName + "' in " + string((const char*)a_node->name));
1114 : }
1115 :
1116 2881 : bool SDMDataObjectParser::parseBoolAttr(xmlNode* a_node, const string& attrName) {
1117 2881 : xmlAttr* attr = 0;
1118 :
1119 2881 : if ((attr = hasAttr(a_node, attrName))) {
1120 2881 : bool result = parseBool(attr->children);
1121 2881 : return result;
1122 : }
1123 0 : else throw SDMDataObjectParserException("could not find attribute '" + attrName + "' in " + string((const char*)a_node->name));
1124 : }
1125 :
1126 3099 : float SDMDataObjectParser::parseFloatAttr(xmlNode* a_node, const string& attrName) {
1127 3099 : xmlAttr* attr = 0;
1128 :
1129 3099 : if ((attr = hasAttr(a_node, attrName))) {
1130 3099 : float result = parseFloat(attr->children);
1131 : //cout << attr->name << " = " << result << endl;
1132 3099 : return result;
1133 : }
1134 0 : else throw SDMDataObjectParserException("could not find attribute '" + attrName + "' in " + string((const char*)a_node->name));
1135 : }
1136 :
1137 :
1138 223568 : string SDMDataObjectParser::parseStringAttr(xmlNode* a_node, const string& attrName) {
1139 : //cout << "Entering parseStringAttr with " << attrName << " in " << a_node->name << endl;
1140 223568 : xmlAttr* attr = 0;
1141 :
1142 223568 : if ((attr = hasAttr(a_node, attrName))) {
1143 223568 : string result = string((const char*)attr->children->content);
1144 : //cout << attr->name << " = " << result << endl;
1145 447136 : return result;
1146 223568 : }
1147 0 : else throw SDMDataObjectParserException("could not find attribute '" + attrName + "' in " + string((const char*)a_node->name));
1148 : }
1149 :
1150 :
1151 0 : vector<string> SDMDataObjectParser::parseStringsAttr(xmlNode* a_node, const string& attrName) {
1152 0 : xmlAttr* attr = 0;
1153 :
1154 0 : if ((attr = hasAttr(a_node, attrName))) {
1155 0 : vector<string> result;
1156 0 : tokenize((const char*)attr->children->content, result);
1157 : //cout << attr->name << " = '"; copy(result.begin(), result.end(), ostream_iterator<string>(cout, " ")); cout << "'" << endl;
1158 0 : return result;
1159 0 : }
1160 0 : else throw SDMDataObjectParserException("could not find attribute '" + attrName + "' in " + string((const char*)a_node->name));
1161 : }
1162 :
1163 0 : set<string> SDMDataObjectParser::parseStringSetAttr(xmlNode* a_node, const string& attrName) {
1164 0 : xmlAttr* attr = 0;
1165 :
1166 0 : if ((attr = hasAttr(a_node, attrName))) {
1167 0 : set<string> result;
1168 0 : tokenize((const char*)attr->children->content, result);
1169 : //cout << attr->name << " = '"; copy(result.begin(), result.end(), ostream_iterator<string>(cout, " ")); cout << "'" << endl;
1170 0 : return result;
1171 0 : }
1172 0 : else throw SDMDataObjectParserException("could not find attribute '" + attrName + "' in " + string((const char*)a_node->name));
1173 : }
1174 :
1175 :
1176 3839 : vector<unsigned int> SDMDataObjectParser::parseProjectPath(xmlNode* a_node, unsigned int len) {
1177 3839 : string projectPath = SDMDataObjectParser::parseStringAttr(a_node, HeaderParser::PROJECTPATH);
1178 3839 : vector<unsigned int> result;
1179 3839 : bool matched = true;
1180 3839 : std::cmatch what;
1181 3839 : switch (len) {
1182 3839 : case 3: matched = std::regex_match(projectPath.c_str(), what, PROJECTPATH3); break;
1183 0 : case 4: matched = std::regex_match(projectPath.c_str(), what, PROJECTPATH4); break;
1184 0 : case 5: matched = std::regex_match(projectPath.c_str(), what, PROJECTPATH5); break;
1185 0 : default: throw SDMDataObjectParserException ("internal error in method 'parseProjectPath'. The parameter 'len' has a value out of the range [3,5]");
1186 : }
1187 :
1188 3839 : if (!matched)
1189 0 : throw SDMDataObjectException("'" + projectPath + "' is an invalid string for a 'projectPath' attribute");
1190 :
1191 15356 : for (unsigned int i = 0; i < len; i++) {
1192 11517 : result.push_back(::atoi(what[i+1].first));
1193 : }
1194 7678 : return result;
1195 3839 : }
1196 :
1197 : const std::regex SDMDataObjectParser::PROJECTPATH4OR5("([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+/)?");
1198 41282 : vector<unsigned int> SDMDataObjectParser::parseProjectPath(xmlNode* a_node) {
1199 41282 : string projectPath = SDMDataObjectParser::parseStringAttr(a_node, HeaderParser::PROJECTPATH);
1200 41282 : vector<unsigned int> result;
1201 :
1202 41282 : bool matched = true;
1203 :
1204 41282 : std::cmatch what;
1205 41282 : matched = std::regex_match(projectPath.c_str(), what, PROJECTPATH4OR5);
1206 :
1207 41282 : if (!matched)
1208 0 : throw SDMDataObjectException("'" + projectPath + "' is an invalid string for a 'projectPath' attribute.");
1209 :
1210 : // Let's retrieve the 4 first numbers.
1211 206410 : for (unsigned int i = 0; i < 4; i++)
1212 165128 : result.push_back(::atoi(what[i+1].first));
1213 :
1214 : // and the fifth if it exists...
1215 41282 : if (what[5].matched) {
1216 20131 : result.push_back(::atoi(what[5].first));
1217 : }
1218 :
1219 82564 : return result;
1220 41282 : }
1221 :
1222 2955 : const ByteOrder* SDMDataObjectParser::parseByteOrderAttr(xmlNode* a_node, const string& attrName) {
1223 2955 : string byteOrder = SDMDataObjectParser::parseStringAttr(a_node, attrName);
1224 :
1225 2955 : if (byteOrder.compare("Little_Endian")==0) return ByteOrder::Little_Endian;
1226 0 : if (byteOrder.compare("Big_Endian")==0) return ByteOrder::Big_Endian;
1227 :
1228 0 : throw SDMDataObjectParserException("'" + byteOrder + "' is an invalid string for a 'byteOrder' attribute.");
1229 2955 : }
1230 :
1231 936 : SDMDataObjectParser::SDMDataObjectParser() {;}
1232 936 : SDMDataObjectParser::~SDMDataObjectParser() {;}
1233 :
1234 0 : void SDMDataObjectParser::parseFileHeader(const string& filename, SDMDataObject& sdmDataObject) {
1235 0 : headerParser.parseFile(filename, sdmDataObject);
1236 0 : }
1237 :
1238 2955 : void SDMDataObjectParser::parseMemoryHeader(const string& buffer, SDMDataObject& sdmDataObject) {
1239 2955 : headerParser.parseMemory(buffer, sdmDataObject);
1240 2955 : }
1241 :
1242 0 : void SDMDataObjectParser::parseFileCorrSubsetHeader(const string& filename, SDMDataSubset& sdmCorrDataSubset) {
1243 0 : corrSubsetHeaderParser.parseFile(filename, sdmCorrDataSubset);
1244 0 : }
1245 :
1246 41282 : void SDMDataObjectParser::parseMemoryCorrSubsetHeader(const string& buffer, SDMDataSubset& sdmCorrDataSubset) {
1247 41282 : corrSubsetHeaderParser.parseMemory(buffer, sdmCorrDataSubset);
1248 41282 : }
1249 :
1250 0 : void SDMDataObjectParser::parseFileTPSubsetHeader(const string& filename, SDMDataSubset& sdmCorrDataSubset) {
1251 0 : tpSubsetHeaderParser.parseFile(filename, sdmCorrDataSubset);
1252 0 : }
1253 :
1254 884 : void SDMDataObjectParser::parseMemoryTPSubsetHeader(const string& buffer, SDMDataSubset& sdmCorrDataSubset) {
1255 884 : tpSubsetHeaderParser.parseMemory(buffer, sdmCorrDataSubset);
1256 884 : }
1257 :
1258 : }
1259 :
1260 : #if 0
1261 : using namespace asdmbinaries;
1262 : int main (int argC, char* argV[]) {
1263 :
1264 : if (argC != 3) return (1);
1265 :
1266 : SDMDataObjectParser parser;
1267 : SDMDataObject sdmDataObject;
1268 :
1269 : SDMDataSubset sdmDataSubset;
1270 :
1271 : cout << "Trying to parse an SDMDataHeader in " << argV[1] << " and an SDMDataSubsetHeader in " << argV[2] <<endl;
1272 : try {
1273 : parser.parseFileHeader(argV[1], sdmDataObject);
1274 : cout << "----- SDMDataObject ------" << endl;
1275 : cout << "SDMDataHeader: " << endl;
1276 : cout << endl;
1277 : cout << sdmDataObject.toString() << endl;
1278 :
1279 : // Now process the sdmDataSubsetHeader passed in argV[2]
1280 : switch (sdmDataObject.dimensionality()) {
1281 : case 0:
1282 : {
1283 : parser.parseFileTPSubsetHeader(argV[2], sdmDataSubset);
1284 : cout << endl;
1285 : cout << "SDMDataSubsetHeader: " << endl;
1286 : cout << endl;
1287 : cout << sdmDataSubset.toString(sdmDataObject.dimensionality()) << endl;
1288 : break;
1289 : }
1290 :
1291 : case 1:
1292 : {
1293 : parser.parseFileCorrSubsetHeader(argV[2], sdmDataSubset);
1294 : cout << endl;
1295 : cout << "SDMDataSubsetHeader: " << endl;
1296 : cout << endl;
1297 : cout << sdmDataSubset.toString(sdmDataObject.dimensionality());
1298 : break;
1299 : }
1300 :
1301 : default:
1302 : break;
1303 : }
1304 : }
1305 : catch (SDMDataObjectParserException e) {
1306 : cout << e.getMessage() << endl;
1307 : exit(1);
1308 : }
1309 :
1310 : cout << endl;
1311 : cout << "----------------------" << endl;
1312 : cout << "XML representation of the sdmDataHeader: " << endl;
1313 : cout << endl;
1314 : cout << sdmDataObject.toXML() << endl;
1315 :
1316 : cout << endl;
1317 : cout << "----------------------" << endl;
1318 : cout << "XML representation of the sdmDataSubsetHeader: " << endl;
1319 : cout << endl;
1320 : cout << sdmDataSubset.toXML(sdmDataObject.dimensionality()) << endl;
1321 : }
1322 : #endif
|