make transaction async
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 3 Oct 2010 14:07:37 +0000 (14:07 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 3 Oct 2010 14:07:37 +0000 (14:07 +0000)
git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@598 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

qtbase/include/transaction.h
qtbase/include/transaction_p.h
qtbase/src/transaction.cpp
woc/qt/qtctrans.cpp
woc/qt/qtout.cpp
woc/qt/qtout.h

index 103e277..25cc027 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "nullable.h"
 #include "WHelper"
+#include <QPointer>
 
 class WTransaction_Private;
 
@@ -29,14 +30,20 @@ class WTransaction:public WHelper
        public:
                /**stage the transaction is in*/
                enum Stage {
-                       Uninitialized,///<transaction has not started yet
-                       Request,///<transaction is running
-                       Success,///<transaction ended successfully
-                       Error,///<transaction ended with an error
+                       Uninitialized=0,///<transaction has not started yet
+                       Request=1,///<transaction is running
+                       Success=6,///<transaction ended successfully
+                       Error=10,///<transaction ended with an error
                };
                
                /**returns the stage the transaction is in*/
                virtual Stage stage()const;
+               ///returns true if the transaction is currently in progress
+               virtual bool isInProgress()const{return stage()==Request;}
+               ///returns true if the transaction is finished
+               virtual bool isFinished()const{return stage()&2;}
+               ///returns true if the transaction has not started yet
+               virtual bool isUnstarted()const{return stage()==Uninitialized;}
                
                /**returns whether the transaction had an error while executing*/
                virtual bool hasError()const;
@@ -48,8 +55,46 @@ class WTransaction:public WHelper
                /**returns the interface that is used for the transaction*/
                virtual QString interface()const;
                
+               /**waits for this transaction to finish, returns true if the transaction was successful, returns immediately if the transaction is not running
+               \param tmout the maximum amount of milli seconds to wait, if 0 it will not time out*/
+               virtual bool waitForFinished(int tmout=30000);
+               
                /**deconstructor*/
                virtual ~WTransaction();
+               
+               /// \private internal classes
+               class Log;
+               class LogWrap;
+               
+               /// \private ancestor of other WaitFor classes
+               class WaitFor_Private {
+                       public:
+                               virtual ~WaitFor_Private(){}
+                               WaitFor_Private& operator<<(WTransaction&);
+                               WaitFor_Private& operator<<(WTransaction*);
+                       protected:
+                               WaitFor_Private(int t){m_tmout=t;}
+                               virtual void loop()=0;
+                               QList<QPointer<WTransaction> > m_trn;
+                               int m_tmout;
+               };
+               
+               /**use this class to wait for any of a number of transactions */
+               class WaitForAny:public WaitFor_Private{
+                       public:
+                               WaitForAny(int tmout=0):WaitFor_Private(tmout){}
+                               virtual ~WaitForAny(){loop();}
+                       protected:
+                               void loop();
+               };
+               /**use this class to wait for all of a number of transactions */
+               class WaitForAll:public WaitFor_Private{
+                       public:
+                               WaitForAll(int tmout=0):WaitFor_Private(tmout){}
+                               virtual ~WaitForAll(){loop();}
+                       protected:
+                               void loop();
+               };
        protected:
                /**internal: construct the transaction*/
                WTransaction(QString iface=QString());
@@ -65,14 +110,15 @@ class WTransaction:public WHelper
                /**internal: execute a query on the web asynchronously*/
                virtual void startQuery(QString,QByteArray);
                
+       protected slots:
                /**internal: collect query data*/
-               virtual void endQuery();
+               virtual void endQuery()=0;
        signals:
-               /** this signal is raised when the transaction is finished, data is available*/
+               /** this signal is raised when the transaction is finished successfully or with an error, data or an error information is available*/
                void finished();
        protected:
-               class Log;
                friend class WTransaction::Log;
+               friend class WTransaction::LogWrap;
                friend class WTransaction_Private;
                WTransaction_Private *d;
 };
