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                 setAutoConvert(true);
00037         }
00038 };
00039 
00042 
00044 inline vec getvec ( Setting& S ) {
00045         vec vector;
00046         if (S.getType() == Setting::TypeArray) {        
00047                 vector.set_size ( S.getLength() );
00048                 for ( int i=0;i<S.getLength();i++ ) {
00049                         switch ( S[i].getType() ) {
00050                                 case Setting::TypeFloat :
00051                                         vector[i]=double ( S[i] );break;
00052                                 case Setting::TypeInt :
00053                                         vector[i]=int ( S[i] );break;
00054                                 case Setting::TypeBoolean :
00055                                         vector[i]=bool ( S[i] );break;
00056                                 default: it_error ( "libconfig error?" );
00057                         }
00058                 }
00059         } else if (S.getType() == Setting::TypeGroup) {
00060                 vector = getvec(S["elements"]);
00061                 int cols = S["cols"];
00062                 if (vector.length() != cols) { 
00063                         it_error("requested vector is a matrix");
00064                 }
00065         } else {
00066                 it_error("requested vector has invalid type");
00067         }
00068         return vector;
00069 };
00070 
00072 inline mat getmat ( Setting& S , int ncols ) {
00073         CHECK_UITYPE ( S,TypeArray );
00074         mat tmp;
00075         int nrows=S.getLength() /ncols;
00076         int r=0,c=0;
00077         tmp.set_size ( nrows, ncols );
00078         
00079         for ( int i=0;i<S.getLength();i++ ) {
00080                 switch ( S[i].getType() ) {
00081                         case Setting::TypeFloat :
00082                                 tmp ( r,c ) =double ( S[i] );break;
00083                         case Setting::TypeInt :
00084                                 tmp ( r,c ) =int ( S[i] );break;
00085                         case Setting::TypeBoolean :
00086                                 tmp ( r,c ) =bool ( S[i] );break;
00087                         default: it_error ( "libconfig error?" );
00088                 }
00089                 c++; if ( c==ncols ) {c=0;r++;}
00090         }
00091         return tmp;
00092 };
00093 
00096 inline mat getmat (Setting & S) {
00097         CHECK_UITYPE (S, TypeGroup);
00098         return getmat(S["elements"], S["cols"]);
00099 }
00100 
00102 
00103 inline ivec getivec ( Setting& S ) {
00104         CHECK_UITYPE ( S,TypeArray );
00105         ivec tmp;
00106         tmp.set_size ( S.getLength() );
00107         for ( int i=0;i<S.getLength();i++ ) {
00108                 switch ( S[i].getType() ) {
00109                         case Setting::TypeFloat :
00110                                 tmp[i]=double ( S[i] );break;
00111                         case Setting::TypeInt :
00112                                 tmp[i]=int ( S[i] );break;
00113                         case Setting::TypeBoolean :
00114                                 tmp[i]=bool ( S[i] );break;
00115                         default: it_error ( "libconfig error?" );
00116                 }
00117         }
00118         return tmp;
00119 };
00120 
00122 
00123 inline Array<string> get_as ( Setting& S ) {
00124         
00125         Array<string> tmp;
00126         tmp.set_size ( S.getLength() );
00127         for ( int i=0;i<S.getLength();i++ ) {tmp ( i ) = ( const char* ) S[i];}
00128         return tmp;
00129 };
00130 
00132 
00137 class UIbuilder {
00138 protected:
00139 public:
00141         UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
00143         virtual bdmroot* build ( Setting &S ) const =0;
00145         virtual ~UIbuilder(){};
00146 };
00147 
00157 class UIexternal:public UIbuilder {
00158 public:
00159         UIexternal() :UIbuilder ( "external" ) {}
00160         bdmroot* build ( Setting &S ) const;
00161 };
00162 
00171 class UIinternal:public UIbuilder {
00172 public:
00173         UIinternal() :UIbuilder ( "internal" ) {}
00174         bdmroot* build ( Setting &S ) const;
00175 };
00176 
00178 void UI_DBG ( Setting &S, const string &spc );
00179 
00181 template<class T>
00182 void UIbuild ( Setting &S, T* &ret ) {
00183         CHECK_UITYPE ( S,TypeGroup );
00184         
00185         it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00186 
00187         const string typ=S["type"];
00188         
00189         UImap::const_iterator iter = __uimap__.find ( typ );
00190         if ( iter == __uimap__.end() ) {
00191                 it_error ( "UI of type \"" + typ + "\" is not registered!" );
00192         }
00193 
00194         
00195         try {
00196                 ret = dynamic_cast<T*> ( iter->second->build ( S ) );
00197         }
00198         catch UICATCH
00199 };
00200 
00202 template<class T>
00203 void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
00204         CHECK_UITYPE ( S,TypeGroup );
00205         
00206         it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00207 
00208         const string typ=S["type"];
00209         if ( typ=="internal" ) {
00210                 try {
00211                         Setting* Stmp = &S;
00212                         do {Stmp=& ( Stmp->getParent() );}
00213                         while ( !Stmp->isRoot() );
00214                         Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
00215                         func ( intS, Tmp ); 
00216                         return;
00217                 }
00218                 catch ( ... ) {
00219                         it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
00220                 }
00221         }
00222         if ( typ=="external" ) {
00223                 UIFile C ( S["filename"] );
00224                 try {
00225                         func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
00226                 }
00227                 catch ( ... ) {
00228                         it_error ( "External field " + string ( S.getPath() ) + " not valid" );
00229                 }
00230                 return;
00231         }
00232 
00233         
00234         func ( S, Tmp );
00235 };
00236 
00237 }
00238 #endif //UIBUILD