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