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