Wexus2 0.20
|
00001 00002 /* 00003 * Copyright (c) 2011 Aleksander B. Demko 00004 * This source code is distributed under the MIT license. 00005 * See the accompanying file LICENSE.MIT.txt for details. 00006 */ 00007 00008 #ifndef __INCLUDED_WEXUS_ACTIVECLASS_H__ 00009 #define __INCLUDED_WEXUS_ACTIVECLASS_H__ 00010 00011 #include <assert.h> 00012 00013 #include <wexus/TR1.h> 00014 00015 #include <QString> 00016 #include <QMap> 00017 #include <QVector> 00018 #include <QVariant> 00019 #include <QSqlDatabase> 00020 00021 #include <wexus/ValidationExpr.h> 00022 00023 namespace wexus 00024 { 00025 class ActiveClass; 00026 00027 class ActiveRecord; //fwd 00028 00029 inline void variantToData(const QVariant &src, QString *outdata) 00030 { 00031 if (src.isValid()) 00032 *outdata = src.toString(); 00033 else 00034 outdata->clear(); 00035 } 00036 inline void variantToData(const QVariant &src, int *outdata) 00037 { 00038 if (src.isValid()) 00039 *outdata = src.toInt(); 00040 else 00041 *outdata = -1; 00042 } 00043 } 00044 00045 /** 00046 * Represents a wexus::ActiveRecord type. 00047 * Every wexus::ActiveRecord has a link to one of these. 00048 * 00049 * @author Aleksander Demko 00050 */ 00051 class wexus::ActiveClass 00052 { 00053 public: 00054 /** 00055 * Converts C++ types (int QString) to SQL types. 00056 * 00057 * @author Aleksander Demko 00058 */ 00059 static QString toSqlType(const QString &t); 00060 00061 /** 00062 * Field "styles". 00063 * 00064 * various "styles" of keys. I really want to call 00065 * these "types", but that would conflict with fieldType() 00066 * already. 00067 * @author Aleksander Demko 00068 */ 00069 enum { 00070 keyStyle = 1, 00071 varStyle, 00072 fKeyStyle, 00073 }; 00074 00075 /** 00076 * Represents one field in an wexus::ActiveClass 00077 * 00078 * @author Aleksander Demko 00079 */ 00080 class ActiveField 00081 { 00082 public: 00083 /// constructor 00084 ActiveField(int style, const QString &fieldName, const QString &fieldType, 00085 const ValidationExpr &valexpr, const QVariant &initVal); 00086 00087 /** 00088 * Returns the "style" (type) of field this is. 00089 * 00090 * @author Aleksander Demko 00091 */ 00092 int style(void) const { return dm_style; } 00093 00094 /** 00095 * Returns the field name of this field. 00096 * 00097 * @author Aleksander Demko 00098 */ 00099 const QString & fieldName(void) const { return dm_fieldName; } 00100 /** 00101 * Returns the C++ data type of this field. 00102 * 00103 * @author Aleksander Demko 00104 */ 00105 const QString & fieldType(void) const { return dm_fieldType; } 00106 /** 00107 * Returns the SQL datatype (converted from fieldType() via toSqlType()) 00108 * of this field. 00109 * 00110 * @author Aleksander Demko 00111 */ 00112 QString sqlFieldType(void) const { return toSqlType(dm_fieldType); } 00113 00114 /** 00115 * Returns the wexus::ValidationExpr defined in the .eh 00116 * for this field, or a null wexus::ValidationExpr is 00117 * none was defined. 00118 * 00119 * @author Aleksander Demko 00120 */ 00121 const ValidationExpr & validationExpr(void) const { return dm_valexpr; } 00122 00123 /** 00124 * Returns the default value, as defined in the .eh file. 00125 * Returns an invalida QVariant if none was set. 00126 * 00127 * @author Aleksander Demko 00128 */ 00129 const QVariant & initVal(void) const { return dm_initval; } 00130 00131 /** 00132 * Converts the current value of this field in the given 00133 * wexus::ActiveRecord instance to a QVariant 00134 * and returns it. 00135 * 00136 * @author Aleksander Demko 00137 */ 00138 virtual QVariant toVariant(const ActiveRecord *inst) const = 0; 00139 00140 /** 00141 * Sets the value of thie field in the given wexus::ActiveRecord 00142 * instance to v. 00143 * 00144 * @author Aleksander Demko 00145 */ 00146 virtual void setVariant(ActiveRecord *inst, const QVariant &v) = 0; 00147 00148 private: 00149 int dm_style; 00150 QString dm_fieldName, dm_fieldType; 00151 ValidationExpr dm_valexpr; 00152 QVariant dm_initval; 00153 }; 00154 00155 template <class RECT, class DATT> class ActiveFieldType : public ActiveField 00156 { 00157 public: 00158 typedef DATT RECT::*MemberPtr; 00159 00160 public: 00161 ActiveFieldType(int style, const QString &fieldName, const QString &fieldType, 00162 const ValidationExpr &valexpr, const QVariant &initVal, 00163 MemberPtr memberptr) 00164 : ActiveField(style, fieldName, fieldType, valexpr, initVal), dm_memberptr(memberptr) { } 00165 00166 virtual QVariant toVariant(const ActiveRecord *inst) const { 00167 const RECT * recinstance = dynamic_cast<const RECT*>(inst); 00168 const DATT * datptr; 00169 00170 assert(recinstance); 00171 00172 datptr = & (recinstance->*dm_memberptr); 00173 00174 return QVariant(*datptr); 00175 } 00176 00177 virtual void setVariant(ActiveRecord *inst, const QVariant &v) { 00178 RECT * recinstance = dynamic_cast<RECT*>(inst); 00179 DATT * datptr; 00180 00181 assert(recinstance); 00182 00183 datptr = & (recinstance->*dm_memberptr); 00184 00185 variantToData(v, datptr); 00186 } 00187 00188 private: 00189 MemberPtr dm_memberptr; 00190 }; 00191 00192 public: 00193 00194 /// ctor 00195 ActiveClass(const QString &_className); 00196 00197 /** 00198 * The C++ class name of this type. 00199 * 00200 * @author Aleksander Demko 00201 */ 00202 const QString & className(void) const { return dm_classname; } 00203 00204 /** 00205 * The C++ class converted to a SQL-comptabile string (mostly :: removed) 00206 * 00207 * @author Aleksander Demko 00208 */ 00209 const QString & tableName(void) const { return dm_tablename; } 00210 00211 /** 00212 * Returns all the field names as one string, seperated 00213 * by commas. Each field name will be prefixed by tableName(). 00214 * 00215 * @author Aleksander Demko 00216 */ 00217 const QString & fieldsAsList(void) const { return dm_fieldsaslist; } 00218 /** 00219 * Returns all the field names as one string, seperated 00220 * by commas. 00221 * 00222 * @author Aleksander Demko 00223 */ 00224 const QString & fieldsAsListSansTable(void) const { return dm_fieldsaslistsanstable; } 00225 /** 00226 * Returns a list of question marks, each seperated by a comma. 00227 * There will be as many question marks as their are fields in this 00228 * class. 00229 * 00230 * @author Aleksander Demko 00231 */ 00232 const QString & questionsAsList(void) const { return dm_questionsaslist; } 00233 00234 /** 00235 * Returns the index of the key column. 00236 * There can only be one (for now.. anyways) 00237 * 00238 * Never fails. 00239 * 00240 * @author Aleksander Demko 00241 */ 00242 int keyColumn(void) const; 00243 00244 /** 00245 * Return the ActiveField referenced by keyColumn() 00246 * 00247 * @author Aleksander Demko 00248 */ 00249 std::shared_ptr<ActiveField> keyField(void) const { return fieldsVec()[keyColumn()]; } 00250 00251 /// creates the table in the database 00252 void createTable(void) const; 00253 00254 public: 00255 typedef QVector<std::shared_ptr<ActiveField> > FieldVec; 00256 typedef QMap<QString, std::shared_ptr<ActiveField> > FieldMap; 00257 00258 /** 00259 * Returns all the fields as a vector. 00260 * 00261 * @author Aleksander Demko 00262 */ 00263 FieldVec & fieldsVec(void) { return dm_vec; } 00264 00265 /** 00266 * Returns all the fields as a vector. 00267 * 00268 * @author Aleksander Demko 00269 */ 00270 const FieldVec & fieldsVec(void) const { return dm_vec; } 00271 00272 /** 00273 * Returns all the fields as a map 00274 * keyed by their field names. 00275 * 00276 * @author Aleksander Demko 00277 */ 00278 FieldMap & fieldsMap(void) { return dm_map; } 00279 00280 /** 00281 * Returns all the fields as a map 00282 * keyed by their field names. 00283 * 00284 * @author Aleksander Demko 00285 */ 00286 const FieldMap & fieldsMap(void) const { return dm_map; } 00287 00288 protected: 00289 /// field adder 00290 template <class RECT, class DATT> 00291 void addField(int style, const QString &fieldName, const QString &fieldType, 00292 const ValidationExpr &valexpr, 00293 const QVariant &initVal, 00294 typename ActiveFieldType<RECT,DATT>::MemberPtr memberptr) { 00295 std::shared_ptr<ActiveField> f(new ActiveFieldType<RECT,DATT>(style, fieldName, fieldType, valexpr, initVal, memberptr)); 00296 00297 dm_vec.push_back(f); 00298 dm_map[fieldName] = f; 00299 00300 if (style == keyStyle) { 00301 assert(dm_keycolumn == -1); // only one primary key field for now 00302 dm_keycolumn = dm_vec.size()-1; 00303 } 00304 } 00305 /// called by descendants construtors 00306 void doneConstruction(void); 00307 00308 private: 00309 QString dm_classname; 00310 QString dm_tablename; 00311 QString dm_fieldsaslist, dm_fieldsaslistsanstable, dm_questionsaslist; 00312 00313 int dm_keycolumn; 00314 00315 FieldVec dm_vec; 00316 FieldMap dm_map; 00317 }; 00318 00319 #endif 00320