casa
$Rev:20696$
|
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 <boost/shared_ptr.hpp> 00013 #include <boost/filesystem/path.hpp> 00014 00019 template<typename T> 00020 struct negateFunctor { 00021 public: 00022 T operator() (const T& v) { 00023 return (v < 0.0) ? v : -v; 00024 } 00025 }; 00026 00034 template<typename T> 00035 std::string displaySet(const std::set<T> &aSet) { 00036 std::ostringstream oss; 00037 oss << "{"; 00038 typename std::set<T>::const_iterator iter = aSet.begin(); 00039 if (iter != aSet.end()) 00040 oss << *iter++; 00041 00042 while (iter != aSet.end()) 00043 oss << "," << *iter++; 00044 oss<< "}"; 00045 return oss.str(); 00046 } 00047 00056 template<typename T> 00057 set<T> SetAndSet(const set<T>& s1, const set<T>& s2) { 00058 set<T> result; 00059 typename set<T>::iterator iter1_s, iter2_s; 00060 for (iter1_s = s1.begin(); iter1_s != s1.end(); iter1_s++) { 00061 if ((iter2_s = s2.find(*iter1_s)) != s2.end()) 00062 result.insert(*iter1_s); 00063 } 00064 return result; 00065 } 00066 00067 00068 template<typename T> 00069 struct rowsInAScanbyTimeIntervalFunctor { 00070 private: 00071 const vector<ScanRow *>& scans; 00072 vector<T *> result; 00073 00086 bool timeIntervalIntersectsAScan (T* row, const std::vector<asdm::ScanRow *>& scans) { 00087 bool result = false; 00088 00089 int64_t currentScanStartTime, currentScanEndTime; 00090 int64_t rowStartTime, rowEndTime; 00091 for (std::vector<asdm::ScanRow *>::const_iterator iter = scans.begin(); iter != scans.end(); iter++) { 00092 currentScanStartTime = (*iter)->getStartTime().get(); 00093 currentScanEndTime = (*iter)->getEndTime().get(); 00094 00095 rowStartTime = row->getTimeInterval().getStart().get(); 00096 rowEndTime = rowStartTime + row->getTimeInterval().getDuration().get(); 00097 if (max(currentScanStartTime, rowStartTime) < min(currentScanEndTime, rowEndTime)) 00098 return true; 00099 } 00100 return result; 00101 } 00102 00103 public: 00104 rowsInAScanbyTimeIntervalFunctor(const std::vector<asdm::ScanRow *>& scans): scans(scans) {}; 00105 const std::vector<T *> & operator() (const std::vector<T *>& rows, bool ignoreTime=false) { 00106 if (ignoreTime) return rows; 00107 00108 result.clear(); 00109 for (typename std::vector<T *>::const_iterator iter = rows.begin(); iter != rows.end(); iter++) { 00110 if (timeIntervalIntersectsAScan (*iter, scans)) 00111 result.push_back(*iter); 00112 } 00113 return result; 00114 } 00115 }; 00116 00117 template<typename T> 00118 struct rowsInAScanbyTimeFunctor { 00119 private: 00120 const vector<ScanRow *>& scans; 00121 vector<T *> result; 00122 00128 bool timeIsInAScan(T* row, const vector<ScanRow *>& scans) { 00129 bool result = false; 00130 00131 int64_t currentScanStartTime, currentScanEndTime; 00132 int64_t rowTime; 00133 rowTime = row->getTime().get(); 00134 for (vector<ScanRow *>::const_iterator iter = scans.begin(); iter != scans.end(); iter++) { 00135 currentScanStartTime = (*iter)->getStartTime().get(); 00136 currentScanEndTime = (*iter)->getEndTime().get(); 00137 if ((currentScanStartTime <= rowTime) && (rowTime < currentScanEndTime)) 00138 return true; 00139 } 00140 return result; 00141 } 00142 00143 public: 00144 rowsInAScanbyTimeFunctor(const vector<ScanRow *>& scans): scans(scans) {}; 00145 const vector<T *> & operator() (const vector<T *>& rows, bool ignoreTime=false) { 00146 if (ignoreTime) return rows; 00147 00148 result.clear(); 00149 for (typename vector<T *>::const_iterator iter = rows.begin(); iter != rows.end(); iter++) { 00150 if (timeIsInAScan (*iter, scans)) 00151 result.push_back(*iter); 00152 } 00153 00154 return result; 00155 } 00156 }; 00157 00162 template<typename T> 00163 struct size_lt { 00164 public: 00165 size_lt(unsigned int y) : y(y) {} 00166 bool operator()(vector<T>& x) {return x.size() < y;} 00167 00168 private: 00169 unsigned int y; 00170 }; 00171 00176 template<typename Enum, typename CEnum> 00177 string stringValue(Enum literal) { 00178 return CEnum::name(literal); 00179 } 00180 00181 00186 template<typename PhysicalQuantity, typename BasicType> 00187 BasicType basicTypeValue (PhysicalQuantity value) { 00188 return (BasicType) value.get(); 00189 } 00190 00191 00192 /* ------------------------------------- TableSaxParser - beginning ------------------------------------------*/ 00193 00194 #if defined(__APPLE__) 00195 #include <mach-o/dyld.h> 00196 std::string getexepath() { 00197 char path[1024]; 00198 uint32_t size = sizeof(path); 00199 return (_NSGetExecutablePath(path, &size) == 0) ? std::string(path) : ""; 00200 } 00201 #else 00202 #include <limits.h> 00203 #include <unistd.h> 00204 std::string getexepath() { 00205 char result[ PATH_MAX ]; 00206 ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX ); 00207 return std::string( result, (count > 0) ? count : 0); 00208 } 00209 #endif 00210 00211 #include <casa/Logging/StreamLogSink.h> 00212 #include <casa/Logging/LogSink.h> 00213 00214 00215 #include "ConversionException.h" 00216 #include "CAtmPhaseCorrection.h" 00217 #include "ASDM.h" 00218 #include "ASDM2MSFiller.h" 00219 00220 #define CONTEXT_P ((ParserContext<T, R, RFilter> *)myContext_p) 00221 #define V2CTX_P(v_p) ((ParserContext<T, R, RFilter> *) v_p) 00222 00223 template<class T, class R, class RFilter> 00224 struct ParserContext { 00225 public: 00226 enum StatesEnum {START, IN_TABLE, IN_ENTITY, AFTER_ENTITY, IN_CONTAINER_ENTITY, AFTER_CONTAINER_ENTITY, IN_ROW, AFTER_ROW, IN_ATTRIBUTE, END}; 00227 asdm::ASDM* asdm_p; 00228 unsigned int maxNumberOfRowsInMem; 00229 boost::shared_ptr<R> row_sp; 00230 std::vector<boost::shared_ptr<R> > rows; 00231 RFilter* rFilter_p; 00232 bool ignoreTime; 00233 void (*tableFiller_f_p) (const vector<R*>&, map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>&); 00234 std::map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>* msFillers_m_p; 00235 const xmlChar* topLevelElement_p; 00236 const xmlChar* entityElement_p; 00237 const xmlChar* containerEntityElement_p; 00238 const xmlChar* rowElement_p; 00239 int depth; 00240 string currentElement; 00241 string currentValue; 00242 StatesEnum state; 00243 bool verbose; 00244 bool debug; 00245 }; 00246 00247 template <class T, class R, class RFilter> 00248 class TableSAXReader { 00249 00250 typedef void (*TableFiller)(const vector<R*>&, map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>&); 00251 00252 public: 00256 TableSAXReader(bool verbose, RFilter& rFilter, TableFiller tableFiller_f_p, std::map<AtmPhaseCorrectionMod::AtmPhaseCorrection, ASDM2MSFiller*>& msFillers_m) { 00257 00258 LogSinkInterface& lsif = LogSink::globalSink(); 00259 00260 // The top level element name can be derived from the template parameter T. 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 **attrs) { 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 // We are right before the toplevel element of the XML document. 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 // We are right after the toplevel element of the XML document. 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 // We are right after the <Entity.../> element. 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 // We are right after the <ContainerEntity.../> element or a <row>..</row> element. 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 = boost::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 // We are inside a <row>...</row> but outside any element contained in that element. 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 // We are inside a element contained in a <row>...</row> element. 00342 case ParserContext<T, R, RFilter>::IN_ATTRIBUTE: 00343 break; 00344 00345 // Otherwise we have a problem. 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 // We are right after a <row>..</row> 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 // Possibly write some remainings rows by applying tableFiller on the vector. 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 // Log a minimum of information about what has just happened. 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 LogSink::postGlobally(LogMessage(oss.str(), LogOrigin((boost::filesystem::path(getexepath())).string(), WHERE), 00387 LogMessage::NORMAL 00388 ) 00389 ); 00390 } 00391 } 00392 // 00393 // Empty the vector before reading new rows. 00394 // 00395 V2CTX_P(v_p)->rows.clear(); 00396 } 00397 break; 00398 00399 // We were in an <Entity/> element. 00400 case ParserContext<T, R, RFilter>::IN_ENTITY : 00401 checkClosingElement(name, V2CTX_P(v_p)->entityElement_p); 00402 nextState = ParserContext<T, R, RFilter>::AFTER_ENTITY; 00403 break; 00404 00405 // We were in a <ContainerEntity/> element. 00406 case ParserContext<T, R, RFilter>::IN_CONTAINER_ENTITY: 00407 checkClosingElement(name, V2CTX_P(v_p)->containerEntityElement_p); 00408 nextState = ParserContext<T, R, RFilter>::AFTER_CONTAINER_ENTITY; 00409 break; 00410 00411 // We were in a <row>..</row> element. 00412 case ParserContext<T, R, RFilter>::IN_ROW : 00413 checkClosingElement(name, V2CTX_P(v_p)->rowElement_p); 00414 nextState = ParserContext<T, R, RFilter>::AFTER_ROW; 00415 00416 // Push the last parsed row into the vector. 00417 V2CTX_P(v_p)->rows.push_back(V2CTX_P(v_p)->row_sp); 00418 00419 // If the size of this vector is equal to the maximum number allowed to reside in memory 00420 // then proceed by applying tableFiller on on the vector and after that clear the vector. 00421 if (V2CTX_P(v_p)->rows.size() == V2CTX_P(v_p)->maxNumberOfRowsInMem) { 00422 std::vector<R*> tmp(V2CTX_P(v_p)->rows.size()); 00423 for (unsigned int iR = 0; iR < tmp.size(); iR++) tmp[iR] = V2CTX_P(v_p)->rows[iR].get(); 00424 const std::vector<R*>& filteredRows = (*(V2CTX_P(v_p)->rFilter_p))(tmp, V2CTX_P(v_p)->ignoreTime); 00425 if (filteredRows.size() > 0) { 00426 (*(V2CTX_P(v_p)->tableFiller_f_p))(filteredRows , *(V2CTX_P(v_p)->msFillers_m_p)); 00427 // 00428 // Log a minimum of information about what has just happened. 00429 // 00430 if (V2CTX_P(v_p)->verbose){ 00431 std::ostringstream oss; 00432 oss.str(""); 00433 oss << "Appended " << filteredRows.size() << " rows to the MS SYSPOWER table." << endl; 00434 LogSink::postGlobally(LogMessage(oss.str(), LogOrigin((boost::filesystem::path(getexepath())).string(), WHERE), 00435 LogMessage::NORMAL 00436 ) 00437 ); 00438 } 00439 } 00440 V2CTX_P(v_p)->rows.clear(); 00441 } 00442 break; 00443 00444 // We were in an element located in a <row>..</row>, which is normally an attribute. 00445 case ParserContext<T, R, RFilter>::IN_ATTRIBUTE : 00446 checkClosingElement(name, (const xmlChar*) V2CTX_P(v_p)->currentElement.c_str()); 00447 nextState = ParserContext<T, R, RFilter>::IN_ROW; 00448 V2CTX_P(v_p)->row_sp.get()->fromText(V2CTX_P(v_p)->currentElement, V2CTX_P(v_p)->currentValue); 00449 break; 00450 00451 default : 00452 string message = "Unexpected '" + string((char *) name) + "'."; 00453 error(message); 00454 } 00455 00456 V2CTX_P(v_p)->state = nextState; 00457 } 00458 00464 static void characters_callback (void * v_p, 00465 const xmlChar * ch, 00466 int len) { 00467 V2CTX_P(v_p)->currentValue = string((char * ) ch, len); 00468 } 00469 00470 00471 private: 00472 bool verbose; 00473 ParserContext<T, R, RFilter> myContext ; 00474 string topLevelElement_s; 00475 asdm::ASDM asdm; 00476 static xmlSAXHandler myHandler; 00477 static xmlSAXHandler initSAXHandler() { 00478 xmlSAXHandler handler = { 0 }; 00479 handler.startElement = start_element_callback; 00480 handler.endElement = end_element_callback; 00481 handler.characters = characters_callback; 00482 return handler; 00483 } 00484 00485 static void error(const string & message) { 00486 throw asdm::ConversionException(message, T::name()); 00487 } 00488 00489 static void unexpectedOpeningElement(const xmlChar *name, const xmlChar *expectedName) { 00490 string message = "Unexpected opening tag '" + string((const char *) name) + "', I was expecting '" + string((const char*) expectedName) +"'."; 00491 error(message); 00492 } 00493 00494 static void unexpectedClosingElement(const xmlChar *name) { 00495 string message = "Unexpected closing tag '" + string((const char *) name) + "'."; 00496 error(message); 00497 } 00498 00499 static void checkOpeningElement(const xmlChar* name, const xmlChar* expectedName) { 00500 if (expectedName && xmlStrcmp(name, expectedName)) unexpectedOpeningElement(name, expectedName); 00501 } 00502 00503 static void checkClosingElement(const xmlChar* name, const xmlChar* expectedName) { 00504 if (xmlStrcmp(name, expectedName)) unexpectedClosingElement(name); 00505 } 00506 00507 static void enterElementInfo(void *v_p, const xmlChar* name) { 00508 cout << "Enter '" << name << "' (depth = " << V2CTX_P(v_p)->depth << ")" << endl; 00509 } 00510 00511 static void exitElementInfo(void *v_p, const xmlChar* name) { 00512 cout << "Exit from '" << name << "' (depth = " << V2CTX_P(v_p)->depth << ")" << endl; 00513 } 00514 00515 }; // end TableSAXReader 00516 00517 template<class T, class R, class RFilter> xmlSAXHandler TableSAXReader<T, R, RFilter>::myHandler = TableSAXReader<T, R, RFilter>::initSAXHandler(); 00518 00519 /* ------------------------------------- TableSaxParser - end ------------------------------------------*/ 00520 #endif