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