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