Line data Source code
1 :
2 : /*
3 : * ALMA - Atacama Large Millimeter Array
4 : * (c) European Southern Observatory, 2002
5 : * (c) Associated Universities Inc., 2002
6 : * Copyright by ESO (in the framework of the ALMA collaboration),
7 : * Copyright by AUI (in the framework of the ALMA collaboration),
8 : * All rights reserved.
9 : *
10 : * This library is free software; you can redistribute it and/or
11 : * modify it under the terms of the GNU Lesser General Public
12 : * License as published by the Free software Foundation; either
13 : * version 2.1 of the License, or (at your option) any later version.
14 : *
15 : * This library is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY, without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : * Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; if not, write to the Free Software
22 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 : * MA 02111-1307 USA
24 : *
25 : * Warning!
26 : * --------------------------------------------------------------------
27 : * | This is generated code! Do not modify this file. |
28 : * | If you do, all changes will be lost when the file is re-generated. |
29 : * --------------------------------------------------------------------
30 : *
31 : * File CalBandpassTable.cpp
32 : */
33 : #include <alma/ASDM/ConversionException.h>
34 : #include <alma/ASDM/DuplicateKey.h>
35 : #include <alma/ASDM/OutOfBoundsException.h>
36 :
37 : using asdm::ConversionException;
38 : using asdm::DuplicateKey;
39 : using asdm::OutOfBoundsException;
40 :
41 : #include <alma/ASDM/ASDM.h>
42 : #include <alma/ASDM/CalBandpassTable.h>
43 : #include <alma/ASDM/CalBandpassRow.h>
44 : #include <alma/ASDM/Parser.h>
45 :
46 : using asdm::ASDM;
47 : using asdm::CalBandpassTable;
48 : using asdm::CalBandpassRow;
49 : using asdm::Parser;
50 :
51 : #include <iostream>
52 : #include <fstream>
53 : #include <iterator>
54 : #include <sstream>
55 : #include <set>
56 : #include <algorithm>
57 : using namespace std;
58 :
59 : #include <alma/ASDM/Misc.h>
60 : using namespace asdm;
61 :
62 : #include <libxml/parser.h>
63 : #include <libxml/tree.h>
64 :
65 : #ifndef WITHOUT_BOOST
66 : #include "boost/filesystem/operations.hpp"
67 : #include <boost/algorithm/string.hpp>
68 : #else
69 : #include <sys/stat.h>
70 : #endif
71 :
72 : namespace asdm {
73 : // The name of the entity we will store in this table.
74 : static string entityNameOfCalBandpass = "CalBandpass";
75 :
76 : // An array of string containing the names of the columns of this table.
77 : // The array is filled in the order : key, required value, optional value.
78 : //
79 : static string attributesNamesOfCalBandpass_a[] = {
80 :
81 : "basebandName"
82 : ,
83 : "sideband"
84 : ,
85 : "atmPhaseCorrection"
86 : ,
87 : "typeCurve"
88 : ,
89 : "receiverBand"
90 : ,
91 : "calDataId"
92 : ,
93 : "calReductionId"
94 :
95 :
96 : , "startValidTime"
97 :
98 : , "endValidTime"
99 :
100 : , "numAntenna"
101 :
102 : , "numPoly"
103 :
104 : , "numReceptor"
105 :
106 : , "antennaNames"
107 :
108 : , "refAntennaName"
109 :
110 : , "freqLimits"
111 :
112 : , "polarizationTypes"
113 :
114 : , "curve"
115 :
116 : , "reducedChiSquared"
117 :
118 :
119 : , "numBaseline"
120 :
121 : , "numFreq"
122 :
123 : , "rms"
124 :
125 : , "frequencyRange"
126 :
127 : , "numSpectralWindow"
128 :
129 : , "chanFreqStart"
130 :
131 : , "chanFreqStep"
132 :
133 : , "numSpectralWindowChan"
134 :
135 : , "spectrum"
136 :
137 : };
138 :
139 : // A vector of string whose content is a copy of the strings in the array above.
140 : //
141 : static vector<string> attributesNamesOfCalBandpass_v (attributesNamesOfCalBandpass_a, attributesNamesOfCalBandpass_a + sizeof(attributesNamesOfCalBandpass_a) / sizeof(attributesNamesOfCalBandpass_a[0]));
142 :
143 : // An array of string containing the names of the columns of this table.
144 : // The array is filled in the order where the names would be read by default in the XML header of a file containing
145 : // the table exported in binary mode.
146 : //
147 : static string attributesNamesInBinOfCalBandpass_a[] = {
148 :
149 : "basebandName" , "sideband" , "atmPhaseCorrection" , "typeCurve" , "receiverBand" , "calDataId" , "calReductionId" , "startValidTime" , "endValidTime" , "numAntenna" , "numPoly" , "numReceptor" , "antennaNames" , "refAntennaName" , "freqLimits" , "polarizationTypes" , "curve" , "reducedChiSquared"
150 : ,
151 : "numBaseline" , "numFreq" , "rms" , "frequencyRange" , "numSpectralWindow" , "chanFreqStart" , "chanFreqStep" , "numSpectralWindowChan" , "spectrum"
152 :
153 : };
154 :
155 : // A vector of string whose content is a copy of the strings in the array above.
156 : //
157 : static vector<string> attributesNamesInBinOfCalBandpass_v(attributesNamesInBinOfCalBandpass_a, attributesNamesInBinOfCalBandpass_a + sizeof(attributesNamesInBinOfCalBandpass_a) / sizeof(attributesNamesInBinOfCalBandpass_a[0]));
158 :
159 :
160 : // The array of attributes (or column) names that make up key key.
161 : //
162 : string keyOfCalBandpass_a[] = {
163 :
164 : "basebandName"
165 : ,
166 : "sideband"
167 : ,
168 : "atmPhaseCorrection"
169 : ,
170 : "typeCurve"
171 : ,
172 : "receiverBand"
173 : ,
174 : "calDataId"
175 : ,
176 : "calReductionId"
177 :
178 : };
179 :
180 : // A vector of strings which are copies of those stored in the array above.
181 : vector<string> keyOfCalBandpass_v(keyOfCalBandpass_a, keyOfCalBandpass_a + sizeof(keyOfCalBandpass_a) / sizeof(keyOfCalBandpass_a[0]));
182 :
183 : /**
184 : * Return the list of field names that make up key key
185 : * as a const reference to a vector of strings.
186 : */
187 0 : const vector<string>& CalBandpassTable::getKeyName() {
188 0 : return keyOfCalBandpass_v;
189 : }
190 :
191 :
192 4 : CalBandpassTable::CalBandpassTable(ASDM &c) : container(c) {
193 :
194 : // Define a default entity.
195 4 : entity.setEntityId(EntityId("uid://X0/X0/X0"));
196 4 : entity.setEntityIdEncrypted("na");
197 4 : entity.setEntityTypeName("CalBandpassTable");
198 4 : entity.setEntityVersion("1");
199 4 : entity.setInstanceVersion("1");
200 :
201 : // Archive XML
202 4 : archiveAsBin = true;
203 :
204 : // File XML
205 4 : fileAsBin = true;
206 :
207 : // By default the table is considered as present in memory
208 4 : presentInMemory = true;
209 :
210 : // By default there is no load in progress
211 4 : loadInProgress = false;
212 4 : }
213 :
214 : /**
215 : * A destructor for CalBandpassTable.
216 : */
217 8 : CalBandpassTable::~CalBandpassTable() {
218 4 : for (unsigned int i = 0; i < privateRows.size(); i++)
219 0 : delete(privateRows.at(i));
220 8 : }
221 :
222 : /**
223 : * Container to which this table belongs.
224 : */
225 0 : ASDM &CalBandpassTable::getContainer() const {
226 0 : return container;
227 : }
228 :
229 : /**
230 : * Return the number of rows in the table.
231 : */
232 0 : unsigned int CalBandpassTable::size() const {
233 0 : if (presentInMemory)
234 0 : return privateRows.size();
235 : else
236 0 : return declaredSize;
237 : }
238 :
239 : /**
240 : * Return the name of this table.
241 : */
242 196 : string CalBandpassTable::getName() const {
243 196 : return entityNameOfCalBandpass;
244 : }
245 :
246 : /**
247 : * Return the name of this table.
248 : */
249 0 : string CalBandpassTable::name() {
250 0 : return entityNameOfCalBandpass;
251 : }
252 :
253 : /**
254 : * Return the the names of the attributes (or columns) of this table.
255 : */
256 0 : const vector<string>& CalBandpassTable::getAttributesNames() { return attributesNamesOfCalBandpass_v; }
257 :
258 : /**
259 : * Return the the names of the attributes (or columns) of this table as they appear by default
260 : * in an binary export of this table.
261 : */
262 0 : const vector<string>& CalBandpassTable::defaultAttributesNamesInBin() { return attributesNamesInBinOfCalBandpass_v; }
263 :
264 : /**
265 : * Return this table's Entity.
266 : */
267 0 : Entity CalBandpassTable::getEntity() const {
268 0 : return entity;
269 : }
270 :
271 : /**
272 : * Set this table's Entity.
273 : */
274 0 : void CalBandpassTable::setEntity(Entity e) {
275 0 : this->entity = e;
276 0 : }
277 :
278 : //
279 : // ====> Row creation.
280 : //
281 :
282 : /**
283 : * Create a new row.
284 : */
285 0 : CalBandpassRow *CalBandpassTable::newRow() {
286 0 : return new CalBandpassRow (*this);
287 : }
288 :
289 :
290 : /**
291 : * Create a new row initialized to the specified values.
292 : * @return a pointer on the created and initialized row.
293 :
294 : * @param basebandName
295 :
296 : * @param sideband
297 :
298 : * @param atmPhaseCorrection
299 :
300 : * @param typeCurve
301 :
302 : * @param receiverBand
303 :
304 : * @param calDataId
305 :
306 : * @param calReductionId
307 :
308 : * @param startValidTime
309 :
310 : * @param endValidTime
311 :
312 : * @param numAntenna
313 :
314 : * @param numPoly
315 :
316 : * @param numReceptor
317 :
318 : * @param antennaNames
319 :
320 : * @param refAntennaName
321 :
322 : * @param freqLimits
323 :
324 : * @param polarizationTypes
325 :
326 : * @param curve
327 :
328 : * @param reducedChiSquared
329 :
330 : */
331 0 : CalBandpassRow* CalBandpassTable::newRow(BasebandNameMod::BasebandName basebandName, NetSidebandMod::NetSideband sideband, AtmPhaseCorrectionMod::AtmPhaseCorrection atmPhaseCorrection, CalCurveTypeMod::CalCurveType typeCurve, ReceiverBandMod::ReceiverBand receiverBand, Tag calDataId, Tag calReductionId, ArrayTime startValidTime, ArrayTime endValidTime, int numAntenna, int numPoly, int numReceptor, std::vector<std::string > antennaNames, std::string refAntennaName, std::vector<Frequency > freqLimits, std::vector<PolarizationTypeMod::PolarizationType > polarizationTypes, std::vector<std::vector<std::vector<float > > > curve, std::vector<double > reducedChiSquared){
332 0 : CalBandpassRow *row = new CalBandpassRow(*this);
333 :
334 0 : row->setBasebandName(basebandName);
335 :
336 0 : row->setSideband(sideband);
337 :
338 0 : row->setAtmPhaseCorrection(atmPhaseCorrection);
339 :
340 0 : row->setTypeCurve(typeCurve);
341 :
342 0 : row->setReceiverBand(receiverBand);
343 :
344 0 : row->setCalDataId(calDataId);
345 :
346 0 : row->setCalReductionId(calReductionId);
347 :
348 0 : row->setStartValidTime(startValidTime);
349 :
350 0 : row->setEndValidTime(endValidTime);
351 :
352 0 : row->setNumAntenna(numAntenna);
353 :
354 0 : row->setNumPoly(numPoly);
355 :
356 0 : row->setNumReceptor(numReceptor);
357 :
358 0 : row->setAntennaNames(antennaNames);
359 :
360 0 : row->setRefAntennaName(refAntennaName);
361 :
362 0 : row->setFreqLimits(freqLimits);
363 :
364 0 : row->setPolarizationTypes(polarizationTypes);
365 :
366 0 : row->setCurve(curve);
367 :
368 0 : row->setReducedChiSquared(reducedChiSquared);
369 :
370 0 : return row;
371 : }
372 :
373 :
374 :
375 0 : CalBandpassRow* CalBandpassTable::newRow(CalBandpassRow* row) {
376 0 : return new CalBandpassRow(*this, row);
377 : }
378 :
379 : //
380 : // Append a row to its table.
381 : //
382 :
383 :
384 :
385 : /**
386 : * Add a row.
387 : * @throws DuplicateKey Thrown if the new row has a key that is already in the table.
388 : * @param x A pointer to the row to be added.
389 : * @return x
390 : */
391 0 : CalBandpassRow* CalBandpassTable::add(CalBandpassRow* x) {
392 :
393 0 : if (getRowByKey(
394 : x->getBasebandName()
395 : ,
396 : x->getSideband()
397 : ,
398 : x->getAtmPhaseCorrection()
399 : ,
400 : x->getTypeCurve()
401 : ,
402 : x->getReceiverBand()
403 : ,
404 0 : x->getCalDataId()
405 : ,
406 0 : x->getCalReductionId()
407 : ))
408 : //throw DuplicateKey(x.getBasebandName() + "|" + x.getSideband() + "|" + x.getAtmPhaseCorrection() + "|" + x.getTypeCurve() + "|" + x.getReceiverBand() + "|" + x.getCalDataId() + "|" + x.getCalReductionId(),"CalBandpass");
409 0 : throw DuplicateKey("Duplicate key exception in ","CalBandpassTable");
410 :
411 0 : row.push_back(x);
412 0 : privateRows.push_back(x);
413 0 : x->isAdded(true);
414 0 : return x;
415 : }
416 :
417 :
418 :
419 0 : void CalBandpassTable::addWithoutCheckingUnique(CalBandpassRow * x) {
420 0 : if (getRowByKey(
421 : x->getBasebandName()
422 : ,
423 : x->getSideband()
424 : ,
425 : x->getAtmPhaseCorrection()
426 : ,
427 : x->getTypeCurve()
428 : ,
429 : x->getReceiverBand()
430 : ,
431 0 : x->getCalDataId()
432 : ,
433 0 : x->getCalReductionId()
434 0 : ) != (CalBandpassRow *) 0)
435 0 : throw DuplicateKey("Dupicate key exception in ", "CalBandpassTable");
436 0 : row.push_back(x);
437 0 : privateRows.push_back(x);
438 0 : x->isAdded(true);
439 0 : }
440 :
441 :
442 :
443 :
444 : //
445 : // A private method to append a row to its table, used by input conversion
446 : // methods, with row uniqueness.
447 : //
448 :
449 :
450 : /**
451 : * If this table has an autoincrementable attribute then check if *x verifies the rule of uniqueness and throw exception if not.
452 : * Check if *x verifies the key uniqueness rule and throw an exception if not.
453 : * Append x to its table.
454 : * @param x a pointer on the row to be appended.
455 : * @returns a pointer on x.
456 : * @throws DuplicateKey
457 :
458 : */
459 0 : CalBandpassRow* CalBandpassTable::checkAndAdd(CalBandpassRow* x, bool skipCheckUniqueness) {
460 0 : if (!skipCheckUniqueness) {
461 :
462 : }
463 :
464 0 : if (getRowByKey(
465 :
466 : x->getBasebandName()
467 : ,
468 : x->getSideband()
469 : ,
470 : x->getAtmPhaseCorrection()
471 : ,
472 : x->getTypeCurve()
473 : ,
474 : x->getReceiverBand()
475 : ,
476 0 : x->getCalDataId()
477 : ,
478 0 : x->getCalReductionId()
479 :
480 0 : )) throw DuplicateKey("Duplicate key exception in ", "CalBandpassTable");
481 :
482 0 : row.push_back(x);
483 0 : privateRows.push_back(x);
484 0 : x->isAdded(true);
485 0 : return x;
486 : }
487 :
488 :
489 :
490 : //
491 : // A private method to brutally append a row to its table, without checking for row uniqueness.
492 : //
493 :
494 0 : void CalBandpassTable::append(CalBandpassRow *x) {
495 0 : privateRows.push_back(x);
496 0 : x->isAdded(true);
497 0 : }
498 :
499 :
500 :
501 :
502 :
503 0 : vector<CalBandpassRow *> CalBandpassTable::get() {
504 0 : checkPresenceInMemory();
505 0 : return privateRows;
506 : }
507 :
508 0 : const vector<CalBandpassRow *>& CalBandpassTable::get() const {
509 0 : const_cast<CalBandpassTable&>(*this).checkPresenceInMemory();
510 0 : return privateRows;
511 : }
512 :
513 :
514 :
515 :
516 :
517 :
518 :
519 :
520 : /*
521 : ** Returns a CalBandpassRow* given a key.
522 : ** @return a pointer to the row having the key whose values are passed as parameters, or 0 if
523 : ** no row exists for that key.
524 : **
525 : */
526 0 : CalBandpassRow* CalBandpassTable::getRowByKey(BasebandNameMod::BasebandName basebandName, NetSidebandMod::NetSideband sideband, AtmPhaseCorrectionMod::AtmPhaseCorrection atmPhaseCorrection, CalCurveTypeMod::CalCurveType typeCurve, ReceiverBandMod::ReceiverBand receiverBand, Tag calDataId, Tag calReductionId) {
527 0 : checkPresenceInMemory();
528 0 : CalBandpassRow* aRow = 0;
529 0 : for (unsigned int i = 0; i < privateRows.size(); i++) {
530 0 : aRow = row.at(i);
531 :
532 :
533 0 : if (aRow->basebandName != basebandName) continue;
534 :
535 :
536 :
537 0 : if (aRow->sideband != sideband) continue;
538 :
539 :
540 :
541 0 : if (aRow->atmPhaseCorrection != atmPhaseCorrection) continue;
542 :
543 :
544 :
545 0 : if (aRow->typeCurve != typeCurve) continue;
546 :
547 :
548 :
549 0 : if (aRow->receiverBand != receiverBand) continue;
550 :
551 :
552 :
553 0 : if (aRow->calDataId != calDataId) continue;
554 :
555 :
556 :
557 0 : if (aRow->calReductionId != calReductionId) continue;
558 :
559 :
560 0 : return aRow;
561 : }
562 0 : return 0;
563 : }
564 :
565 :
566 :
567 : /**
568 : * Look up the table for a row whose all attributes
569 : * are equal to the corresponding parameters of the method.
570 : * @return a pointer on this row if any, 0 otherwise.
571 : *
572 :
573 : * @param basebandName.
574 :
575 : * @param sideband.
576 :
577 : * @param atmPhaseCorrection.
578 :
579 : * @param typeCurve.
580 :
581 : * @param receiverBand.
582 :
583 : * @param calDataId.
584 :
585 : * @param calReductionId.
586 :
587 : * @param startValidTime.
588 :
589 : * @param endValidTime.
590 :
591 : * @param numAntenna.
592 :
593 : * @param numPoly.
594 :
595 : * @param numReceptor.
596 :
597 : * @param antennaNames.
598 :
599 : * @param refAntennaName.
600 :
601 : * @param freqLimits.
602 :
603 : * @param polarizationTypes.
604 :
605 : * @param curve.
606 :
607 : * @param reducedChiSquared.
608 :
609 : */
610 0 : CalBandpassRow* CalBandpassTable::lookup(BasebandNameMod::BasebandName basebandName, NetSidebandMod::NetSideband sideband, AtmPhaseCorrectionMod::AtmPhaseCorrection atmPhaseCorrection, CalCurveTypeMod::CalCurveType typeCurve, ReceiverBandMod::ReceiverBand receiverBand, Tag calDataId, Tag calReductionId, ArrayTime startValidTime, ArrayTime endValidTime, int numAntenna, int numPoly, int numReceptor, std::vector<std::string > antennaNames, std::string refAntennaName, std::vector<Frequency > freqLimits, std::vector<PolarizationTypeMod::PolarizationType > polarizationTypes, std::vector<std::vector<std::vector<float > > > curve, std::vector<double > reducedChiSquared) {
611 : CalBandpassRow* aRow;
612 0 : for (unsigned int i = 0; i < privateRows.size(); i++) {
613 0 : aRow = privateRows.at(i);
614 0 : if (aRow->compareNoAutoInc(basebandName, sideband, atmPhaseCorrection, typeCurve, receiverBand, calDataId, calReductionId, startValidTime, endValidTime, numAntenna, numPoly, numReceptor, antennaNames, refAntennaName, freqLimits, polarizationTypes, curve, reducedChiSquared)) return aRow;
615 : }
616 0 : return 0;
617 : }
618 :
619 :
620 :
621 :
622 :
623 :
624 :
625 : #ifndef WITHOUT_ACS
626 : using asdmIDL::CalBandpassTableIDL;
627 : #endif
628 :
629 : #ifndef WITHOUT_ACS
630 : // Conversion Methods
631 :
632 : CalBandpassTableIDL *CalBandpassTable::toIDL() {
633 : CalBandpassTableIDL *x = new CalBandpassTableIDL ();
634 : unsigned int nrow = size();
635 : x->row.length(nrow);
636 : vector<CalBandpassRow*> v = get();
637 : for (unsigned int i = 0; i < nrow; ++i) {
638 : //x->row[i] = *(v[i]->toIDL());
639 : v[i]->toIDL(x->row[i]);
640 : }
641 : return x;
642 : }
643 :
644 : void CalBandpassTable::toIDL(asdmIDL::CalBandpassTableIDL& x) const {
645 : unsigned int nrow = size();
646 : x.row.length(nrow);
647 : vector<CalBandpassRow*> v = get();
648 : for (unsigned int i = 0; i < nrow; ++i) {
649 : v[i]->toIDL(x.row[i]);
650 : }
651 : }
652 : #endif
653 :
654 : #ifndef WITHOUT_ACS
655 : void CalBandpassTable::fromIDL(CalBandpassTableIDL x) {
656 : unsigned int nrow = x.row.length();
657 : for (unsigned int i = 0; i < nrow; ++i) {
658 : CalBandpassRow *tmp = newRow();
659 : tmp->setFromIDL(x.row[i]);
660 : // checkAndAdd(tmp);
661 : add(tmp);
662 : }
663 : }
664 : #endif
665 :
666 :
667 0 : string CalBandpassTable::toXML() {
668 0 : string buf;
669 :
670 0 : buf.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> ");
671 0 : buf.append("<CalBandpassTable xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:clbndp=\"http://Alma/XASDM/CalBandpassTable\" xsi:schemaLocation=\"http://Alma/XASDM/CalBandpassTable http://almaobservatory.org/XML/XASDM/4/CalBandpassTable.xsd\" schemaVersion=\"4\" schemaRevision=\"-1\">\n");
672 :
673 0 : buf.append(entity.toXML());
674 0 : string s = container.getEntity().toXML();
675 : // Change the "Entity" tag to "ContainerEntity".
676 0 : buf.append("<Container" + s.substr(1,s.length() - 1)+" ");
677 0 : vector<CalBandpassRow*> v = get();
678 0 : for (unsigned int i = 0; i < v.size(); ++i) {
679 : try {
680 0 : buf.append(v[i]->toXML());
681 0 : } catch (const NoSuchRow &e) {
682 0 : }
683 0 : buf.append(" ");
684 : }
685 0 : buf.append("</CalBandpassTable> ");
686 0 : return buf;
687 0 : }
688 :
689 :
690 0 : string CalBandpassTable::getVersion() const {
691 0 : return version;
692 : }
693 :
694 :
695 0 : void CalBandpassTable::fromXML(string& tableInXML) {
696 : //
697 : // Look for a version information in the schemaVersion of the XML
698 : //
699 : xmlDoc *doc;
700 : #if LIBXML_VERSION >= 20703
701 0 : doc = xmlReadMemory(tableInXML.data(), tableInXML.size(), "XMLTableHeader.xml", NULL, XML_PARSE_NOBLANKS|XML_PARSE_HUGE);
702 : #else
703 : doc = xmlReadMemory(tableInXML.data(), tableInXML.size(), "XMLTableHeader.xml", NULL, XML_PARSE_NOBLANKS);
704 : #endif
705 0 : if ( doc == NULL )
706 0 : throw ConversionException("Failed to parse the xmlHeader into a DOM structure.", "CalBandpass");
707 :
708 0 : xmlNode* root_element = xmlDocGetRootElement(doc);
709 0 : if ( root_element == NULL || root_element->type != XML_ELEMENT_NODE )
710 0 : throw ConversionException("Failed to retrieve the root element in the DOM structure.", "CalBandpass");
711 :
712 0 : xmlChar * propValue = xmlGetProp(root_element, (const xmlChar *) "schemaVersion");
713 0 : if ( propValue != 0 ) {
714 0 : version = string( (const char*) propValue);
715 0 : xmlFree(propValue);
716 : }
717 :
718 0 : Parser xml(tableInXML);
719 0 : if (!xml.isStr("<CalBandpassTable"))
720 0 : error();
721 : // cout << "Parsing a CalBandpassTable" << endl;
722 0 : string s = xml.getElement("<Entity","/>");
723 0 : if (s.length() == 0)
724 0 : error();
725 0 : Entity e;
726 0 : e.setFromXML(s);
727 0 : if (e.getEntityTypeName() != "CalBandpassTable")
728 0 : error();
729 0 : setEntity(e);
730 : // Skip the container's entity; but, it has to be there.
731 0 : s = xml.getElement("<ContainerEntity","/>");
732 0 : if (s.length() == 0)
733 0 : error();
734 :
735 : // Get each row in the table.
736 0 : s = xml.getElementContent("<row>","</row>");
737 : CalBandpassRow *row;
738 0 : if (getContainer().checkRowUniqueness()) {
739 : try {
740 0 : while (s.length() != 0) {
741 0 : row = newRow();
742 0 : row->setFromXML(s);
743 0 : checkAndAdd(row);
744 0 : s = xml.getElementContent("<row>","</row>");
745 : }
746 :
747 : }
748 0 : catch (const DuplicateKey &e1) {
749 0 : throw ConversionException(e1.getMessage(),"CalBandpassTable");
750 0 : }
751 0 : catch (const UniquenessViolationException &e1) {
752 0 : throw ConversionException(e1.getMessage(),"CalBandpassTable");
753 0 : }
754 0 : catch (...) {
755 : // cout << "Unexpected error in CalBandpassTable::checkAndAdd called from CalBandpassTable::fromXML " << endl;
756 0 : }
757 : }
758 : else {
759 : try {
760 0 : while (s.length() != 0) {
761 0 : row = newRow();
762 0 : row->setFromXML(s);
763 0 : addWithoutCheckingUnique(row);
764 0 : s = xml.getElementContent("<row>","</row>");
765 : }
766 : }
767 0 : catch (const DuplicateKey &e1) {
768 0 : throw ConversionException(e1.getMessage(),"CalBandpassTable");
769 0 : }
770 0 : catch (...) {
771 : // cout << "Unexpected error in CalBandpassTable::addWithoutCheckingUnique called from CalBandpassTable::fromXML " << endl;
772 0 : }
773 : }
774 :
775 :
776 0 : if (!xml.isStr("</CalBandpassTable>"))
777 0 : error();
778 :
779 : //Does not change the convention defined in the model.
780 : //archiveAsBin = false;
781 : //fileAsBin = false;
782 :
783 : // clean up the xmlDoc pointer
784 0 : if ( doc != NULL ) xmlFreeDoc(doc);
785 :
786 0 : }
787 :
788 :
789 0 : void CalBandpassTable::error() {
790 0 : throw ConversionException("Invalid xml document","CalBandpass");
791 : }
792 :
793 :
794 0 : string CalBandpassTable::MIMEXMLPart(const asdm::ByteOrder* byteOrder) {
795 0 : string UID = getEntity().getEntityId().toString();
796 0 : string withoutUID = UID.substr(6);
797 0 : string containerUID = getContainer().getEntity().getEntityId().toString();
798 0 : ostringstream oss;
799 0 : oss << "<?xml version='1.0' encoding='ISO-8859-1'?>";
800 0 : oss << "\n";
801 0 : oss << "<CalBandpassTable xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:clbndp=\"http://Alma/XASDM/CalBandpassTable\" xsi:schemaLocation=\"http://Alma/XASDM/CalBandpassTable http://almaobservatory.org/XML/XASDM/4/CalBandpassTable.xsd\" schemaVersion=\"4\" schemaRevision=\"-1\">\n";
802 0 : oss<< "<Entity entityId='"<<UID<<"' entityIdEncrypted='na' entityTypeName='CalBandpassTable' schemaVersion='1' documentVersion='1'/>\n";
803 0 : oss<< "<ContainerEntity entityId='"<<containerUID<<"' entityIdEncrypted='na' entityTypeName='ASDM' schemaVersion='1' documentVersion='1'/>\n";
804 0 : oss << "<BulkStoreRef file_id='"<<withoutUID<<"' byteOrder='"<<byteOrder->toString()<<"' />\n";
805 0 : oss << "<Attributes>\n";
806 :
807 0 : oss << "<basebandName/>\n";
808 0 : oss << "<sideband/>\n";
809 0 : oss << "<atmPhaseCorrection/>\n";
810 0 : oss << "<typeCurve/>\n";
811 0 : oss << "<receiverBand/>\n";
812 0 : oss << "<calDataId/>\n";
813 0 : oss << "<calReductionId/>\n";
814 0 : oss << "<startValidTime/>\n";
815 0 : oss << "<endValidTime/>\n";
816 0 : oss << "<numAntenna/>\n";
817 0 : oss << "<numPoly/>\n";
818 0 : oss << "<numReceptor/>\n";
819 0 : oss << "<antennaNames/>\n";
820 0 : oss << "<refAntennaName/>\n";
821 0 : oss << "<freqLimits/>\n";
822 0 : oss << "<polarizationTypes/>\n";
823 0 : oss << "<curve/>\n";
824 0 : oss << "<reducedChiSquared/>\n";
825 :
826 0 : oss << "<numBaseline/>\n";
827 0 : oss << "<numFreq/>\n";
828 0 : oss << "<rms/>\n";
829 0 : oss << "<frequencyRange/>\n";
830 0 : oss << "<numSpectralWindow/>\n";
831 0 : oss << "<chanFreqStart/>\n";
832 0 : oss << "<chanFreqStep/>\n";
833 0 : oss << "<numSpectralWindowChan/>\n";
834 0 : oss << "<spectrum/>\n";
835 0 : oss << "</Attributes>\n";
836 0 : oss << "</CalBandpassTable>\n";
837 :
838 0 : return oss.str();
839 0 : }
840 :
841 0 : string CalBandpassTable::toMIME(const asdm::ByteOrder* byteOrder) {
842 0 : EndianOSStream eoss(byteOrder);
843 :
844 0 : string UID = getEntity().getEntityId().toString();
845 :
846 : // The MIME Header
847 0 : eoss <<"MIME-Version: 1.0";
848 0 : eoss << "\n";
849 0 : eoss << "Content-Type: Multipart/Related; boundary='MIME_boundary'; type='text/xml'; start= '<header.xml>'";
850 0 : eoss <<"\n";
851 0 : eoss <<"Content-Description: Correlator";
852 0 : eoss <<"\n";
853 0 : eoss <<"alma-uid:" << UID;
854 0 : eoss <<"\n";
855 0 : eoss <<"\n";
856 :
857 : // The MIME XML part header.
858 0 : eoss <<"--MIME_boundary";
859 0 : eoss <<"\n";
860 0 : eoss <<"Content-Type: text/xml; charset='ISO-8859-1'";
861 0 : eoss <<"\n";
862 0 : eoss <<"Content-Transfer-Encoding: 8bit";
863 0 : eoss <<"\n";
864 0 : eoss <<"Content-ID: <header.xml>";
865 0 : eoss <<"\n";
866 0 : eoss <<"\n";
867 :
868 : // The MIME XML part content.
869 0 : eoss << MIMEXMLPart(byteOrder);
870 :
871 : // The MIME binary part header
872 0 : eoss <<"--MIME_boundary";
873 0 : eoss <<"\n";
874 0 : eoss <<"Content-Type: binary/octet-stream";
875 0 : eoss <<"\n";
876 0 : eoss <<"Content-ID: <content.bin>";
877 0 : eoss <<"\n";
878 0 : eoss <<"\n";
879 :
880 : // The MIME binary content
881 0 : entity.toBin(eoss);
882 0 : container.getEntity().toBin(eoss);
883 0 : eoss.writeInt((int) privateRows.size());
884 0 : for (unsigned int i = 0; i < privateRows.size(); i++) {
885 0 : privateRows.at(i)->toBin(eoss);
886 : }
887 :
888 : // The closing MIME boundary
889 0 : eoss << "\n--MIME_boundary--";
890 0 : eoss << "\n";
891 :
892 0 : return eoss.str();
893 0 : }
894 :
895 :
896 0 : void CalBandpassTable::setFromMIME(const string & mimeMsg) {
897 0 : string xmlPartMIMEHeader = "Content-ID: <header.xml>\n\n";
898 :
899 0 : string binPartMIMEHeader = "--MIME_boundary\nContent-Type: binary/octet-stream\nContent-ID: <content.bin>\n\n";
900 :
901 : // Detect the XML header.
902 0 : string::size_type loc0 = mimeMsg.find(xmlPartMIMEHeader, 0);
903 0 : if ( loc0 == string::npos) {
904 : // let's try with CRLFs
905 0 : xmlPartMIMEHeader = "Content-ID: <header.xml>\r\n\r\n";
906 0 : loc0 = mimeMsg.find(xmlPartMIMEHeader, 0);
907 0 : if ( loc0 == string::npos )
908 0 : throw ConversionException("Failed to detect the beginning of the XML header", "CalBandpass");
909 : }
910 :
911 0 : loc0 += xmlPartMIMEHeader.size();
912 :
913 : // Look for the string announcing the binary part.
914 0 : string::size_type loc1 = mimeMsg.find( binPartMIMEHeader, loc0 );
915 :
916 0 : if ( loc1 == string::npos ) {
917 0 : throw ConversionException("Failed to detect the beginning of the binary part", "CalBandpass");
918 : }
919 :
920 : //
921 : // Extract the xmlHeader and analyze it to find out what is the byte order and the sequence
922 : // of attribute names.
923 : //
924 0 : string xmlHeader = mimeMsg.substr(loc0, loc1-loc0);
925 : xmlDoc *doc;
926 0 : doc = xmlReadMemory(xmlHeader.data(), xmlHeader.size(), "BinaryTableHeader.xml", NULL, XML_PARSE_NOBLANKS);
927 0 : if ( doc == NULL )
928 0 : throw ConversionException("Failed to parse the xmlHeader into a DOM structure.", "CalBandpass");
929 :
930 : // This vector will be filled by the names of all the attributes of the table
931 : // in the order in which they are expected to be found in the binary representation.
932 : //
933 0 : vector<string> attributesSeq;
934 :
935 0 : xmlNode* root_element = xmlDocGetRootElement(doc);
936 0 : if ( root_element == NULL || root_element->type != XML_ELEMENT_NODE )
937 0 : throw ConversionException("Failed to parse the xmlHeader into a DOM structure.", "CalBandpass");
938 :
939 0 : const ByteOrder* byteOrder=0;
940 0 : if ( string("ASDMBinaryTable").compare((const char*) root_element->name) == 0) {
941 : // Then it's an "old fashioned" MIME file for tables.
942 : // Just try to deserialize it with Big_Endian for the bytes ordering.
943 0 : byteOrder = asdm::ByteOrder::Big_Endian;
944 :
945 : //
946 : // Let's consider a default order for the sequence of attributes.
947 : //
948 :
949 :
950 0 : attributesSeq.push_back("basebandName") ;
951 :
952 0 : attributesSeq.push_back("sideband") ;
953 :
954 0 : attributesSeq.push_back("atmPhaseCorrection") ;
955 :
956 0 : attributesSeq.push_back("typeCurve") ;
957 :
958 0 : attributesSeq.push_back("receiverBand") ;
959 :
960 0 : attributesSeq.push_back("calDataId") ;
961 :
962 0 : attributesSeq.push_back("calReductionId") ;
963 :
964 0 : attributesSeq.push_back("startValidTime") ;
965 :
966 0 : attributesSeq.push_back("endValidTime") ;
967 :
968 0 : attributesSeq.push_back("numAntenna") ;
969 :
970 0 : attributesSeq.push_back("numPoly") ;
971 :
972 0 : attributesSeq.push_back("numReceptor") ;
973 :
974 0 : attributesSeq.push_back("antennaNames") ;
975 :
976 0 : attributesSeq.push_back("refAntennaName") ;
977 :
978 0 : attributesSeq.push_back("freqLimits") ;
979 :
980 0 : attributesSeq.push_back("polarizationTypes") ;
981 :
982 0 : attributesSeq.push_back("curve") ;
983 :
984 0 : attributesSeq.push_back("reducedChiSquared") ;
985 :
986 :
987 0 : attributesSeq.push_back("numBaseline") ;
988 :
989 0 : attributesSeq.push_back("numFreq") ;
990 :
991 0 : attributesSeq.push_back("rms") ;
992 :
993 0 : attributesSeq.push_back("frequencyRange") ;
994 :
995 0 : attributesSeq.push_back("numSpectralWindow") ;
996 :
997 0 : attributesSeq.push_back("chanFreqStart") ;
998 :
999 0 : attributesSeq.push_back("chanFreqStep") ;
1000 :
1001 0 : attributesSeq.push_back("numSpectralWindowChan") ;
1002 :
1003 0 : attributesSeq.push_back("spectrum") ;
1004 :
1005 :
1006 :
1007 :
1008 : // And decide that it has version == "2"
1009 0 : version = "2";
1010 : }
1011 0 : else if (string("CalBandpassTable").compare((const char*) root_element->name) == 0) {
1012 : // It's a new (and correct) MIME file for tables.
1013 : //
1014 : // 1st ) Look for a BulkStoreRef element with an attribute byteOrder.
1015 : //
1016 0 : xmlNode* bulkStoreRef = 0;
1017 0 : xmlNode* child = root_element->children;
1018 :
1019 0 : if (xmlHasProp(root_element, (const xmlChar*) "schemaVersion")) {
1020 0 : xmlChar * value = xmlGetProp(root_element, (const xmlChar *) "schemaVersion");
1021 0 : version = string ((const char *) value);
1022 0 : xmlFree(value);
1023 : }
1024 :
1025 : // Skip the two first children (Entity and ContainerEntity).
1026 0 : bulkStoreRef = (child == 0) ? 0 : ( (child->next) == 0 ? 0 : child->next->next );
1027 :
1028 0 : if ( bulkStoreRef == 0 || (bulkStoreRef->type != XML_ELEMENT_NODE) || (string("BulkStoreRef").compare((const char*) bulkStoreRef->name) != 0))
1029 0 : throw ConversionException ("Could not find the element '/CalBandpassTable/BulkStoreRef'. Invalid XML header '"+ xmlHeader + "'.", "CalBandpass");
1030 :
1031 : // We found BulkStoreRef, now look for its attribute byteOrder.
1032 0 : _xmlAttr* byteOrderAttr = 0;
1033 0 : for (struct _xmlAttr* attr = bulkStoreRef->properties; attr; attr = attr->next)
1034 0 : if (string("byteOrder").compare((const char*) attr->name) == 0) {
1035 0 : byteOrderAttr = attr;
1036 0 : break;
1037 : }
1038 :
1039 0 : if (byteOrderAttr == 0)
1040 0 : throw ConversionException("Could not find the element '/CalBandpassTable/BulkStoreRef/@byteOrder'. Invalid XML header '" + xmlHeader +"'.", "CalBandpass");
1041 :
1042 0 : string byteOrderValue = string((const char*) byteOrderAttr->children->content);
1043 0 : if (!(byteOrder = asdm::ByteOrder::fromString(byteOrderValue)))
1044 0 : throw ConversionException("No valid value retrieved for the element '/CalBandpassTable/BulkStoreRef/@byteOrder'. Invalid XML header '" + xmlHeader + "'.", "CalBandpass");
1045 :
1046 : //
1047 : // 2nd) Look for the Attributes element and grab the names of the elements it contains.
1048 : //
1049 0 : xmlNode* attributes = bulkStoreRef->next;
1050 0 : if ( attributes == 0 || (attributes->type != XML_ELEMENT_NODE) || (string("Attributes").compare((const char*) attributes->name) != 0))
1051 0 : throw ConversionException ("Could not find the element '/CalBandpassTable/Attributes'. Invalid XML header '"+ xmlHeader + "'.", "CalBandpass");
1052 :
1053 0 : xmlNode* childOfAttributes = attributes->children;
1054 :
1055 0 : while ( childOfAttributes != 0 && (childOfAttributes->type == XML_ELEMENT_NODE) ) {
1056 0 : attributesSeq.push_back(string((const char*) childOfAttributes->name));
1057 0 : childOfAttributes = childOfAttributes->next;
1058 : }
1059 0 : }
1060 : // Create an EndianISStream from the substring containing the binary part.
1061 0 : EndianISStream eiss(mimeMsg.substr(loc1+binPartMIMEHeader.size()), byteOrder);
1062 :
1063 0 : entity = Entity::fromBin((EndianIStream&) eiss);
1064 :
1065 : // We do nothing with that but we have to read it.
1066 0 : Entity containerEntity = Entity::fromBin((EndianIStream&) eiss);
1067 :
1068 : // Let's read numRows but ignore it and rely on the value specified in the ASDM.xml file.
1069 0 : int numRows = ((EndianIStream&) eiss).readInt();
1070 0 : if ((numRows != -1) // Then these are *not* data produced at the EVLA.
1071 0 : && ((unsigned int) numRows != this->declaredSize )) { // Then the declared size (in ASDM.xml) is not equal to the one
1072 : // written into the binary representation of the table.
1073 0 : cout << "The a number of rows ('"
1074 : << numRows
1075 0 : << "') declared in the binary representation of the table is different from the one declared in ASDM.xml ('"
1076 0 : << this->declaredSize
1077 0 : << "'). I'll proceed with the value declared in ASDM.xml"
1078 0 : << endl;
1079 : }
1080 :
1081 0 : if (getContainer().checkRowUniqueness()) {
1082 : try {
1083 0 : for (uint32_t i = 0; i < this->declaredSize; i++) {
1084 0 : CalBandpassRow* aRow = CalBandpassRow::fromBin((EndianIStream&) eiss, *this, attributesSeq);
1085 0 : checkAndAdd(aRow);
1086 : }
1087 : }
1088 0 : catch (const DuplicateKey &e) {
1089 0 : throw ConversionException("Error while writing binary data , the message was "
1090 0 : + e.getMessage(), "CalBandpass");
1091 0 : }
1092 0 : catch (const TagFormatException &e) {
1093 0 : throw ConversionException("Error while reading binary data , the message was "
1094 0 : + e.getMessage(), "CalBandpass");
1095 0 : }
1096 : }
1097 : else {
1098 0 : for (uint32_t i = 0; i < this->declaredSize; i++) {
1099 0 : CalBandpassRow* aRow = CalBandpassRow::fromBin((EndianIStream&) eiss, *this, attributesSeq);
1100 0 : append(aRow);
1101 : }
1102 : }
1103 : //Does not change the convention defined in the model.
1104 : //archiveAsBin = true;
1105 : //fileAsBin = true;
1106 0 : if ( doc != NULL ) xmlFreeDoc(doc);
1107 :
1108 0 : }
1109 :
1110 0 : void CalBandpassTable::setUnknownAttributeBinaryReader(const string& attributeName, BinaryAttributeReaderFunctor* barFctr) {
1111 : //
1112 : // Is this attribute really unknown ?
1113 : //
1114 0 : for (vector<string>::const_iterator iter = attributesNamesOfCalBandpass_v.begin(); iter != attributesNamesOfCalBandpass_v.end(); iter++) {
1115 0 : if ((*iter).compare(attributeName) == 0)
1116 0 : throw ConversionException("the attribute '"+attributeName+"' is known you can't override the way it's read in the MIME binary file containing the table.", "CalBandpass");
1117 : }
1118 :
1119 : // Ok then register the functor to activate when an unknown attribute is met during the reading of a binary table?
1120 0 : unknownAttributes2Functors[attributeName] = barFctr;
1121 0 : }
1122 :
1123 0 : BinaryAttributeReaderFunctor* CalBandpassTable::getUnknownAttributeBinaryReader(const string& attributeName) const {
1124 0 : map<string, BinaryAttributeReaderFunctor*>::const_iterator iter = unknownAttributes2Functors.find(attributeName);
1125 0 : return (iter == unknownAttributes2Functors.end()) ? 0 : iter->second;
1126 : }
1127 :
1128 :
1129 0 : void CalBandpassTable::toFile(string directory) {
1130 0 : if (!directoryExists(directory.c_str()) &&
1131 0 : !createPath(directory.c_str())) {
1132 0 : throw ConversionException("Could not create directory " , directory);
1133 : }
1134 :
1135 0 : string fileName = directory + "/CalBandpass.xml";
1136 0 : ofstream tableout(fileName.c_str(),ios::out|ios::trunc);
1137 0 : if (tableout.rdstate() == ostream::failbit)
1138 0 : throw ConversionException("Could not open file " + fileName + " to write ", "CalBandpass");
1139 0 : if (fileAsBin)
1140 0 : tableout << MIMEXMLPart();
1141 : else
1142 0 : tableout << toXML() << endl;
1143 0 : tableout.close();
1144 0 : if (tableout.rdstate() == ostream::failbit)
1145 0 : throw ConversionException("Could not close file " + fileName, "CalBandpass");
1146 :
1147 0 : if (fileAsBin) {
1148 : // write the bin serialized
1149 0 : string fileName = directory + "/CalBandpass.bin";
1150 0 : ofstream tableout(fileName.c_str(),ios::out|ios::trunc);
1151 0 : if (tableout.rdstate() == ostream::failbit)
1152 0 : throw ConversionException("Could not open file " + fileName + " to write ", "CalBandpass");
1153 0 : tableout << toMIME() << endl;
1154 0 : tableout.close();
1155 0 : if (tableout.rdstate() == ostream::failbit)
1156 0 : throw ConversionException("Could not close file " + fileName, "CalBandpass");
1157 0 : }
1158 0 : }
1159 :
1160 :
1161 0 : void CalBandpassTable::setFromFile(const string& directory) {
1162 : #ifndef WITHOUT_BOOST
1163 : if (boost::filesystem::exists(boost::filesystem::path(uniqSlashes(directory + "/CalBandpass.xml"))))
1164 : setFromXMLFile(directory);
1165 : else if (boost::filesystem::exists(boost::filesystem::path(uniqSlashes(directory + "/CalBandpass.bin"))))
1166 : setFromMIMEFile(directory);
1167 : #else
1168 : // alternative in Misc.h
1169 0 : if (file_exists(uniqSlashes(directory + "/CalBandpass.xml")))
1170 0 : setFromXMLFile(directory);
1171 0 : else if (file_exists(uniqSlashes(directory + "/CalBandpass.bin")))
1172 0 : setFromMIMEFile(directory);
1173 : #endif
1174 : else
1175 0 : throw ConversionException("No file found for the CalBandpass table", "CalBandpass");
1176 0 : }
1177 :
1178 :
1179 0 : void CalBandpassTable::setFromMIMEFile(const string& directory) {
1180 0 : string tablePath ;
1181 :
1182 0 : tablePath = directory + "/CalBandpass.bin";
1183 0 : ifstream tablefile(tablePath.c_str(), ios::in|ios::binary);
1184 0 : if (!tablefile.is_open()) {
1185 0 : throw ConversionException("Could not open file " + tablePath, "CalBandpass");
1186 : }
1187 : // Read in a stringstream.
1188 0 : stringstream ss; ss << tablefile.rdbuf();
1189 :
1190 0 : if (tablefile.rdstate() == istream::failbit || tablefile.rdstate() == istream::badbit) {
1191 0 : throw ConversionException("Error reading file " + tablePath,"CalBandpass");
1192 : }
1193 :
1194 : // And close.
1195 0 : tablefile.close();
1196 0 : if (tablefile.rdstate() == istream::failbit)
1197 0 : throw ConversionException("Could not close file " + tablePath,"CalBandpass");
1198 :
1199 0 : setFromMIME(ss.str());
1200 0 : }
1201 : /*
1202 : void CalBandpassTable::openMIMEFile (const string& directory) {
1203 :
1204 : // Open the file.
1205 : string tablePath ;
1206 : tablePath = directory + "/CalBandpass.bin";
1207 : ifstream tablefile(tablePath.c_str(), ios::in|ios::binary);
1208 : if (!tablefile.is_open())
1209 : throw ConversionException("Could not open file " + tablePath, "CalBandpass");
1210 :
1211 : // Locate the xmlPartMIMEHeader.
1212 : string xmlPartMIMEHeader = "CONTENT-ID: <HEADER.XML>\n\n";
1213 : CharComparator comparator;
1214 : istreambuf_iterator<char> BEGIN(tablefile.rdbuf());
1215 : istreambuf_iterator<char> END;
1216 : istreambuf_iterator<char> it = search(BEGIN, END, xmlPartMIMEHeader.begin(), xmlPartMIMEHeader.end(), comparator);
1217 : if (it == END)
1218 : throw ConversionException("failed to detect the beginning of the XML header", "CalBandpass");
1219 :
1220 : // Locate the binaryPartMIMEHeader while accumulating the characters of the xml header.
1221 : string binPartMIMEHeader = "--MIME_BOUNDARY\nCONTENT-TYPE: BINARY/OCTET-STREAM\nCONTENT-ID: <CONTENT.BIN>\n\n";
1222 : string xmlHeader;
1223 : CharCompAccumulator compaccumulator(&xmlHeader, 100000);
1224 : ++it;
1225 : it = search(it, END, binPartMIMEHeader.begin(), binPartMIMEHeader.end(), compaccumulator);
1226 : if (it == END)
1227 : throw ConversionException("failed to detect the beginning of the binary part", "CalBandpass");
1228 :
1229 : cout << xmlHeader << endl;
1230 : //
1231 : // We have the xmlHeader , let's parse it.
1232 : //
1233 : xmlDoc *doc;
1234 : doc = xmlReadMemory(xmlHeader.data(), xmlHeader.size(), "BinaryTableHeader.xml", NULL, XML_PARSE_NOBLANKS);
1235 : if ( doc == NULL )
1236 : throw ConversionException("Failed to parse the xmlHeader into a DOM structure.", "CalBandpass");
1237 :
1238 : // This vector will be filled by the names of all the attributes of the table
1239 : // in the order in which they are expected to be found in the binary representation.
1240 : //
1241 : vector<string> attributesSeq(attributesNamesInBinOfCalBandpass_v);
1242 :
1243 : xmlNode* root_element = xmlDocGetRootElement(doc);
1244 : if ( root_element == NULL || root_element->type != XML_ELEMENT_NODE )
1245 : throw ConversionException("Failed to parse the xmlHeader into a DOM structure.", "CalBandpass");
1246 :
1247 : const ByteOrder* byteOrder=0;
1248 : if ( string("ASDMBinaryTable").compare((const char*) root_element->name) == 0) {
1249 : // Then it's an "old fashioned" MIME file for tables.
1250 : // Just try to deserialize it with Big_Endian for the bytes ordering.
1251 : byteOrder = asdm::ByteOrder::Big_Endian;
1252 :
1253 : // And decide that it has version == "2"
1254 : version = "2";
1255 : }
1256 : else if (string("CalBandpassTable").compare((const char*) root_element->name) == 0) {
1257 : // It's a new (and correct) MIME file for tables.
1258 : //
1259 : // 1st ) Look for a BulkStoreRef element with an attribute byteOrder.
1260 : //
1261 : xmlNode* bulkStoreRef = 0;
1262 : xmlNode* child = root_element->children;
1263 :
1264 : if (xmlHasProp(root_element, (const xmlChar*) "schemaVersion")) {
1265 : xmlChar * value = xmlGetProp(root_element, (const xmlChar *) "schemaVersion");
1266 : version = string ((const char *) value);
1267 : xmlFree(value);
1268 : }
1269 :
1270 : // Skip the two first children (Entity and ContainerEntity).
1271 : bulkStoreRef = (child == 0) ? 0 : ( (child->next) == 0 ? 0 : child->next->next );
1272 :
1273 : if ( bulkStoreRef == 0 || (bulkStoreRef->type != XML_ELEMENT_NODE) || (string("BulkStoreRef").compare((const char*) bulkStoreRef->name) != 0))
1274 : throw ConversionException ("Could not find the element '/CalBandpassTable/BulkStoreRef'. Invalid XML header '"+ xmlHeader + "'.", "CalBandpass");
1275 :
1276 : // We found BulkStoreRef, now look for its attribute byteOrder.
1277 : _xmlAttr* byteOrderAttr = 0;
1278 : for (struct _xmlAttr* attr = bulkStoreRef->properties; attr; attr = attr->next)
1279 : if (string("byteOrder").compare((const char*) attr->name) == 0) {
1280 : byteOrderAttr = attr;
1281 : break;
1282 : }
1283 :
1284 : if (byteOrderAttr == 0)
1285 : throw ConversionException("Could not find the element '/CalBandpassTable/BulkStoreRef/@byteOrder'. Invalid XML header '" + xmlHeader +"'.", "CalBandpass");
1286 :
1287 : string byteOrderValue = string((const char*) byteOrderAttr->children->content);
1288 : if (!(byteOrder = asdm::ByteOrder::fromString(byteOrderValue)))
1289 : throw ConversionException("No valid value retrieved for the element '/CalBandpassTable/BulkStoreRef/@byteOrder'. Invalid XML header '" + xmlHeader + "'.", "CalBandpass");
1290 :
1291 : //
1292 : // 2nd) Look for the Attributes element and grab the names of the elements it contains.
1293 : //
1294 : xmlNode* attributes = bulkStoreRef->next;
1295 : if ( attributes == 0 || (attributes->type != XML_ELEMENT_NODE) || (string("Attributes").compare((const char*) attributes->name) != 0))
1296 : throw ConversionException ("Could not find the element '/CalBandpassTable/Attributes'. Invalid XML header '"+ xmlHeader + "'.", "CalBandpass");
1297 :
1298 : xmlNode* childOfAttributes = attributes->children;
1299 :
1300 : while ( childOfAttributes != 0 && (childOfAttributes->type == XML_ELEMENT_NODE) ) {
1301 : attributesSeq.push_back(string((const char*) childOfAttributes->name));
1302 : childOfAttributes = childOfAttributes->next;
1303 : }
1304 : }
1305 : // Create an EndianISStream from the substring containing the binary part.
1306 : EndianIFStream eifs(&tablefile, byteOrder);
1307 :
1308 : entity = Entity::fromBin((EndianIStream &) eifs);
1309 :
1310 : // We do nothing with that but we have to read it.
1311 : Entity containerEntity = Entity::fromBin((EndianIStream &) eifs);
1312 :
1313 : // Let's read numRows but ignore it and rely on the value specified in the ASDM.xml file.
1314 : int numRows = eifs.readInt();
1315 : if ((numRows != -1) // Then these are *not* data produced at the EVLA.
1316 : && ((unsigned int) numRows != this->declaredSize )) { // Then the declared size (in ASDM.xml) is not equal to the one
1317 : // written into the binary representation of the table.
1318 : cout << "The a number of rows ('"
1319 : << numRows
1320 : << "') declared in the binary representation of the table is different from the one declared in ASDM.xml ('"
1321 : << this->declaredSize
1322 : << "'). I'll proceed with the value declared in ASDM.xml"
1323 : << endl;
1324 : }
1325 : // clean up xmlDoc pointer
1326 : if ( doc != NULL ) xmlFreeDoc(doc);
1327 : }
1328 : */
1329 :
1330 :
1331 0 : void CalBandpassTable::setFromXMLFile(const string& directory) {
1332 0 : string tablePath ;
1333 :
1334 0 : tablePath = directory + "/CalBandpass.xml";
1335 :
1336 : /*
1337 : ifstream tablefile(tablePath.c_str(), ios::in|ios::binary);
1338 : if (!tablefile.is_open()) {
1339 : throw ConversionException("Could not open file " + tablePath, "CalBandpass");
1340 : }
1341 : // Read in a stringstream.
1342 : stringstream ss;
1343 : ss << tablefile.rdbuf();
1344 :
1345 : if (tablefile.rdstate() == istream::failbit || tablefile.rdstate() == istream::badbit) {
1346 : throw ConversionException("Error reading file '" + tablePath + "'", "CalBandpass");
1347 : }
1348 :
1349 : // And close
1350 : tablefile.close();
1351 : if (tablefile.rdstate() == istream::failbit)
1352 : throw ConversionException("Could not close file '" + tablePath + "'", "CalBandpass");
1353 :
1354 : // Let's make a string out of the stringstream content and empty the stringstream.
1355 : string xmlDocument = ss.str(); ss.str("");
1356 :
1357 : // Let's make a very primitive check to decide
1358 : // whether the XML content represents the table
1359 : // or refers to it via a <BulkStoreRef element.
1360 : */
1361 :
1362 0 : string xmlDocument;
1363 : try {
1364 0 : xmlDocument = getContainer().getXSLTransformer()(tablePath);
1365 0 : if (getenv("ASDM_DEBUG")) cout << "About to read " << tablePath << endl;
1366 : }
1367 0 : catch (const XSLTransformerException &e) {
1368 0 : throw ConversionException("Caugth an exception whose message is '" + e.getMessage() + "'.", "CalBandpass");
1369 0 : }
1370 :
1371 0 : if (xmlDocument.find("<BulkStoreRef") != string::npos)
1372 0 : setFromMIMEFile(directory);
1373 : else
1374 0 : fromXML(xmlDocument);
1375 0 : }
1376 :
1377 :
1378 :
1379 :
1380 :
1381 :
1382 :
1383 :
1384 :
1385 :
1386 : } // End namespace asdm
1387 :
|