Wexus2 0.20
wexus2.src/wexus/ActiveClass.h
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 
 All Classes Namespaces Functions Variables Enumerations Enumerator