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