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