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