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