casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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 <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