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