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 
00018         class UIbuilder;
00020         typedef map<const string, const UIbuilder*> UImap;
00021         extern UImap __uimap__;
00022 
00023         class UIFile : public Config {
00024         public:
00025                 UIFile ( const char * fname ) :Config() {
00026                         try{Config::readFile ( fname );}
00027                         catch ( ParseException& P ) {
00028                                 char msg[200];
00029                                 sprintf ( msg,"Error in file %s  on line %d.", fname, P.getLine() );
00030                                 it_error ( msg );
00031                         }
00032                         catch ( FileIOException f ) {it_error ( "File " + string ( fname ) + " not found" );}
00033                 }
00034         };
00035 
00040         class UIbuilder {
00041         protected:
00042                 const vec getvec ( Setting& S ) const {
00043                         CHECK_UITYPE ( S,TypeArray );
00044                         vec tmp;
00045                         tmp.set_size ( S.getLength() );
00046                         for ( int i=0;i<S.getLength();i++ ) {
00047                                 switch ( S[i].getType() ) {
00048                                         case Setting::TypeFloat :
00049                                                 tmp[i]=double ( S[i] );break;
00050                                         case Setting::TypeInt :
00051                                                 tmp[i]=int ( S[i] );break;
00052                                         case Setting::TypeBoolean :
00053                                                 tmp[i]=bool ( S[i] );break;
00054                                         default: it_error ( "libconfig error?" );
00055                                 }
00056                         }
00057                         return tmp;
00058                 };
00059                 const vec getivec ( Setting& S ) const {
00060                         CHECK_UITYPE ( S,TypeArray );
00061                         vec tmp;
00062                         tmp.set_size ( S.getLength() );
00063                         for ( int i=0;i<S.getLength();i++ ) {
00064                                 switch ( S[i].getType() ) {
00065                                         case Setting::TypeFloat :
00066                                                 tmp[i]=double ( S[i] );break;
00067                                         case Setting::TypeInt :
00068                                                 tmp[i]=int ( S[i] );break;
00069                                         case Setting::TypeBoolean :
00070                                                 tmp[i]=bool ( S[i] );break;
00071                                         default: it_error ( "libconfig error?" );
00072                                 }
00073                         }
00074                         return tmp;
00075                 };
00076         public:
00078                 UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
00080                 virtual bdmroot* build ( Setting &S ) const =0;
00081         };
00082 
00083         class UIexternal:public UIbuilder {
00084         public:
00085                 UIexternal() :UIbuilder ( "external" ) {}
00086                 bdmroot* build ( Setting &S ) const;
00087         };
00088 
00089         class UIinternal:public UIbuilder {
00090         public:
00091                 UIinternal() :UIbuilder ( "internal" ) {}
00092                 bdmroot* build ( Setting &S ) const;
00093         };
00094 
00096         void UI_DBG ( Setting &S, const string &spc );
00097 
00099         template<class T>
00100         void UIbuild ( Setting &S, T* &ret ) {
00101                 CHECK_UITYPE ( S,TypeGroup );
00102                 
00103                 it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00104 
00105                 const string typ=S["type"];
00106                 
00107                 UImap::const_iterator iter = __uimap__.find ( typ );
00108                 if ( iter == __uimap__.end() ) {
00109                         it_error ( "UI of type \"" + typ + "\" is not registered!" );
00110                 }
00111 
00112                 
00113                 try {
00114                         ret = dynamic_cast<T*> ( iter->second->build ( S ) );
00115                 }
00116                 catch ( SettingTypeException e ) {
00117                         UI_DBG(S,""); 
00118                         it_error ( "Setting " +string ( e.getPath() ) +" is of incorrect Type" );}
00119                 catch ( SettingNotFoundException e ) {
00120                         UI_DBG(S,"");
00121                         it_error ( "Setting " + string ( e.getPath() ) +" was not found" );}
00122         };
00123 
00125         template<class T>
00126         void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
00127                 CHECK_UITYPE ( S,TypeGroup );
00128                 
00129                 it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00130 
00131                 const string typ=S["type"];
00132                 if ( typ=="internal" ) {
00133                         try {
00134                                 Setting* Stmp = &S;
00135                                 do {Stmp=& ( Stmp->getParent() );}
00136                                 while ( !Stmp->isRoot() );
00137                                 Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
00138                                 func ( intS, Tmp ); 
00139                                 return;
00140                         }
00141                         catch ( ... ) {
00142                                 it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
00143                         }
00144                 }
00145                 if ( typ=="external" ) {
00146                         UIFile C(S["filename"]);
00147                         try {
00148                                 func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
00149                         }
00150                         catch ( ... ) {
00151                                 it_error ( "External field " + string ( S.getPath() ) + " not valid" );
00152                         }
00153                         return;
00154                 }
00155 
00156                 
00157                 func ( S, Tmp );
00158         };
00159 
00160 }
00161 #endif //UIBUILD