asdm2MSGeneric.h

Go to the documentation of this file.
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 /* ------------------------------------- TableSaxParser - beginning ------------------------------------------*/
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     //LogSinkInterface& lsif = LogSink::globalSink();
00258     static_cast<void>(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 **) {
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 = 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       // 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 #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         // Empty the vector before reading new rows.
00398         //
00399         V2CTX_P(v_p)->rows.clear();
00400       }
00401       break;
00402         
00403       // We were in an <Entity/> element.
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       // We were in a <ContainerEntity/> element.
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       // We were in a <row>..</row> element.
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       // Push the last parsed row into the vector.
00421       V2CTX_P(v_p)->rows.push_back(V2CTX_P(v_p)->row_sp);
00422 
00423       // If the size of this vector is equal to the maximum number allowed to reside in memory
00424       // then proceed by applying tableFiller on on the vector and after that clear the vector.
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           // Log a minimum of information about what has just happened.
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       // We were in an element located in a <row>..</row>, which is normally an attribute. 
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 }; // end TableSAXReader
00524   
00525 template<class T, class R, class RFilter> xmlSAXHandler TableSAXReader<T, R, RFilter>::myHandler = TableSAXReader<T, R, RFilter>::initSAXHandler();
00526 
00527 /* ------------------------------------- TableSaxParser - end ------------------------------------------*/  
00528 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1