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