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