00001 #ifndef UIBUILD
00002 #define UIBUILD
00003 
00004 #include <itpp/itbase.h>
00005 #include "stat/libBM.h"
00006 #include "libconfig/libconfig.h++"
00007 
00008 namespace bdm {
00009 
00010 using namespace libconfig;
00011 using namespace std;
00012 
00013 #define CHECK_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong input path \"")+string(S.getPath())+string("\""));
00014 #define UIREGISTER(UI) UI* UI##_global_instance = new UI();
00015 
00017 #define UICATCH  ( SettingTypeException e ) {it_error ( "Setting " +string ( e.getPath() ) +" is of incorrect Type" );} catch ( SettingNotFoundException e ) {it_error ( "Setting " + string ( e.getPath() ) +" was not found" );}
00018 
00020 
00021 class UIbuilder;
00023 typedef map<const string, const UIbuilder*> UImap;
00024 extern UImap __uimap__;
00025 
00026 class UIFile : public Config {
00027 public:
00028         UIFile ( const char * fname ) :Config() {
00029                 try{Config::readFile ( fname );}
00030                 catch ( FileIOException f ) {it_error ( "File " + string ( fname ) + " not found" );}
00031                 catch ( ParseException& P ) {
00032                         char msg[200];
00033                         sprintf ( msg,"Error in file %s  on line %d.", fname, P.getLine() );
00034                         it_error ( msg );
00035                 }
00036         }
00037 };
00038 
00041 
00043 inline vec getvec ( Setting& S ) {
00044         CHECK_UITYPE ( S,TypeArray );
00045         vec tmp;
00046         tmp.set_size ( S.getLength() );
00047         for ( int i=0;i<S.getLength();i++ ) {
00048                 switch ( S[i].getType() ) {
00049                         case Setting::TypeFloat :
00050                                 tmp[i]=double ( S[i] );break;
00051                         case Setting::TypeInt :
00052                                 tmp[i]=int ( S[i] );break;
00053                         case Setting::TypeBoolean :
00054                                 tmp[i]=bool ( S[i] );break;
00055                         default: it_error ( "libconfig error?" );
00056                 }
00057         }
00058         return tmp;
00059 };
00060 
00062 inline mat getmat ( Setting& S , int ncols ) {
00063         CHECK_UITYPE ( S,TypeArray );
00064         mat tmp;
00065         int nrows=S.getLength() /ncols;
00066         int r=0,c=0;
00067         tmp.set_size ( nrows, ncols );
00068         
00069         for ( int i=0;i<S.getLength();i++ ) {
00070                 switch ( S[i].getType() ) {
00071                         case Setting::TypeFloat :
00072                                 tmp ( r,c ) =double ( S[i] );break;
00073                         case Setting::TypeInt :
00074                                 tmp ( r,c ) =int ( S[i] );break;
00075                         case Setting::TypeBoolean :
00076                                 tmp ( r,c ) =bool ( S[i] );break;
00077                         default: it_error ( "libconfig error?" );
00078                 }
00079                 c++; if ( c==ncols ) {c=0;r++;}
00080         }
00081         return tmp;
00082 };
00083 
00085 
00086 inline ivec getivec ( Setting& S ) {
00087         CHECK_UITYPE ( S,TypeArray );
00088         ivec tmp;
00089         tmp.set_size ( S.getLength() );
00090         for ( int i=0;i<S.getLength();i++ ) {
00091                 switch ( S[i].getType() ) {
00092                         case Setting::TypeFloat :
00093                                 tmp[i]=double ( S[i] );break;
00094                         case Setting::TypeInt :
00095                                 tmp[i]=int ( S[i] );break;
00096                         case Setting::TypeBoolean :
00097                                 tmp[i]=bool ( S[i] );break;
00098                         default: it_error ( "libconfig error?" );
00099                 }
00100         }
00101         return tmp;
00102 };
00103 
00105 
00106 inline Array<string> get_as ( Setting& S ) {
00107         CHECK_UITYPE ( S,TypeArray );
00108         Array<string> tmp;
00109         tmp.set_size ( S.getLength() );
00110         for ( int i=0;i<S.getLength();i++ ) {tmp ( i ) = ( const char* ) S[i];}
00111         return tmp;
00112 };
00113 
00115 
00120 class UIbuilder {
00121 protected:
00122 public:
00124         UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
00126         virtual bdmroot* build ( Setting &S ) const =0;
00127 };
00128 
00138 class UIexternal:public UIbuilder {
00139 public:
00140         UIexternal() :UIbuilder ( "external" ) {}
00141         bdmroot* build ( Setting &S ) const;
00142 };
00143 
00152 class UIinternal:public UIbuilder {
00153 public:
00154         UIinternal() :UIbuilder ( "internal" ) {}
00155         bdmroot* build ( Setting &S ) const;
00156 };
00157 
00159 void UI_DBG ( Setting &S, const string &spc );
00160 
00162 template<class T>
00163 void UIbuild ( Setting &S, T* &ret ) {
00164         CHECK_UITYPE ( S,TypeGroup );
00165         
00166         it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00167 
00168         const string typ=S["type"];
00169         
00170         UImap::const_iterator iter = __uimap__.find ( typ );
00171         if ( iter == __uimap__.end() ) {
00172                 it_error ( "UI of type \"" + typ + "\" is not registered!" );
00173         }
00174 
00175         
00176         try {
00177                 ret = dynamic_cast<T*> ( iter->second->build ( S ) );
00178         }
00179         catch UICATCH
00180 };
00181 
00183 template<class T>
00184 void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
00185         CHECK_UITYPE ( S,TypeGroup );
00186         
00187         it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00188 
00189         const string typ=S["type"];
00190         if ( typ=="internal" ) {
00191                 try {
00192                         Setting* Stmp = &S;
00193                         do {Stmp=& ( Stmp->getParent() );}
00194                         while ( !Stmp->isRoot() );
00195                         Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
00196                         func ( intS, Tmp ); 
00197                         return;
00198                 }
00199                 catch ( ... ) {
00200                         it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
00201                 }
00202         }
00203         if ( typ=="external" ) {
00204                 UIFile C ( S["filename"] );
00205                 try {
00206                         func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
00207                 }
00208                 catch ( ... ) {
00209                         it_error ( "External field " + string ( S.getPath() ) + " not valid" );
00210                 }
00211                 return;
00212         }
00213 
00214         
00215         func ( S, Tmp );
00216 };
00217 
00218 }
00219 #endif //UIBUILD