root/bdm/uibuilder.h @ 263

Revision 263, 5.2 kB (checked in by smidl, 15 years ago)

UIArxDS test

Line 
1#ifndef UIBUILD
2#define UIBUILD
3
4#include <itpp/itbase.h>
5#include "stat/libBM.h"
6#include "libconfig/libconfig.h++"
7
8namespace bdm {
9
10        using namespace libconfig;
11        using namespace std;
12
13#define CHECK_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong input path \"")+string(S.getPath())+string("\""));
14#define UIREGISTER(UI) UI* UI##_global_instance = new UI();
15
16////////// GLOBAL VAriables
17
18        class UIbuilder;
19//! Internal structure mapping strings to UIBuilder objects
20        typedef map<const string, const UIbuilder*> UImap;
21        extern UImap __uimap__;
22
23        class UIFile : public Config {
24        public:
25                UIFile ( const char * fname ) :Config() {
26                        try{Config::readFile ( fname );}
27                        catch ( ParseException& P ) {
28                                char msg[200];
29                                sprintf ( msg,"Error in file %s  on line %d.", fname, P.getLine() );
30                                it_error ( msg );
31                        }
32                        catch ( FileIOException f ) {it_error ( "File " + string ( fname ) + " not found" );}
33                }
34        };
35
36        /*!\brief Builds computational object from a UserInfo structure
37
38        Return value is a pointer to the created object (memory management issue?)
39        */
40        class UIbuilder {
41        protected:
42                const vec getvec ( Setting& S ) const {
43                        CHECK_UITYPE ( S,TypeArray );
44                        vec tmp;
45                        tmp.set_size ( S.getLength() );
46                        for ( int i=0;i<S.getLength();i++ ) {
47                                switch ( S[i].getType() ) {
48                                        case Setting::TypeFloat :
49                                                tmp[i]=double ( S[i] );break;
50                                        case Setting::TypeInt :
51                                                tmp[i]=int ( S[i] );break;
52                                        case Setting::TypeBoolean :
53                                                tmp[i]=bool ( S[i] );break;
54                                        default: it_error ( "libconfig error?" );
55                                }
56                        }
57                        return tmp;
58                };
59                const mat getmat ( Setting& S , int ncols) const {
60                        CHECK_UITYPE ( S,TypeArray );
61                        mat tmp;
62                        int nrows=S.getLength()/ncols;
63                        int r=0,c=0;
64                        tmp.set_size ( nrows, ncols );
65                        // Build matrix row-wise
66                        for ( int i=0;i<S.getLength();i++ ) {
67                                switch ( S[i].getType() ) {
68                                        case Setting::TypeFloat :
69                                                tmp(r,c)=double ( S[i] );break;
70                                        case Setting::TypeInt :
71                                                tmp(r,c)=int ( S[i] );break;
72                                        case Setting::TypeBoolean :
73                                                tmp(r,c)=bool ( S[i] );break;
74                                        default: it_error ( "libconfig error?" );
75                                }
76                                c++; if (c==ncols) {c=0;r++;}
77                        }
78                        return tmp;
79                };
80                const vec getivec ( Setting& S ) const {
81                        CHECK_UITYPE ( S,TypeArray );
82                        vec tmp;
83                        tmp.set_size ( S.getLength() );
84                        for ( int i=0;i<S.getLength();i++ ) {
85                                switch ( S[i].getType() ) {
86                                        case Setting::TypeFloat :
87                                                tmp[i]=double ( S[i] );break;
88                                        case Setting::TypeInt :
89                                                tmp[i]=int ( S[i] );break;
90                                        case Setting::TypeBoolean :
91                                                tmp[i]=bool ( S[i] );break;
92                                        default: it_error ( "libconfig error?" );
93                                }
94                        }
95                        return tmp;
96                };
97        public:
98                //!Constructor needs to be run only once macro UIREGISTER
99                UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
100                //! Function building the computational object
101                virtual bdmroot* build ( Setting &S ) const =0;
102        };
103
104        class UIexternal:public UIbuilder {
105        public:
106                UIexternal() :UIbuilder ( "external" ) {}
107                bdmroot* build ( Setting &S ) const;
108        };
109
110        class UIinternal:public UIbuilder {
111        public:
112                UIinternal() :UIbuilder ( "internal" ) {}
113                bdmroot* build ( Setting &S ) const;
114        };
115
116        //! [Debugging] Print values in current S to cout
117        void UI_DBG ( Setting &S, const string &spc );
118
119//! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
120        template<class T>
121        void UIbuild ( Setting &S, T* &ret ) {
122                CHECK_UITYPE ( S,TypeGroup );
123                // Check if field "type" is present, if not it is not a valid UI
124                it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
125
126                const string typ=S["type"];
127                // Find "type" in list of registred UI builders
128                UImap::const_iterator iter = __uimap__.find ( typ );
129                if ( iter == __uimap__.end() ) {
130                        it_error ( "UI of type \"" + typ + "\" is not registered!" );
131                }
132
133                //BUILD the result
134                try {
135                        ret = dynamic_cast<T*> ( iter->second->build ( S ) );
136                }
137                catch ( SettingTypeException e ) {
138                        UI_DBG(S,""); 
139                        it_error ( "Setting " +string ( e.getPath() ) +" is of incorrect Type" );}
140                catch ( SettingNotFoundException e ) {
141                        UI_DBG(S,"");
142                        it_error ( "Setting " + string ( e.getPath() ) +" was not found" );}
143        };
144
145//! Auxiliary function allowing recursivity in S (too complex, remove?)
146        template<class T>
147        void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
148                CHECK_UITYPE ( S,TypeGroup );
149                // Check if field "type" is present, if not it is not a valid UI
150                it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
151
152                const string typ=S["type"];
153                if ( typ=="internal" ) {
154                        try {
155                                Setting* Stmp = &S;
156                                do {Stmp=& ( Stmp->getParent() );}
157                                while ( !Stmp->isRoot() );
158                                Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
159                                func ( intS, Tmp ); // <======== calling func
160                                return;
161                        }
162                        catch ( ... ) {
163                                it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
164                        }
165                }
166                if ( typ=="external" ) {
167                        UIFile C(S["filename"]);
168                        try {
169                                func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
170                        }
171                        catch ( ... ) {
172                                it_error ( "External field " + string ( S.getPath() ) + " not valid" );
173                        }
174                        return;
175                }
176
177                // v======================= calling final func
178                func ( S, Tmp );
179        };
180
181}
182#endif //UIBUILD
Note: See TracBrowser for help on using the browser.