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