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