index 6a7716b..cc58d2a 100644 (file)
@@ -58,6 +58,7 @@ class WTransaction_Private:public QObject {
        Q_OBJECT
        public:
                WTransaction_Private(WTransaction*);
+               virtual ~WTransaction_Private();
                /**internal: execute a query synchronously on the web, used by subclasses*/
                virtual QByteArray executeQuery(QString,QByteArray);
                
@@ -76,6 +77,8 @@ class WTransaction_Private:public QObject {
        signals:
                /** \internal this signal is raised when the transaction on the HTTP level finished*/
                void webFinished();
+               /** used by high level objects, emitted when data is available */
+               void dataAvailable();
                
        public:
                WTransaction::Stage m_stage;
@@ -95,4 +98,33 @@ class WTransaction_Private:public QObject {
                int m_refctr;
 };
 
+/// \internal wrapper around the logger
+class WTransaction::LogWrap{
+       public:
+               /**instantiates a log wrapper using the logger of the parent or creates a new one in the parent*/
+               LogWrap(WTransaction*parent,const QString&request,const QString&interface=QString());
+               
+               ///logs/stores a request message
+               void setRequ(const QString&,const QString&);
+               ///logs/stores a response message
+               void setResp(const QString&,const QString&);
+               ///logs an error, if the interface is set up to log only on errors it also logs the stored request and response
+               void setError(const QString&);
+               ///logs some informational message
+               void setInfo(const QString&);
+       private:
+               WTransaction*parent;
+};
+
+class WTransaction_PrivateBase {
+       private:
+               int refctr;
+       protected:
+               WTransaction_PrivateBase();
+               virtual ~WTransaction_PrivateBase();
+       public:
+               virtual void attach(){refctr++;}
+               virtual void detach(){refctr--;if(refctr==0)delete this;}
+};
+
 #endif
index 56fc80a..0c9a10f 100644 (file)
@@ -15,6 +15,7 @@
 #include "WInterface"
 
 #include <QCoreApplication>
+#include <QDateTime>
 #include <QDebug>
 #include <QEventLoop>
 #include <QNetworkAccessManager>
@@ -137,7 +138,6 @@ void WTransaction_Private::startQuery(QString hreq,QByteArray data)
 
 }
 
-void WTransaction::endQuery(){d->endQuery();}
 void WTransaction_Private::endQuery()
 {
        //sanity check
@@ -181,8 +181,10 @@ void WTransaction_Private::endQuery()
                m_stage=WTransaction::Error;
                m_errtype="_internal";
                m_errstr="Ooops: still in Request phase at end of response handling.";
+               return;
        }
        //remaining high level errors are handled by the generated code
+       emit dataAvailable();
 }
 
 QByteArray WTransaction::executeQuery(QString hreq,QByteArray data){return d->executeQuery(hreq,data);}
@@ -210,6 +212,21 @@ QByteArray WTransaction_Private::executeQuery(QString hreq,QByteArray data)
                return QByteArray();
 }
 
+bool WTransaction::waitForFinished(int tmout)
+{
+       //is it running?
+       if(d->m_stage==Success)return true;
+       if(d->m_stage!=Request)return false;
+       //wait for it
+       QEventLoop loop;
+       connect(this,SIGNAL(finished()),&loop,SLOT(quit()));
+       if(tmout>0)
+               QTimer::singleShot(tmout,&loop,SLOT(quit()));
+       loop.exec();
+       //return
+       return d->m_stage==Success;
+}
+
 void WTransaction_Private::webTimeout()
 {
        if(m_stage!=WTransaction::Request)return;
@@ -332,6 +349,35 @@ void WTransaction::Log::setError(const QString&s)
        outStr(QString("Transaction %1 Error: %2").arg(trn).arg(s));
 }
 
+WTransaction::LogWrap::LogWrap(WTransaction*p,const QString&r,const QString&i)
+{
+       Q_ASSERT_X(p!=0,"LogWrap constructor","expecting parent to be valid");
+       parent=p;
+       if(p->d->m_log==0)new Log(p,r,i);
+}
+
+void WTransaction::LogWrap::setRequ(const QString&s1,const QString&s2)
+{
+       if(parent->d->m_log)
+               parent->d->m_log->setRequ(s1,s2);
+}
+void WTransaction::LogWrap::setResp(const QString&s1,const QString&s2)
+{
+       if(parent->d->m_log)
+               parent->d->m_log->setResp(s1,s2);
+}
+void WTransaction::LogWrap::setError(const QString&s)
+{
+       if(parent->d->m_log)
+               parent->d->m_log->setError(s);
+}
+void WTransaction::LogWrap::setInfo(const QString&s)
+{
+       if(parent->d->m_log)
+               parent->d->m_log->setInfo(s);
+}
+
+
 /*****************************************************************************/
 
 WTransaction_Private::WTransaction_Private(WTransaction*trn)
@@ -341,12 +387,19 @@ WTransaction_Private::WTransaction_Private(WTransaction*trn)
        m_refctr=0;
        attach(trn);
        connect(this,SIGNAL(webFinished()),this,SLOT(endQuery()));
