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