00001 #ifndef TableSAXReader_h
00002 #define TableSAXReader_h
00003 #include <stdlib.h>
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <iostream>
00007 #include <set>
00008 #include <libxml/tree.h>
00009 #include <libxml/parser.h>
00010 #include <libxml/parserInternals.h>
00011
00012 #include <memory>
00013
00018 template<typename T>
00019 struct negateFunctor {
00020 public:
00021 T operator() (const T& v) {
00022 return (v < 0.0) ? v : -v;
00023 }
00024 };
00025
00033 template<typename T>
00034 std::string displaySet(const std::set<T> &aSet) {
00035 std::ostringstream oss;
00036 oss << "{";
00037 typename std::set<T>::const_iterator iter = aSet.begin();
00038 if (iter != aSet.end())
00039 oss << *iter++;
00040
00041 while (iter != aSet.end())
00042 oss << "," << *iter++;
00043 oss<< "}";
00044 return oss.str();
00045 }
00046
00055 template<typename T>
00056 set<T> SetAndSet(const set<T>& s1, const set<T>& s2) {
00057 set<T> result;
00058 typename set<T>::iterator iter1_s, iter2_s;
00059 for (iter1_s = s1.begin(); iter1_s != s1.end(); iter1_s++) {
00060 if ((iter2_s = s2.find(*iter1_s)) != s2.end())
00061 result.insert(*iter1_s);
00062 }
00063 return result;
00064 }
00065
00066
00067 template<typename T>
00068 struct rowsInAScanbyTimeIntervalFunctor {
00069 private:
00070 const vector<ScanRow *>& scans;
00071 vector<T *> result;
00072
00085 bool timeIntervalIntersectsAScan (T* row, const std::vector<asdm::ScanRow *>& scans) {
00086 bool result = false;
00087
00088 int64_t currentScanStartTime, currentScanEndTime;
00089 int64_t rowStartTime, rowEndTime;
00090 for (std::vector<asdm::ScanRow *>::const_iterator iter = scans.begin(); iter != scans.end(); iter++) {
00091 currentScanStartTime = (*iter)->getStartTime().get();
00092 currentScanEndTime = (*iter)->getEndTime().get();
00093
00094 rowStartTime = row->getTimeInterval().getStart().get();
00095 rowEndTime = rowStartTime + row->getTimeInterval().getDuration().get();
00096 if (max(currentScanStartTime, rowStartTime) < min(currentScanEndTime, rowEndTime))
00097 return true;
00098 }
00099 return result;
00100 }
00101
00102 public:
00103 rowsInAScanbyTimeIntervalFunctor(const std::vector<asdm::ScanRow *>& scans): scans(scans) {};
00104 const std::vector<T *> & operator() (const std::vector<T *>& rows, bool ignoreTime=false) {
00105 if (ignoreTime) return rows;
00106
00107 result.clear();
00108 for (typename std::vector<T *>::const_iterator iter = rows.begin(); iter != rows.end(); iter++) {
00109 if (timeIntervalIntersectsAScan (*iter, scans))
00110 result.push_back(*iter);
00111 }
00112 return result;
00113 }
00114 };
00115
00116 template<typename T>
00117 struct rowsInAScanbyTimeFunctor {
00118 private:
00119 const vector<ScanRow *>& scans;
00120 vector<T *> result;
00121
00127 bool timeIsInAScan(T* row, const vector<ScanRow *>& scans) {
00128 bool result = false;
00129
00130 int64_t currentScanStartTime, currentScanEndTime;
00131 int64_t rowTime;
00132 rowTime = row->getTime().get();
00133 for (vector<ScanRow *>::const_iterator iter = scans.begin(); iter != scans.end(); iter++) {
00134 currentScanStartTime = (*iter)->getStartTime().get();
00135 currentScanEndTime = (*iter)->getEndTime().get();
00136 if ((currentScanStartTime <= rowTime) && (rowTime < currentScanEndTime))
00137 return true;
00138 }
00139 return result;
00140 }
00141
00142 public:
00143 rowsInAScanbyTimeFunctor(const vector<ScanRow *>& scans): scans(scans) {};
00144 const vector<T *> & operator() (const vector<T *>& rows, bool ignoreTime=false) {
00145 if (ignoreTime) return rows;
00146
00147 result.clear();
00148 for (typename vector<T *>::const_iterator iter = rows.begin(); iter != rows.end(); iter++) {
00149 if (timeIsInAScan (*iter, scans))
00150 result.push_back(*iter);
00151 }
00152
00153 return result;
00154 }
00155 };
00156
00161 template<typename T>
00162 struct size_lt {
00163 public:
00164 size_lt(unsigned int y) : y(y) {}
00165 bool operator()(vector<T>& x) {return x.size() < y;}
00166
00167 private:
00168 unsigned int y;
00169 };
00170
00175 template<typename Enum, typename CEnum>
00176 string stringValue(Enum literal) {
00177 return CEnum::name(literal);
00178 }
00179
00180
00185 template<typename PhysicalQuantity, typename BasicType>
00186 BasicType basicTypeValue (PhysicalQuantity value) {
00187 return (BasicType) value.get();
00188 }
00189
00190
00191
00192
00193 #if defined(__APPLE__)
00194 #include <mach-o/dyld.h>
00195 std::string getexepath() {
00196 char path[1024];
00197 uint32_t size = sizeof(path);
00198 return (_NSGetExecutablePath(path, &size) == 0) ? std::string(path) : "";
00199 }
00200 #else
00201 #include <limits.h>
00202 #include <unistd.h>
00203 std::string getexepath() {
00204 char result[ PATH_MAX ];
00205 ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
00206 return std::string( result, (count > 0) ? count : 0);
00207 }
00208 #endif
00209
00210 #include <casa/Logging/StreamLogSink.h>
00211 #include <casa/Logging/LogSink.h>
00212
00213
00214 #include "ConversionException.h"
00215 #include "CAtmPhaseCorrection.h"
00216 #include "ASDM.h"
00217 #include "ASDM2MSFiller.h"
00218
00219 #define CONTEXT_P ((ParserContext<T, R, RFilter> *)myContext_p)
00220 #define V2CTX_P(v_p) ((ParserContext<T, R, RFilter> *) v_p)
00221
00222 template<class T, class R, class RFilter>
00223 struct ParserContext {
00224 public:
00225 enum StatesEnum {START, IN_TABLE, IN_ENTITY, AFTER_ENTITY, IN_CONTAINER_ENTITY, AFTER_CONTAINER_ENTITY, IN_ROW, AFTER_ROW, IN_ATTRIBUTE, END};
00226 asdm::ASDM* asdm_p;
00227 unsigned int maxNumberOfRowsInMem;
00228 std::shared_ptr<R> row_sp;
00229 std::vector<std::shared_ptr<R> > rows;
00230 RFilter* rFilter_p;
00231 bool ignoreTime;
00232 void (*tableFiller_f_p) (const vector<R*>&, map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>&);
00233 std::map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>* msFillers_m_p;
00234 const xmlChar* topLevelElement_p;
00235 const xmlChar* entityElement_p;
00236 const xmlChar* containerEntityElement_p;
00237 const xmlChar* rowElement_p;
00238 int depth;
00239 string currentElement;
00240 string currentValue;
00241 StatesEnum state;
00242 bool verbose;
00243 bool debug;
00244 };
00245
00246 template <class T, class R, class RFilter>
00247 class TableSAXReader {
00248
00249 typedef void (*TableFiller)(const vector<R*>&, map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>&);
00250
00251 public:
00255 TableSAXReader(bool verbose, RFilter& rFilter, TableFiller tableFiller_f_p, std::map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>& msFillers_m) {
00256
00257
00258 static_cast<void>(LogSink::globalSink());
00259
00260
00261 myContext.asdm_p = &asdm;
00262 myContext.maxNumberOfRowsInMem = 100000;
00263 myContext.rFilter_p = &rFilter;
00264 myContext.tableFiller_f_p = tableFiller_f_p;
00265 myContext.msFillers_m_p = &msFillers_m;
00266 myContext.state = ParserContext<T, R, RFilter>::START;
00267 topLevelElement_s = T::name()+"Table";
00268 myContext.topLevelElement_p = (const xmlChar *) topLevelElement_s.c_str();
00269 myContext.entityElement_p = (const xmlChar *) "Entity";
00270 myContext.containerEntityElement_p = (const xmlChar *)"ContainerEntity";
00271 myContext.rowElement_p = (const xmlChar *) "row";
00272 myContext.depth = 0;
00273 myContext.verbose = verbose;
00274 myContext.debug = getenv("ASDM_DEBUG") != NULL;
00275 }
00276
00280 ~TableSAXReader() {;}
00281
00285 void operator() (const string& asdmDirectory, bool ignoreTime) {
00286 myContext.ignoreTime = ignoreTime;
00287 string tablePath = asdmDirectory + "/"+ T::name() + ".xml";
00288 xmlSAXUserParseFile(&myHandler, &myContext, tablePath.c_str());
00289 }
00290
00295 static void start_element_callback(void *v_p, const xmlChar *name, const xmlChar **) {
00296 const xmlChar* expectedElement;
00297 typename ParserContext<T, R, RFilter>::StatesEnum nextState;
00298
00299 if (V2CTX_P(v_p)->debug) TableSAXReader<T, R, RFilter>::enterElementInfo(V2CTX_P(v_p), name);
00300 V2CTX_P(v_p)->depth++;
00301
00302 switch (V2CTX_P(v_p)->state) {
00303
00304 case ParserContext<T, R, RFilter>::START :
00305 expectedElement = V2CTX_P(v_p)->topLevelElement_p;
00306 nextState = ParserContext<T, R, RFilter>::IN_TABLE;
00307 break;
00308
00309
00310 case ParserContext<T, R, RFilter>::IN_TABLE :
00311 expectedElement = V2CTX_P(v_p)->entityElement_p;
00312 nextState = ParserContext<T, R, RFilter>::IN_ENTITY;
00313 break;
00314
00315
00316 case ParserContext<T, R, RFilter>::AFTER_ENTITY :
00317 expectedElement = V2CTX_P(v_p)->containerEntityElement_p;
00318 nextState = ParserContext<T, R, RFilter>::IN_CONTAINER_ENTITY;
00319 break;
00320
00321
00322 case ParserContext<T, R, RFilter>::AFTER_ROW :
00323 case ParserContext<T, R, RFilter>::AFTER_CONTAINER_ENTITY :
00324 {
00325 T& tableRef = (T&) V2CTX_P(v_p)->asdm_p->getTable(T::name());
00326 V2CTX_P(v_p)->row_sp = std::shared_ptr<R>(tableRef.newRow());
00327 expectedElement = V2CTX_P(v_p)->rowElement_p;
00328 nextState = ParserContext<T, R, RFilter>::IN_ROW;
00329 }
00330 break;
00331
00332
00333 case ParserContext<T, R, RFilter>::IN_ROW :
00334 {
00335 expectedElement = NULL;
00336 V2CTX_P(v_p)->currentElement = (char *) name;
00337 nextState = ParserContext<T, R, RFilter>::IN_ATTRIBUTE;
00338 }
00339 break;
00340
00341
00342 case ParserContext<T, R, RFilter>::IN_ATTRIBUTE:
00343 break;
00344
00345
00346 default :
00347 string message = "Unexpected '" + string((char *) name) + "'.";
00348 error(message);
00349 };
00350
00351 checkOpeningElement(name, expectedElement);
00352 V2CTX_P(v_p)->state = nextState;
00353 }
00354
00359 static void end_element_callback(void *v_p, const xmlChar* name) {
00360 typename ParserContext<T, R, RFilter>::StatesEnum nextState;
00361 typename ParserContext<T, R, RFilter>::StatesEnum currentState = V2CTX_P(v_p)->state;
00362
00363 V2CTX_P(v_p)->depth--;
00364 if (V2CTX_P(v_p)->debug) TableSAXReader<T, R, RFilter>::exitElementInfo(v_p, name);
00365
00366 switch (currentState) {
00367
00368 case ParserContext<T, R, RFilter>::AFTER_ROW :
00369 checkClosingElement(name, V2CTX_P(v_p)->topLevelElement_p);
00370 nextState = ParserContext<T, R, RFilter>::END;
00371
00372
00373 if (V2CTX_P(v_p)->rows.size() > 0) {
00374 std::vector<R*> tmp(V2CTX_P(v_p)->rows.size());
00375 for (unsigned int iR = 0; iR < tmp.size(); iR++) tmp[iR] = V2CTX_P(v_p)->rows[iR].get();
00376 const std::vector<R*>& filteredRows = (*(V2CTX_P(v_p)->rFilter_p))(tmp, V2CTX_P(v_p)->ignoreTime);
00377 if (filteredRows.size() > 0) {
00378 (*(V2CTX_P(v_p)->tableFiller_f_p))(filteredRows , *(V2CTX_P(v_p)->msFillers_m_p));
00379
00380
00381
00382 if (V2CTX_P(v_p)->verbose){
00383 std::ostringstream oss;
00384 oss.str("");
00385 oss << "Appended " << filteredRows.size() << " rows to the MS SYSPOWER table." << endl;
00386 #if (BOOST_FILESYSTEM_VERSION == 3)
00387 LogSink::postGlobally(LogMessage(oss.str(), LogOrigin((boost::filesystem::path(getexepath())).filename().string(), WHERE),
00388 #else
00389 LogSink::postGlobally(LogMessage(oss.str(), LogOrigin((boost::filesystem::path(getexepath())).filename(), WHERE),
00390 #endif
00391 LogMessage::NORMAL
00392 )
00393 );
00394 }
00395 }
00396
00397
00398
00399 V2CTX_P(v_p)->rows.clear();
00400 }
00401 break;
00402
00403
00404 case ParserContext<T, R, RFilter>::IN_ENTITY :
00405 checkClosingElement(name, V2CTX_P(v_p)->entityElement_p);
00406 nextState = ParserContext<T, R, RFilter>::AFTER_ENTITY;
00407 break;
00408
00409
00410 case ParserContext<T, R, RFilter>::IN_CONTAINER_ENTITY:
00411 checkClosingElement(name, V2CTX_P(v_p)->containerEntityElement_p);
00412 nextState = ParserContext<T, R, RFilter>::AFTER_CONTAINER_ENTITY;
00413 break;
00414
00415
00416 case ParserContext<T, R, RFilter>::IN_ROW :
00417 checkClosingElement(name, V2CTX_P(v_p)->rowElement_p);
00418 nextState = ParserContext<T, R, RFilter>::AFTER_ROW;
00419
00420
00421 V2CTX_P(v_p)->rows.push_back(V2CTX_P(v_p)->row_sp);
00422
00423
00424
00425 if (V2CTX_P(v_p)->rows.size() == V2CTX_P(v_p)->maxNumberOfRowsInMem) {
00426 std::vector<R*> tmp(V2CTX_P(v_p)->rows.size());
00427 for (unsigned int iR = 0; iR < tmp.size(); iR++) tmp[iR] = V2CTX_P(v_p)->rows[iR].get();
00428 const std::vector<R*>& filteredRows = (*(V2CTX_P(v_p)->rFilter_p))(tmp, V2CTX_P(v_p)->ignoreTime);
00429 if (filteredRows.size() > 0) {
00430 (*(V2CTX_P(v_p)->tableFiller_f_p))(filteredRows , *(V2CTX_P(v_p)->msFillers_m_p));
00431
00432
00433
00434 if (V2CTX_P(v_p)->verbose){
00435 std::ostringstream oss;
00436 oss.str("");
00437 oss << "Appended " << filteredRows.size() << " rows to the MS SYSPOWER table." << endl;
00438 #if (BOOST_FILESYSTEM_VERSION == 3)
00439 LogSink::postGlobally(LogMessage(oss.str(), LogOrigin((boost::filesystem::path(getexepath())).filename().string(), WHERE),
00440 #else
00441 LogSink::postGlobally(LogMessage(oss.str(), LogOrigin((boost::filesystem::path(getexepath())).filename(), WHERE),
00442 #endif
00443 LogMessage::NORMAL
00444 )
00445 );
00446 }
00447 }
00448 V2CTX_P(v_p)->rows.clear();
00449 }
00450 break;
00451
00452
00453 case ParserContext<T, R, RFilter>::IN_ATTRIBUTE :
00454 checkClosingElement(name, (const xmlChar*) V2CTX_P(v_p)->currentElement.c_str());
00455 nextState = ParserContext<T, R, RFilter>::IN_ROW;
00456 V2CTX_P(v_p)->row_sp.get()->fromText(V2CTX_P(v_p)->currentElement, V2CTX_P(v_p)->currentValue);
00457 break;
00458
00459 default :
00460 string message = "Unexpected '" + string((char *) name) + "'.";
00461 error(message);
00462 }
00463
00464 V2CTX_P(v_p)->state = nextState;
00465 }
00466
00472 static void characters_callback (void * v_p,
00473 const xmlChar * ch,
00474 int len) {
00475 V2CTX_P(v_p)->currentValue = string((char * ) ch, len);
00476 }
00477
00478
00479 private:
00480 bool verbose;
00481 ParserContext<T, R, RFilter> myContext ;
00482 string topLevelElement_s;
00483 asdm::ASDM asdm;
00484 static xmlSAXHandler myHandler;
00485 static xmlSAXHandler initSAXHandler() {
00486 xmlSAXHandler handler = { 0 };
00487 handler.startElement = start_element_callback;
00488 handler.endElement = end_element_callback;
00489 handler.characters = characters_callback;
00490 return handler;
00491 }
00492
00493 static void error(const string & message) {
00494 throw asdm::ConversionException(message, T::name());
00495 }
00496
00497 static void unexpectedOpeningElement(const xmlChar *name, const xmlChar *expectedName) {
00498 string message = "Unexpected opening tag '" + string((const char *) name) + "', I was expecting '" + string((const char*) expectedName) +"'.";
00499 error(message);
00500 }
00501
00502 static void unexpectedClosingElement(const xmlChar *name) {
00503 string message = "Unexpected closing tag '" + string((const char *) name) + "'.";
00504 error(message);
00505 }
00506
00507 static void checkOpeningElement(const xmlChar* name, const xmlChar* expectedName) {
00508 if (expectedName && xmlStrcmp(name, expectedName)) unexpectedOpeningElement(name, expectedName);
00509 }
00510
00511 static void checkClosingElement(const xmlChar* name, const xmlChar* expectedName) {
00512 if (xmlStrcmp(name, expectedName)) unexpectedClosingElement(name);
00513 }
00514
00515 static void enterElementInfo(void *v_p, const xmlChar* name) {
00516 cout << "Enter '" << name << "' (depth = " << V2CTX_P(v_p)->depth << ")" << endl;
00517 }
00518
00519 static void exitElementInfo(void *v_p, const xmlChar* name) {
00520 cout << "Exit from '" << name << "' (depth = " << V2CTX_P(v_p)->depth << ")" << endl;
00521 }
00522
00523 };
00524
00525 template<class T, class R, class RFilter> xmlSAXHandler TableSAXReader<T, R, RFilter>::myHandler = TableSAXReader<T, R, RFilter>::initSAXHandler();
00526
00527
00528 #endif