+//     qDebug()<<"constructed a private object"<<(long long)this;
+}
+
+WTransaction_Private::~WTransaction_Private()
+{
+//     qDebug()<<"destructing private object"<<(long long)this;
 }
 
 WTransaction_Private* WTransaction_Private::attach(WTransaction*trn)
 {
        m_refctr++;
        connect(trn,SIGNAL(destroyed(QObject*)),this,SLOT(detach(QObject*)));
+       connect(this,SIGNAL(dataAvailable()),trn,SLOT(endQuery()));
        return this;
 }
 
@@ -360,3 +413,74 @@ void WTransaction_Private::detach(QObject*trn)
                trn->disconnect(this);
        }
 }
+
+WTransaction_PrivateBase::WTransaction_PrivateBase()
+{
+       refctr=1;
+//     qDebug()<<"created private base"<<(long long)this;
+}
+
+WTransaction_PrivateBase::~WTransaction_PrivateBase()
+{
+//     qDebug()<<"destructed private base"<<(long long)this;
+}
+
+/*****************************************************************************/
+
+WTransaction::WaitFor_Private& WTransaction::WaitFor_Private::operator<<(WTransaction&t)
+{
+       m_trn<< &t;
+       return *this;
+}
+WTransaction::WaitFor_Private& WTransaction::WaitFor_Private::operator<<(WTransaction*t)
+{
+       m_trn<< t;
+       return *this;
+}
+
+void WTransaction::WaitForAny::loop()
+{
+       QEventLoop loop;
+       //reduce list and connect to signals
+       for(int i=0;i<m_trn.size();i++){
+               if(m_trn[i].isNull())continue;
+               if(!m_trn[i]->isInProgress())continue;
+               connect(m_trn[i],SIGNAL(finished()),&loop,SLOT(quit()));
+       }
+       //set up timeout
+       if(m_tmout>0)
+               QTimer::singleShot(m_tmout,&loop,SLOT(quit()));
+       //start loop
+       loop.exec();
+}
+void WTransaction::WaitForAll::loop()
+{
+       QDateTime start=QDateTime::currentDateTime();
+       do{
+               int rtm=0;
+               //check timeout
+               if(m_tmout>0){
+                       rtm=m_tmout-start.msecsTo(QDateTime::currentDateTime());
+                       if(rtm<=0)
+                               return;
+               }
+               //reduce list
+               QList<QPointer<WTransaction> > tmp;
+               for(int i=0;i<m_trn.size();i++){
+                       if(m_trn[i].isNull())continue;
+                       if(!m_trn[i]->isInProgress())continue;
+                       tmp<<m_trn[i];
+               }
+               if(tmp.size()==0)return;
+               m_trn=tmp;
+               //create loop
+               QEventLoop loop;
+               for(int i=0;i<m_trn.size();i++)
+                       connect(m_trn[i],SIGNAL(finished()),&loop,SLOT(quit()));
+               //set up timeout
+               if(rtm>0)
+                       QTimer::singleShot(rtm,&loop,SLOT(quit()));
+               //start loop
+               loop.exec();
+       }while(true);
+}
index 515adae..6a7fefa 100644 (file)
@@ -31,10 +31,14 @@ void WocQtClientTransaction::finalize()
 void WocQtClientTransaction::newTransaction(const WocTransaction&trn)
 {
        QString cn=m_prefix+"T"+trn.name();
+       QString cnp=cn+"_Private";
        addFile(cn);
+//     addFile(WocQtOut::Header,"prv"+cn+".h");
        MFile hdr(m_basedir+"/"+m_subdir+"/src"+cn+".h");
+//     MFile hdp(m_basedir+"/"+m_subdir+"/prv"+cn+".h");
        MFile src(m_basedir+"/"+m_subdir+"/src"+cn+".cpp");
        if(!hdr.open(QIODevice::WriteOnly|QIODevice::Truncate) ||
+//        !hdp.open(QIODevice::WriteOnly|QIODevice::Truncate) ||
           !src.open(QIODevice::WriteOnly|QIODevice::Truncate)){
                qDebug("Error: cannot create class files for transaction %s.",cn.toAscii().data());
                emit errorFound();
@@ -45,44 +49,59 @@ void WocQtClientTransaction::newTransaction(const WocTransaction&trn)
        QStringList out=trn.outputNames();
        //lead in
        hdr.write(QByteArray(HDRSTART).replace("%",cn.toAscii()));
+//     hdp.write(QByteArray(HDRSTART).replace("%",cnp.toAscii()));
        src.write(QByteArray(SRCSTART).replace("%",cn.toAscii()));
-       QString hcd;
-       QString scd;
-       hcd="#include \""+m_transbase+"\"\n";
-       hcd+="#include \"WTransaction_Private\"\n";
-       scd+="#include \"WInterface\"\n#include <QCoreApplication>\n";
+       
+       //start constructing code
+       QString hcd;//header: class decl
+       QString hdi;//header includes
+       QString pcd;//private class decl
+       QString scd;//cpp source
+       QString sri;//cpp includes
+       hdi="#include \""+m_transbase+"\"\n";
+//     pcd="#include \"src"+cn+".h\"\n";
+       sri+="#include \"WTransaction_Private\"\n";
+//     sri+="#include \"prv"+cn+".h\"\n";
+       sri+="#include \"WInterface\"\n";
+       sri+="#include <QCoreApplication>\n\n";
        for(int i=0;i<in.size();i++){
                QString tp=qtobjtype(trn,in[i],WocQtOut::In);
-               if(tp!="")hcd+="#include <"+tp+">\n";
+               if(tp!="")hdi+="#include <"+tp+">\n";
        }
        for(int i=0;i<out.size();i++){
                QString tp=qtobjtype(trn,out[i],WocQtOut::Out);
-               if(tp!="")hcd+="#include <"+tp+">\n";
+               if(tp!="")hdi+="#include <"+tp+">\n";
        }
+       hcd+="\nclass "+cnp+";\n";
        hcd+="\nclass "+cn+":public "+m_transbase+"\n{\n";
-       hdr.write(hcd.toAscii());
+       pcd+="\nclass "+cnp+":public WTransaction_PrivateBase\n{\n";
        
        //create properties
        QString inlist,clist;
-       hcd="  private:\n";
+       hcd+="  private:\n\t"+cnp+"*p;\n\tfriend class "+cnp+";\n";
+       pcd+="  protected:\n\tfriend class "+cn+";\n";
+       pcd+="\t"+cnp+"("+cn+"*parent){parent->p=this;}\n";
+       pcd+="\tvoid attach("+cn+"*parent){parent->p=this;WTransaction_PrivateBase::attach();}\n";
+       pcd+="\tvoid detach("+cn+"*parent){parent->p=0;WTransaction_PrivateBase::detach();}\n";
        for(int i=0;i<in.size();i++){
-               hcd+="\t"+qttype(trn,in[i],WocQtOut::In)+"in_"+in[i]+";\n";
+               pcd+="\t"+qttype(trn,in[i],WocQtOut::In)+"in_"+in[i]+";\n";
                if(i){inlist+=",";clist+=",";}
                inlist+="const "+qttype(trn,in[i],WocQtOut::In)+"&a"+in[i];
                clist+="a"+in[i];
        }
        for(int i=0;i<out.size();i++)
-               hcd+="\t"+qttype(trn,out[i],WocQtOut::Out)+"out_"+out[i]+";\n";
-       hdr.write(hcd.toAscii());
+               pcd+="\t"+qttype(trn,out[i],WocQtOut::Out)+"out_"+out[i]+";\n";
        
        //query method decl
-       hdr.write(QByteArray("\tvoid netquery();\n"));
+       hcd+="\tvoid netquery();\n\tvoid asyncnetquery();\n";
+       hcd+="\tQByteArray encodeData();\n\tvoid decodeData(QByteArray);\n";
+       hcd+="  protected:\n\tvirtual void endQuery();\n";
        
        //global interface code
        QString sif="  "+cn+" query"+trn.name()+"("+inlist+")\n\t";
        sif+="{return "+cn+"::query("+clist+(clist!=""?",":"")+"name());}\n";
-       m_iface.write(sif.toAscii());
-               
+       m_iface.write(sif.toAscii());sif.clear();
+       
        //create constructors
        if(inlist!="")inlist+=",";
        inlist+="QString iface";
@@ -90,145 +109,187 @@ void WocQtClientTransaction::newTransaction(const WocTransaction&trn)
        clist+="iface";
        QString defparm="=\""+WocProcessor::instance()->projectName()+"\"";
        //define parametric constructor
-       hcd="  public:\n";
-       hcd+="\t"+cn+"("+inlist+defparm+");\n";
+       hcd+="\t"+cn+"("+inlist+");\n";
        //parametric constructor implementation
        scd+=cn+"::"+cn+"("+inlist+")\n\t:"+m_transbase+"(iface)\n{\n";
+       scd+="\tnew "+cnp+"(this);\n";
        for(int i=0;i<in.size();i++){
-               scd+="\tin_"+in[i]+"=a"+in[i]+";\n";
+               scd+="\tp->in_"+in[i]+"=a"+in[i]+";\n";
        }
        scd+="}\n\n";
+       //decl default constructor
+       hcd+="  public:\n";
+       hcd+="\t"+cn+"();\n";
+       scd+=cn+"::"+cn+"()\n{\n\tnew "+cnp+"(this);\n}\n\n";
        //decl copy constructor
        hcd+="\t"+cn+"(const "+cn+"&);\n";
        //copy constructor implementation
        scd+=cn+"::"+cn+"(const "+cn+"&t)\n\t:"+m_transbase+"(t)\n{\n";
-       for(int i=0;i<in.size();i++){
-               scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
-       }
+       scd+="\tt.p->attach(this);\n";
        scd+="}\n\n";
        //decl copy operator
        hcd+="\t"+cn+"& operator=(const "+cn+"&);\n";
        //copy operator implemented
        scd+=cn+"& "+cn+"::operator=(const "+cn+"&t)\n{\n";
        scd+="\t"+m_transbase+"::operator=(t);\n";
-       for(int i=0;i<in.size();i++){
-               scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
-       }
-       for(int i=0;i<out.size();i++){
-               scd+="\tout_"+out[i]+"=t.out_"+out[i]+";\n";
-       }
+       scd+="\tp->detach(this);t.p->attach(this);\n";
        scd+="\treturn *this;\n}\n\n";
        
+       //destructor
+       hcd+="\t~"+cn+"();\n";
+       scd+=cn+"::~"+cn+"()\n{\n\tp->detach(this);\n}\n\n";
+       
        //query method implemented
        scd+="void "+cn+"::netquery()\n{\n";
-       scd+="\tLog log(this,\""+trn.name()+"\");\n";
-       scd+="\tQDomDocument doc;QDomElement root=doc.createElement(\"WobRequest-"+trn.name()+"\");\n";
-       scd+="\tQDomElement tmp;\n";
-       scd+="\tWInterface *iface=WInterface::instance(d->m_iface);\n";
-       scd+="\tif(iface==0){d->m_errtype=\"_iface\";d->m_errstr=\"interface not found\";d->m_stage=Error;log.setError(d->m_errstr);return;}\n";
+       scd+="\tWTransaction::Log log(this,\""+trn.name()+"\");\n";
+       scd+="\tQByteArray enc=encodeData();\n";
+       scd+="\tif(enc.isEmpty()){\n\t\temit finished();\n\t\treturn;\n\t}\n";
+       scd+="\texecuteQuery(\""+trn.name()+"\",enc);\n";
+       scd+="}\n";
+       //async query method implemented
+       scd+="void "+cn+"::asyncnetquery()\n{\n";
+       scd+="\tnew WTransaction::Log(this,\""+trn.name()+"\");\n";
+       scd+="\tQByteArray enc=encodeData();\n";
+       scd+="\tif(enc.isEmpty()){\n\t\temit finished();\n\t\treturn;\n\t}\n";
+       scd+="\tstartQuery(\""+trn.name()+"\",enc);\n";
+       scd+="}\n";
        //encode input
+       scd+="QByteArray "+cn+"::encodeData()\n{\n";
        scd+=trnInput(trn);
-       scd+="\tdoc.appendChild(root);\n";
-       //query
-       scd+="\tQByteArray rba=executeQuery(\""+trn.name()+"\",doc.toByteArray());\n";
+       scd+="}\n";
        //decode output
+       scd+="void "+cn+"::decodeData(QByteArray rba)\n{\n";
        scd+=trnOutput(trn);
        scd+="}\n";
-       hdr.write(hcd.toAscii());
-       src.write(scd.toAscii());
+       scd+="void "+cn+"::endQuery()\n{\n";
+       scd+="\tdecodeData(d->m_rspdata.trimmed());\n";
+       scd+="\temit finished();\n}\n";
        
        
        //create getters
-       hcd="";
        for(int i=0;i<out.size();i++){
                QString tp=qttype(trn,out[i],WocQtOut::Out);
-               hcd+="\t"+tp+" get"+out[i]+"(){return out_"+out[i]+";}\n";
+               hcd+="\t"+tp+" get"+out[i]+"();\n";
+               scd+=tp+" "+cn+"::get"+out[i]+"(){return p->out_"+out[i]+";}\n";
        }
+       
        //create queries
-       scd="";
        hcd+="\tstatic "+cn+" query("+inlist+defparm+");\n";
        scd+=cn+" "+cn+"::query("+inlist+")\n{\n";
        scd+="\t"+cn;
-       if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;";
+       if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;\n";
        scd+="\tr.netquery();\n\treturn r;\n}\n";
+       hcd+="\tstatic "+cn+" asyncQuery("+inlist+defparm+");\n";
+       scd+=cn+" "+cn+"::asyncQuery("+inlist+")\n{\n";
+       scd+="\t"+cn;
+       if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;\n";
+       scd+="\tr.asyncnetquery();\n\treturn r;\n}\n";
        
-       //lead out
+       //button up
+       hcd+="};\n\n";
+       pcd+="};\n\n";
+       
+       //write code
+       hdr.write(hdi.toAscii());
        hdr.write(hcd.toAscii());
+//     hdp.write(pcd.toAscii());
+       src.write(sri.toAscii());
+       src.write(pcd.toAscii());
        src.write(scd.toAscii());
-       hdr.write(QByteArray("\n};\n"));
+       
+       //lead out
        hdr.write(QByteArray(HDREND).replace("%",cn.toAscii()));
+//     hdp.write(QByteArray(HDREND).replace("%",cnp.toAscii()));
        src.write(QByteArray(SRCEND).replace("%",cn.toAscii()));
 }
 
 QString WocQtClientTransaction::trnInput(const WocTransaction&trn)
 {
-       QString code="\t/*start of input encoding*/\n";
+       QString code;
+       code+="\tWTransaction::LogWrap log(this,\""+trn.name()+"\");\n";
+       code+="\tQDomDocument doc;QDomElement root=doc.createElement(\"WobRequest-"+trn.name()+"\");\n";
+       code+="\tQDomElement tmp;\n";
+       code+="\tWInterface *iface=WInterface::instance(d->m_iface);\n";
+       code+="\tif(iface==0){\n";
+       code+="\t\td->m_errtype=\"_iface\";d->m_errstr=\"interface not found\";\n";
+       code+="\t\td->m_stage=Error;log.setError(d->m_errstr);\n\t\treturn QByteArray();\n\t}\n";
+       code+="\t/*start of input encoding*/\n";
        QStringList sl=trn.inputNames();
        for(int i=0;i<sl.size();i++){
                QString t=trn.inputType(sl[i]);
                if(trn.isAttributeType(t)){
-                       code+="\troot.setAttribute(\""+sl[i]+"\",in_"+sl[i];
+                       code+="\troot.setAttribute(\""+sl[i]+"\",p->in_"+sl[i];
                        if(trn.isBoolType(t))
                                code+="?\"true\":\"false\"";
                        code+=");\n";
                }else{
                        if(trn.isListType(t)){
                                QString pt=trn.plainType(t);
-                               code+="\tfor(int i=0;i<in_"+sl[i]+".size();i++){\n";
+                               code+="\tfor(int i=0;i<p->in_"+sl[i]+".size();i++){\n";
                                if(trn.isObjectType(t)){
-                                       code+="\t\ttmp=in_"+sl[i]+"[i].toXml(doc,\""+sl[i]+"\");\n";
+                                       code+="\t\ttmp=p->in_"+sl[i]+"[i].toXml(doc,\""+sl[i]+"\");\n";
                                }else{
                                        code+="\t\ttmp=doc.createElement(\""+sl[i]+"\");\n";
                                        code+="\t\ttmp.appendChild(doc.createTextNode(";
                                        if(trn.isIntType(t))
-                                               code+="QString::number(in_"+sl[i]+"[i])";
+                                               code+="QString::number(p->in_"+sl[i]+"[i])";
                                        else
                                        if(trn.isBoolType(t))
-                                               code+="in_"+sl[i]+"[i]?\"true\":\"false\"";
+                                               code+="p->in_"+sl[i]+"[i]?\"true\":\"false\"";
                                        else
                                        if(trn.isBlobType(t))
-                                               code+="in_"+sl[i]+".toBase64()";
+                                               code+="p->in_"+sl[i]+".toBase64()";
                                        else
-                                               code+="in_"+sl[i]+"[i]";
+                                               code+="p->in_"+sl[i]+"[i]";
                                        code+="));\n";
                                }
                                code+="\t\troot.appendChild(tmp);\n";
                                code+="\t}\n";
                        }else{
                                if(trn.isObjectType(t)){
-                                       code+="\troot.appendChild(in_"+sl[i]+".toXml(doc,\""+sl[i]+"\"));\n";
+                                       code+="\troot.appendChild(p->in_"+sl[i]+".toXml(doc,\""+sl[i]+"\"));\n";
                                }else{
                                        code+="\ttmp=doc.createElement(\""+sl[i]+"\");\n";
                                        code+="\ttmp.appendChild(doc.createTextNode(";
                                        if(trn.isIntType(t))
-                                               code+="QString::number(in_"+sl[i]+")";
+                                               code+="QString::number(p->in_"+sl[i]+")";
                                        else
                                        if(trn.isBlobType(t))
-                                               code+="in_"+sl[i]+".toBase64()";
+                                               code+="p->in_"+sl[i]+".toBase64()";
                                        else
-                                               code+="in_"+sl[i];
+                                               code+="p->in_"+sl[i];
                                        code+="));\n\troot.appendChild(tmp);\n";
                                }
                        }
                }
        }
        code+="\t/*end of input encoding*/\n";
+       code+="\tdoc.appendChild(root);\n";
+       code+="\treturn doc.toByteArray();\n";
        return code;
 }
 
 QString WocQtClientTransaction::trnOutput(const WocTransaction&trn)
 {
        QStringList sl=trn.outputNames();
-       QString code="\t/*start of output decoding*/\n";
+       QString code;
+       code+="\tWTransaction::LogWrap log(this,\""+trn.name()+"\");\n";
+       code+="\t/*start of output decoding*/\n";
        //basic XML parsing
-       code+="\tif(rba.isEmpty())return;\n";
-       code+="\tdoc=QDomDocument();\n";
+       code+="\tif(rba.isEmpty()){\n";
+       code+="\t\td->m_stage=Error;d->m_errtype=\"_iface\";\n";
+       code+="\t\td->m_errstr=QCoreApplication::translate(\"WobTransaction\",\"XML result parser error: empty response.\");\n";
+       code+="\t\tlog.setError(d->m_errstr);\n\t\treturn;\n\t}\n";
+       code+="\tQDomDocument doc;\n";
        code+="\tQString emsg;int eln,ecl;\n";
        code+="\tif(!doc.setContent(rba,&emsg,&eln,&ecl)){\n";
-       code+="\t\td->m_stage=Error;d->m_errtype=\"_iface\";d->m_errstr=QString(QCoreApplication::translate(\"WobTransaction\",\"XML result parser error line %1 col %2: %3\")).arg(eln).arg(ecl).arg(emsg);\n\t\tlog.setError(d->m_errstr);\n\t\treturn;\n\t}\n";
-       code+="\troot=doc.documentElement();\n";
+       code+="\t\td->m_stage=Error;d->m_errtype=\"_iface\";\n";
+       code+="\t\td->m_errstr=QString(QCoreApplication::translate(\"WobTransaction\",\"XML result parser error line %1 col %2: %3\")).arg(eln).arg(ecl).arg(emsg);\n";
+       code+="\t\tlog.setError(d->m_errstr);\n\t\treturn;\n\t}\n";
+       code+="\tQDomElement root=doc.documentElement();\n";
        //decide where to go, error handling
-       code+="\tif(d->m_wobstatus!=\"ok\"){\n\t\td->m_stage=Error;d->m_errtype=\"_server\";d->m_errstr=\"unknown server error\";\n";
+       code+="\tif(d->m_wobstatus!=\"ok\"){\n";
+       code+="\t\td->m_stage=Error;d->m_errtype=\"_server\";d->m_errstr=\"unknown server error\";\n";
        code+="\t\tQString terr=root.text().trimmed();\n";
        code+="\t\tif(terr==\"\"){\n\t\t\tlog.setError(d->m_errstr);\n\t\t\treturn;\n\t\t}\n";
        code+="\t\td->m_errtype=root.attribute(\"type\",\"_server\");\n";
@@ -238,7 +299,7 @@ QString WocQtClientTransaction::trnOutput(const WocTransaction&trn)
        for(int i=0;i<sl.size();i++){
                QString t=trn.outputType(sl[i]);
                if(trn.isAttributeType(t)){
-                       code+="\tout_"+sl[i]+"=";
+                       code+="\tp->out_"+sl[i]+"=";
                        if(trn.isBoolType(t))code+="str2bool(";
                        code+="root.attribute(\""+sl[i]+"\")";
                        if(trn.isIntType(t))code+=".toInt()";else
@@ -249,25 +310,25 @@ QString WocQtClientTransaction::trnOutput(const WocTransaction&trn)
                        if(trn.isListType(t)){
                                code+="\tfor(int i=0;i<nl.size();i++){\n";
                                if(trn.isObjectType(t)){
-                                       code+="\t\ttry{out_"+sl[i]+".append("+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(i).toElement()));}catch(WException e){d->m_stage=Error;d->m_errtype=e.component();d->m_errstr=e.error();log.setError(d->m_errstr);}\n";
+                                       code+="\t\ttry{p->out_"+sl[i]+".append("+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(i).toElement()));}catch(WException e){d->m_stage=Error;d->m_errtype=e.component();d->m_errstr=e.error();log.setError(d->m_errstr);}\n";
                                }else if(trn.isIntType(t)){
-                                       code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text().toInt());\n";
+                                       code+="\t\tp->out_"+sl[i]+".append(nl.at(i).toElement().text().toInt());\n";
                                }else if(trn.isBoolType(t)){
-                                       code+="\t\tout_"+sl[i]+".append(str2bool(nl.at(i).toElement().text()));\n";
+                                       code+="\t\tp->out_"+sl[i]+".append(str2bool(nl.at(i).toElement().text()));\n";
                                }else if(trn.isBlobType(t)){
-                                       code+="\t\tout_"+sl[i]+".append(QByteArray::fromBase64(nl.at(i).toElement().text().toAscii()));\n";
+                                       code+="\t\tp->out_"+sl[i]+".append(QByteArray::fromBase64(nl.at(i).toElement().text().toAscii()));\n";
                                }else{//can only be string
-                                       code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text());\n";
+                                       code+="\t\tp->out_"+sl[i]+".append(nl.at(i).toElement().text());\n";
                                }
                                code+="\t}\n";
                        }else{
                                code+="\tif(nl.size()>0){\n";
                                if(trn.isObjectType(t)){
-                                       code+="\t\ttry{out_"+sl[i]+"="+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(0).toElement());}catch(WException e){d->m_stage=Error;d->m_errtype=e.component();d->m_errstr=e.error();log.setError(d->m_errstr);}\n";
+                                       code+="\t\ttry{p->out_"+sl[i]+"="+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(0).toElement());}catch(WException e){d->m_stage=Error;d->m_errtype=e.component();d->m_errstr=e.error();log.setError(d->m_errstr);}\n";
                                }else if(trn.isBlobType(t)){
-                                       code+="\t\tout_"+sl[i]+"=QByteArray::fromBase64(nl.at(0).toElement().text().toAscii());\n";
+                                       code+="\t\tp->out_"+sl[i]+"=QByteArray::fromBase64(nl.at(0).toElement().text().toAscii());\n";
                                }else{//can only be string
-                                       code+="\t\tout_"+sl[i]+"=nl.at(0).toElement().text();\n";
+                                       code+="\t\tp->out_"+sl[i]+"=nl.at(0).toElement().text();\n";
                                }
                                code+="\t}\n";
                        }
index ad3dcec..d95382b 100644 (file)
@@ -140,6 +140,22 @@ void WocQtOut::addFile(QString bn)
        wrap.write(QString("#include \"src"+bn+".h\"\n").toAscii());
 }
 
+void WocQtOut::addFile(WocQtOut::FileType ft,QString fn)
+{
+       QString code;
+       switch(ft){
+               case Header:code="HEADERS+="+m_subdir+"/"+fn+"\n";break;
+               case Source:code+="SOURCES+="+m_subdir+"/"+fn+"\n";break;
+       }
+       m_pri.write(code.toAscii());
+}
+
+void WocQtOut::addProjectLine(QString ln)
+{
+       m_pri.write(QString(ln+"\n").toAscii());
+}
+
+
 QString WocQtOut::qttype(const WocClass&cls,QString p,bool dolist)
 {
        QString r;
index 77781c2..45deeae 100644 (file)
@@ -58,6 +58,12 @@ class WocQtOut:public WocOutput
                MFile m_pri,m_iface,m_ifacecpp,m_hdr;
                bool m_clean;
                
+               ///types of files generated
+               enum FileType{
+                       Header,
+                       Source
+               };
+               
                /**helper: generate a proper Qt type for a property*/
                QString qttype(const WocClass&,QString,bool dolist=true);
                enum InOut{In,Out};
@@ -65,8 +71,15 @@ class WocQtOut:public WocOutput
                QString qttype(const WocTransaction&,QString,InOut);
                /**helper: generate a proper QT type for a transaction variable, WO* only */
                QString qtobjtype(const WocTransaction&,QString,InOut);
-               /**helper: adds a file to the project file*/
+               /**helper: adds a file to the project file
+               \param basename the class name to add*/
                void addFile(QString basename);
+               /**helper: adds a file to the project file
+               \param fname the file name to add
+               \param kind the type of file*/
+               void addFile(FileType kind,QString fname);
+               /**helper: add a line to the project file*/
+               void addProjectLine(QString);
                
                WocQtClass*qclass;
                WocQtTable*qtable;