From 91dc937a4bde648370ecd231f3ac01b0aa269c8f Mon Sep 17 00:00:00 2001 From: konrad Date: Fri, 15 Jan 2010 18:56:08 +0000 Subject: [PATCH] move woc git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@420 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- woc/htmlout.cpp | 390 +++++++++++++++++ woc/htmlout.h | 45 ++ woc/mfile.cpp | 85 ++++ woc/mfile.h | 46 ++ woc/phpout.cpp | 1103 +++++++++++++++++++++++++++++++++++++++++++++++ woc/phpout.h | 97 +++++ woc/processor.cpp | 1223 +++++++++++++++++++++++++++++++++++++++++++++++++++++ woc/processor.h | 462 ++++++++++++++++++++ woc/qtout.cpp | 821 +++++++++++++++++++++++++++++++++++ woc/qtout.h | 64 +++ woc/woc.cpp | 36 ++ woc/woc.pro | 30 ++ 12 files changed, 4402 insertions(+), 0 deletions(-) create mode 100644 woc/htmlout.cpp create mode 100644 woc/htmlout.h create mode 100644 woc/mfile.cpp create mode 100644 woc/mfile.h create mode 100644 woc/phpout.cpp create mode 100644 woc/phpout.h create mode 100644 woc/processor.cpp create mode 100644 woc/processor.h create mode 100644 woc/qtout.cpp create mode 100644 woc/qtout.h create mode 100644 woc/woc.cpp create mode 100644 woc/woc.pro diff --git a/woc/htmlout.cpp b/woc/htmlout.cpp new file mode 100644 index 0000000..3ef5503 --- /dev/null +++ b/woc/htmlout.cpp @@ -0,0 +1,390 @@ +// +// C++ Implementation: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "htmlout.h" + +#include +#include + +WocHtmlOut::WocHtmlOut(QDomElement&el) +{ + qDebug("Info: creating Html Output Generator."); + WocProcessor*woc=WocProcessor::instance(); + m_basedir=woc->baseDir()+"/"+el.attribute("sourceDir","."); + m_subdir=el.attribute("subDir","htmlwob"); + bool clean=str2bool(el.attribute("clean","0")); + //cleanup directory (remove normal files, assume remainder is harmless) + QDir d(m_basedir+"/"+m_subdir); + if(d.exists() && clean){ + QStringList ent=d.entryList(QDir::Files); + for(int i=0;i\n\n")); + m_index.write(QByteArray("Project Index\n")); + + m_index.write(QByteArray("\n")); + //write project info + QString inf="

Project "+woc->projectName()+"

\n"; + inf+="Human Readable Version: "+woc->verHR()+"
"; + inf+="Communication Layer Version: "+woc->verComm()+"
"; + inf+="Minimum Compatible Version: "+woc->verNeedComm()+"

"; + + inf+="SVN Repository URL: "+woc->svnRepositoryUrl()+"
"; + inf+="SVN Repository Root: "+woc->svnRepositoryRoot()+"
"; + inf+="SVN Revision: "+woc->svnRevision()+"

"; + + inf+="Database Instance Object: "+woc->dbInst()+"
"; + inf+="Database Schema Object: "+woc->dbSchema()+"
"; + inf+="Database Schema Version: "+woc->dbVersion()+"

"; + + m_index.write(inf.toAscii()); + + //write global docu + QStringList dcs=woc->docStrings(); + for(int i=0;i\n"; + m_index.write(inf.toAscii()); + } +} + +WocHtmlOut::~WocHtmlOut(){} + +void WocHtmlOut::finalize() +{ + //TODO: write index table content + m_index.write(QByteArray("

Index

\n")); + m_index.write(QByteArray("\n")); + m_index.write(QByteArray("

Classes

Transactions

Tables

    \n")); + QStringList sl=WocProcessor::instance()->classNames(); + QString s; + qSort(sl); + for(int i=0;i"+sl[i]+"\n"; + m_index.write(s.toAscii()); + + m_index.write(QByteArray("
    ")); + sl=WocProcessor::instance()->transactionNames(); + s=""; + qSort(sl); + for(int i=0;i"+sl[i]+"\n"; + m_index.write(s.toAscii()); + + m_index.write(QByteArray("
    ")); + sl=WocProcessor::instance()->tableNames(); + s=""; + qSort(sl); + for(int i=0;i"+sl[i]+"\n"; + m_index.write(s.toAscii()); + + m_index.write(QByteArray("
\n")); + + m_index.write(QByteArray("\n\n")); + m_index.close(); +} + +void WocHtmlOut::newTable(const WocTable&tbl) +{ + QString cn=tbl.name(); + QFile htm(m_basedir+"/"+m_subdir+"/table-"+cn+".html"); + if(!htm.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create html file for table %s.",cn.toAscii().data()); + emit errorFound(); + return; + } + //lead in + htm.write(QString("Table "+cn+"\n").toAscii()); + + QString hcd; + //table declaration + hcd+="

Table "+cn+"

\n"; + + if(tbl.isAuditable()){ + hcd+="

This table is audited, see " + +tbl.name()+"_audit for details.

\n"; + } + + QStringList td=tbl.docStrings(); + for(int i=0;i\n"; + + hcd+="\n"; + QStringList cl=tbl.columns(); + for(int i=0;i\n"; + } + hcd+="
Column NameTypePropertiesDocu
"+tbl.columnType(cl[i])+""; + if(tbl.columnIsPrimary(cl[i])) + hcd+="Primary-Key "; + if(tbl.columnIsNull(cl[i])) + hcd+="NULL-able "; + if(tbl.columnHasDefault(cl[i])) + hcd+="default=\""+tbl.columnDefault(cl[i])+"\" "; + if(tbl.columnIsForeign(cl[i])){ + QStringList cf=tbl.columnForeign(cl[i]).split(":"); + hcd+="Foreign-Key="+cf[0]+"("+cf[1]+") "; + } + if(tbl.columnIsIndexed(cl[i])) + hcd+="Indexed "; + if(tbl.columnIsUnique(cl[i])) + hcd+="Unique"; + hcd+=""+tbl.columnDoc(cl[i])+"
\n"; + + //enums + for(int i=0;ilst=tbl.columnEnums(cl[i]); + if(lst.size()>0){ + hcd+="

Enum for column "+cl[i]+"

\n
    \n"; + for(int j=0;j0){ + hcd+="

    Foreign Getters

    \n
      "; + for(int i=0;i >pre=tbl.presets(); + if(pre.size()>0){ + hcd+="

      Presets

      \n\n"; + cl=tbl.columns(); + for(int i=0;i"; + hcd+="\n"; + for(int i=0;iClass "+cn+"\n").toAscii()); + + QString hcd; + //class declaration + hcd+="

      "; + if(cls.isAbstract(""))hcd+="Abstract "; + hcd+="Class "+cn+"

      \n"; + + //conditional abstract + QStringList ab=cls.abstractLangs(); + if(ab.size()>0){ + hcd+="

      The class is conditionally abstract in: "; + for(int i=0;i\n"; + htm.write(hcd.toAscii()); + + //enums + classEnums(cls,htm); + + //properties + classProperties(cls,htm); + + //mappings + classMappings(cls,htm); + + //lead out + htm.write(QByteArray("\n")); +} + +void WocHtmlOut::classEnums(const WocClass&cls,QFile&hdr) +{ + QStringList k=cls.enumTypes(); + if(k.size()==0)return; + QString hcd="

      Enums

      \n"; + for(int i=0;i\n"; + hcd+="
      "; + hcd+="\n"; + QListev=cls.enumValues(k[i]); + for(int j=0;j\n"; + } + hcd+="
      SymbolValueDocu
      "+QString::number(ev[j].val) + +""+ev[j].doc+"
      \n"; + } + hdr.write(hcd.toAscii()); +} + +void WocHtmlOut::classProperties(const WocClass&cls,QFile&hdr) +{ + QStringList k=cls.propertyNames(); + if(k.size()==0)return; + QString hcd; + //declare members + hcd="

      Properties

      \n
        \n"; + for(int i=0;i"; + hcd+=cls.propertyType(k[i]); + if(cls.propertyIsObject(k[i])) + hcd+=""; + hcd+=")"; + QString d=cls.propDoc(k[i]); + if(d!="")hcd+="
        "+d; + hcd+="\n"; + } + hcd+="
      \n"; + //write + hdr.write(hcd.toAscii()); +} + +void WocHtmlOut::classMappings(const WocClass&cls,QFile&hdr) +{ + QStringList k=cls.mappingTables(); + if(k.size()==0)return; + QString hcd; + for(int i=0;i"+k[i]+"\n"; + hcd+="\n"; + hcd+="\n"; + QMap map=cls.mapping(k[i]); + QStringList k2=map.keys(); + for(int j=0;j\n"; + } + hcd+="
      PropertyColumn
      "+map[k2[j]]+"
      \n"; + } + + hdr.write(hcd.toAscii()); +} + +void WocHtmlOut::newTransaction(const WocTransaction&trn) +{ + QString cn=trn.name(); + QFile htm(m_basedir+"/"+m_subdir+"/trn-"+cn+".html"); + if(!htm.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create HTML file for transaction %s.",cn.toAscii().data()); + emit errorFound(); + return; + } + //basics + QStringList in=trn.inputNames(); + QStringList out=trn.outputNames(); + QStringList doc=trn.docStrings(); + //lead in + QString hcd; + hcd="Transaction "+cn+"\n

      Transaction "+cn+"

      \n"; + //auth mode + hcd+="

      Authentication mode: "; + switch(trn.authMode()){ + case WocTransaction::Checked:hcd+="Checked (known user, must have the privilege)";break; + case WocTransaction::Auth:hcd+="Authenticated (known user, any/no privileges)";break; + case WocTransaction::Open:hcd+="Open (unauthenticated, any user)";break; + default:hcd+="Ooops. Unknown Mode.";break; + } + hcd+="

      \n"; + //docu + for(int i=0;i\n"; + //in/out + hcd+="

      Inputs:

      \n
        \n"; + for(int i=0;i"; + hcd+=t; + if(trn.isObjectType(t)) + hcd+=""; + //add docu + t=trn.inputDoc(in[i]); + if(t!="")hcd+="
        "+t; + hcd+="\n"; + } + hcd+="
      \n

      Outputs:

      \n
        \n"; + for(int i=0;i"; + hcd+=t; + if(trn.isObjectType(t)) + hcd+=""; + //add docu + t=trn.outputDoc(out[i]); + if(t!="")hcd+="
        "+t; + hcd+="\n"; + } + hcd+="
      \n"; + //privileges + QStringList pri=trn.privileges(); + if(pri.size()){ + hcd+="

      Privileges

      \n
        \n"; + for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_HTMLOUT_H +#define WOC_HTMLOUT_H + +#include "processor.h" + +#include + +class QDomElement; + +class WocHtmlOut:public WocOutput +{ + public: + WocHtmlOut(QDomElement&); + ~WocHtmlOut(); + protected: + virtual void finalize(); + virtual void newClass(const WocClass&); + virtual void newTable(const WocTable&); + virtual void newTransaction(const WocTransaction&); + private: + QString m_basedir,m_subdir; + QFile m_index; + + /**helper: generate enums for classes*/ + void classEnums(const WocClass&,QFile&); + /**helper: generate properties*/ + void classProperties(const WocClass&,QFile&); + /**helper: generate mappings*/ + void classMappings(const WocClass&,QFile&); + +}; + +#endif diff --git a/woc/mfile.cpp b/woc/mfile.cpp new file mode 100644 index 0000000..e6c0c9a --- /dev/null +++ b/woc/mfile.cpp @@ -0,0 +1,85 @@ +// +// C++ Implementation: mfile +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2010 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "mfile.h" + +#include + +//static +QMap MFile::touched; + +MFile::MFile(QString n,QObject*parent):QFile(n+",new",parent),name(n){isopen=false;} +MFile::MFile(QObject *parent):QFile(parent){isopen=false;} +MFile::~MFile() +{ + if(isopen)close(); +} + +void MFile::close() +{ +// qDebug("Info: closing %s",name.toAscii().data()); + //compare + bool ident=false; + if(isopen){ + QFile::close(); + QFile::open(QIODevice::ReadOnly); + QByteArray here=readAll(); + QFile there(name); + if(there.open(QIODevice::ReadOnly)){ + ident=(here == there.readAll()); + there.close(); + } + } + //actual close + QFile::close(); + //move + if(isopen){ + isopen=false; + if(ident){ + //if identical: remove new version to preserve file time + remove(); + }else{ + //if not identical: use new version, remove old one + QFile(name).remove(); + QFile(name+",new").rename(name); + } + } +} + +void MFile::setFileName(QString n) +{ + name=n; + QFile::setFileName(n+",new"); +} + +bool MFile::open(QIODevice::OpenMode m) +{ + isopen=QFile::open(m); + if(isopen){ + //remember it + QFileInfo fi(name); + QString p=fi.absolutePath(); + QString f=fi.fileName(); + if(!touched.contains(p))touched.insert(p,QStringList()); + if(!touched[p].contains(f))touched[p]<, (C) 2010 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_MFILE_H +#define WOC_MFILE_H + +#include +#include +#include + +/**overwrites QFile to only generate a file if its new version differs from an existing one, it creates a temporary file with ",new" added to the file name; additionally it records all file names that it touches; +this is not a complete implementation - just enough for woc*/ +class MFile:public QFile +{ + public: + MFile(QString name,QObject*parent=0); + MFile(QObject *parent=0); + ~MFile(); + + virtual void close(); + virtual bool open(QIODevice::OpenMode m); + + QString fileName()const{return name;} + void setFileName(QString n); + + static bool touchedFile(QString); + private: + //flag to show whether file is open + bool isopen; + //original name of the file + QString name; + + //stores touched files + static QMap touched; +}; + +#endif diff --git a/woc/phpout.cpp b/woc/phpout.cpp new file mode 100644 index 0000000..5ccb84b --- /dev/null +++ b/woc/phpout.cpp @@ -0,0 +1,1103 @@ +// +// C++ Implementation: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "phpout.h" + +#include +#include + +static const QByteArray PHPSTART(""); + +static const QByteArray SCHEMASTART("class WobSchema extends WobSchemaBase\n{\nfunction __construct(){\n"); +static const QByteArray SCHEMAEND("}};\n"); + +static const QByteArray TRANSACTCLASS("class WobTransaction extends WobTransactionBase\n{\n"); +static const QByteArray TRANSACTSTART(" static public function handle(){switch(WobTransactionBase::getTransactionName()){\n"); +static const QByteArray TRANSACTEND("\tdefault:WobTransactionBase::noSuchTransaction();break;\n }}\n"); + +WocPHPServerOut::WocPHPServerOut(const QDomElement&el) +{ + qDebug("Info: creating PHP Server Output Generator."); + m_basedir=WocProcessor::instance()->baseDir()+"/"+el.attribute("sourceDir","."); + m_subdir=el.attribute("subDir","phpwob"); + m_fileext=el.attribute("extension",".inc"); + QList nl=elementsByTagName(el,"Authenticator"); + if(nl.size()){ + QDomElement el2=nl.at(0).toElement(); + m_isauth=el2.attribute("isAuthenticated","false"); + m_hasrole=el2.attribute("hasRole","false"); + m_username=el2.attribute("userName","\"\""); + m_authinit=el2.attribute("init",""); + }else{ + m_isauth="false"; + m_hasrole="false"; + m_username="\"\""; + } + //cleanup directory (remove normal files, assume remainder is harmless) + QDir d(m_basedir+"/"+m_subdir); + if(d.exists() && str2bool(el.attribute("clean","0"))){ + QStringList ent=d.entryList(QDir::Files); + for(int i=0;isversion=\""+WocProcessor::instance()->dbVersion()+"\";\n").toAscii()); + addLoad("WobSchema","schema"); + //create Transaction file + m_transact.setFileName(m_basedir+"/"+m_subdir+"/transaction"+m_fileext); + if(!m_transact.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: PHP Server Generator - cannot create transaction processor file."); + emit errorFound(); + return; + } + m_transact.write(PHPSTART); + m_transact.write(TRANSACTCLASS); + transInfo(); + m_transact.write(TRANSACTSTART); + addLoad("WobTransaction","transaction"); +} + +void WocPHPServerOut::transInfo() +{ + WocProcessor*woc=WocProcessor::instance(); + m_transact.write(QString(" static public function commVersion(){return \""+woc->verComm()+"\";}\n").toAscii()); + m_transact.write(QString(" static public function needCommVersion(){return \""+woc->verNeedComm()+"\";}\n").toAscii()); + m_transact.write(QString(" static public function version(){return \""+woc->verHR()+"\";}\n").toAscii()); + m_transact.write(QString(" static public function svnVersion(){return \""+woc->svnRevision()+"\";}\n\n").toAscii()); + m_transact.write(QString(" static public function svnRepositoryRoot(){return \""+woc->svnRepositoryRoot()+"\";}\n\n").toAscii()); + m_transact.write(QString(" static public function svnRepositoryUrl(){return \""+woc->svnRepositoryUrl()+"\";}\n\n").toAscii()); +} + +void WocPHPServerOut::transInfo2() +{ + WocProcessor*woc=WocProcessor::instance(); + //transaction names + QString code=" static public function transactionNames(){\n\treturn array("; + QStringList tns=woc->transactionNames(); + for(int i=0;iprivilegeNames(); + for(int i=0;idbInst(); + //DB query + code+="){\n\tglobal "+dbi+";\n\t$res="+dbi+"->select(\""+tbl.name()+"\",\"*\",\""; + for(int i=0;iescapeColumn(\""+tbl.name()+"\",\""+pcols[i]+"\",$"+pcols[i]+").\""; + } + code+="\");\n"; + //check result + code+="\tif($res===false)return false;\n\tif(count($res)<1)return false;\n\telse return new WT"+tbl.name()+"($res[0],true);\n}\n\n"; + + //static get selection + code+="public static function selectFromDB($where=\"\",$orderby=\"\"){\n\tglobal "+dbi+";\n\t$res="+dbi+"->select(\""+tbl.name()+"\",\"*\",$where,$orderby);\n\tif($res===false || count($res)<1)return array();\n\t"; + code+="$r=array();\n\tforeach($res as $row)\n\t\t$r[]=new WT"+tbl.name()+"($row,true);\n\treturn $r;\n}\n\n"; + + //go through columns, generate specific code + for(int i=0;iescapeColumn(\""+foreign[0]+"\",\""+foreign[1]+"\",$this->"+cols[i]+"));\n}\n\n"; + } + //implement enum check for set method of enum columns + if(tbl.columnType(cols[i]).startsWith("enum")){ + code+="protected function verifyValue"+cols[i]+"($v){if(false"; + QListens=tbl.columnEnums(cols[i]); + QListenvs; + for(int j=0;jescapeColumn(\""; + code+=foreign[0]+"\",\""+foreign[1]+"\",$this->"+local+"));\n}\n\n"; + } + + //create enum constants + QListens=tbl.getEnums(); + for(int i=0;idata);\n"; + code+="\treturn $ad->insert();\n}\n"; + } + + //create newKey function + code+="public function newKey(){\n\tparent::newKey();\n"; + for(int i=0;iarray(\""; + code+=tbl.columnType(cols[i])+"\""; + if(!tbl.columnIsNull(cols[i]))code+=",\"notnull\""; + if(tbl.columnIsForeign(cols[i]))code+=",\"foreignkey:"+tbl.columnForeign(cols[i])+"\""; + if(pcols.size()<2 && tbl.columnIsPrimary(cols[i]))code+=",\"primarykey\""; + if(tbl.columnHasDefault(cols[i]))code+=",\"default:"+tbl.columnDefault(cols[i])+"\""; + if(tbl.columnIsIndexed(cols[i]))code+=",\"index\""; + if(tbl.columnIsUnique(cols[i]))code+=",\"unique\""; + code+=")"; + } + if(pcols.size()>=2){ + code+=",\n\t\t\":primarykey\"=>array("; + for(int i=0;i >presets=tbl.presets(); + if(presets.size()>0){ + code+="\t$this->preset[\""+tbl.name()+"\"]=array("; + for(int i=0;i"+presets[i][k[j]]; + } + code+=")"; + } + code+="\n\t);\n"; + } + + //write + m_schema.write(code.toAscii()); + + //create autoloading + addLoad("WT"+tbl.name(),"wt_"+tbl.name()); +} + +void WocPHPServerOut::addLoad(QString cn,QString fn) +{ + QString ld="$AUTOCLASS[\""+cn+"\"]=\""+m_subdir+"/"+fn+m_fileext+"\";\n"; + m_loader.write(ld.toAscii()); +} + +void WocPHPServerOut::newClass(const WocClass&cls) +{ + //cover basics + QString cn=className(cls); + QString cna=abstractClassName(cls); + QString fn="wo_"+cls.name(); + addLoad(cna,fn); + fn=m_subdir+"/"+fn+m_fileext; + QFile tf(m_basedir+"/"+fn); + if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: cannot create PHP object file %s.",fn.toAscii().data()); + emit errorFound(); + return; + } + tf.write(PHPSTART); + + //// + //generate code + QString code="/* TRANSLATOR "+cna+" */\nclass "+cna+" extends "+cls.serverBaseClass()+"{\n\n"; + tf.write(code.toAscii()); + + //property declaration and constructor + tf.write(classConstruct(cls).toAscii()); + + //enums + tf.write(classEnums(cls).toAscii()); + + //properties + tf.write(classProperties(cls).toAscii()); + + //mappings + tf.write(classMappings(cls).toAscii()); + + //serializers + tf.write(classSerializers(cls).toAscii()); + + //de-serializer + tf.write(classDeserializers(cls).toAscii()); + + //end of class + code="\n//end of class\n};\n"; + tf.write(code.toAscii()); + + tf.write(PHPEND); + tf.close(); +} + +QString WocPHPServerOut::classConstruct(const WocClass&cls) +{ + QString code; + QStringList k=cls.propertyNames(); + for(int i=0;iev=cls.enumValues(k[i]); + for(int j=0;jprop_"+k[i]+";}\n"; + //is it a list? + if(cls.propertyIsList(k[i])){ + //lists... + //getters + code+=classPropertyListGetters(cls,k[i]); + //setters + code+=classPropertyListSetters(cls,k[i]); + }else{ + //non-lists... + //getters + code+=classPropertyScalarGetters(cls,k[i]); + //setter + code+=classPropertyScalarSetters(cls,k[i]); + } + } + + return code; +} + +QString WocPHPServerOut::classPropertyValidator(const WocClass&cls,QString prop) +{ + QString code; + code+="static public function validate"+prop+"($value){\n"; + if(cls.propertyIsEnum(prop)){ + QListev=cls.enumValues(cls.propertyPlainType(prop)); + code+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n"; + for(int j=0;jprop_"+prop+";}\n"; + else + if(cls.propertyIsBlob(prop)){ + code+="public function getstrlist_"+prop+"(){\n\t$ret=array();\n"; + code+="\tforeach($this->prop_"+prop+" as $p)$ret[]=base64_encode($this->prop_"+prop+");"; + code+="\treturn $ret;\n}\n"; + }else + if(cls.propertyIsInt(prop)){ + code+="public function getstrlist_"+prop+"(){\n"; + code+="\t$ret=array();\n\tforeach($this->prop_"+prop+" as $p)$ret[]=\"\".$p;\n"; + code+="\treturn $ret;\n}\n"; + }else + if(cls.propertyIsBool(prop)){ + code+="public function getstrlist_"+prop+"(){\n"; + code+="\t$ret=array();\n\tforeach($this->prop_"+prop+" as $p)$ret[]=$p?\"yes\":\"no\";\n"; + code+="\treturn $ret;\n}\n"; + }else + if(cls.propertyIsEnum(prop)){ + code+="public function getstrlist_"+prop+"(){\n"; + code+="\t$ret=array();\n"; + code+="\tforeach($this->prop_"+prop+" as $p)switch($p){\n"; + QList ev=cls.enumValues(cls.propertyPlainType(prop)); + for(int j=0;jprop_"+prop+"=array();}\n"; + QString acode;//body of add_ function, see below + code+="public function set"+prop+"(array $values){\n"; + if(cls.propertyIsEnum(prop)){ + QListev=cls.enumValues(cls.propertyPlainType(prop)); + code+="\t$prop=array();\n"; + code+="\tforeach($values as $value){\n"; + code+="\t\tif(is_numeric($value)){\n\t\t\t$value=$value+0;\n"; + acode+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n"; + for(int j=0;jprop_"+prop+";}\n"; + else + if(cls.propertyIsBlob(prop)) + code+="public function getstr_"+prop+"(){return base64_encode($this->prop_"+prop+");}\n"; + else + if(cls.propertyIsInt(prop)) + code+="public function getstr_"+prop+"(){return \"\".$this->prop_"+prop+";}\n"; + else + if(cls.propertyIsBool(prop)) + code+="public function getstr_"+prop+"(){return $this->prop_"+prop+"?\"yes\":\"no\";}\n"; + else + if(cls.propertyIsEnum(prop)){ + code+="public function getstr_"+prop+"(){\n\tswitch($this->prop_"+prop+"){\n"; + QList ev=cls.enumValues(cls.propertyPlainType(prop)); + for(int j=0;jev=cls.enumValues(cls.propertyPlainType(prop)); + code+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n"; + for(int j=0;jprop_"+prop+"=true;else\n"; + code+="\tif($value==\"no\")$this->prop_"+prop+"=false;\n\telse return false;\n"; + code+="\treturn true;\n"; + }else + if(cls.propertyIsString(prop)||cls.propertyIsBlob(prop)) + code+="\t$this->prop_"+prop+"=\"\".$value;\n\treturn true;\n"; + //TODO: special handling for astring + //TODO: do something about Blob + else + if(cls.propertyIsObject(prop)){ + code+="\tif(is_a($value,\"WO"+cls.propertyPlainType(prop)+"\")){\n"; + code+="\t\t$this->prop_"+prop+"=$value;\n"; + code+="\t\treturn true;\n\t}\n"; + }else{ + qDebug("Warning: unable to generate setter for class %s property %s: unknown type.",cls.name().toAscii().data(),prop.toAscii().data()); + code+="\treturn false;\n"; + } + code+="}\n"; + + return code; +} + +QString WocPHPServerOut::classSerializers(const WocClass&cls) +{ + QString code; + //toString function (wraps toXml) + code+="\npublic function toString(){\n\t$xml=new DomDocument;\n"; + code+="\t$xml->appendChild($this->toXml($xml));\n\treturn $xml->saveXml();\n}\n"; + //toXml function: + code+="public function toXml($xml,$elementname=\""+cls.name()+"\"){\n"; + code+="\t$root=$xml->createElement($elementname);\n"; + //add properties + QStringList p=cls.propertyNames(); + for(int j=0;jtextContent));\n"; + }else{ + code+="\t\t$data->add_"+k[i]+"($el->textContent);\n"; + } + code+="\t}\n"; + }else{ + if(cls.propertyIsObject(k[i])){ + code+="\tforeach(WObject::elementsByTagName($elem,\""+k[i]+"\") as $el){\n"; + code+="\t\t$data->set"+k[i]+"(WO"+cls.propertyPlainType(k[i])+"::fromXml($xml,$el));\n"; + code+="\t}\n"; + }else + if(cls.propertyIsAttribute(k[i])){ + code+="\tif($elem->hasAttribute(\""+k[i]+"\"))\n"; + code+="\t\t$data->set"+k[i]+"($elem->getAttribute(\""+k[i]+"\"));\n"; + }else{ + code+="\tforeach(WObject::elementsByTagName($elem,\""+k[i]+"\") as $el){\n"; + if(cls.propertyIsBlob(k[i])) + code+="\t\t$data->set"+k[i]+"(base64_decode($el->textContent));\n"; + else + code+="\t\t$data->set"+k[i]+"($el->textContent);\n"; + code+="\t}\n"; + } + } + } + code+="\treturn $data;\n}\n"; + return code; +} + +QString WocPHPServerOut::classMappings(const WocClass&cls) +{ + //implement mappings + QString code; + QStringList k=cls.mappingTables(); + for(int i=0;itable(k[i]); + //single object mapping + code+="\nstatic public function fromTable"+k[i]+"($table){\n"; + code+="\tif($table === false)return false;\n"; + code+="\t$data=new WO"+cls.name()+"();\n"; + QMapmap=cls.mapping(k[i]); + QStringList mapk=cls.mappingProperties(k[i]); + for(int j=0;j"+map[mapk[j]]+";\n"; + } + code+="\treturn $data;\n}\n"; + //wrapper for multi-object mapping + code+="static public function fromTableArray"+k[i]+"(array $table){\n\t$ret=array();\n"; + code+="\tfor($i=0;$i"+map[mapk[j]]+"!=$this->prop_"+mapk[j]+")\n"; + code+="\t\t$table->"+map[mapk[j]]+"=$this->prop_"+mapk[j]+";\n"; + } + } + code+="\treturn $table;\n}\n"; + } + + return code; +} + +QString WocPHPServerOut::propertyToXml(const WocClass&cls,QString sl) +{ + QString prop=sl.trimmed(); + //is it a list? + if(cls.propertyIsList(prop)){ + //is it a class? + if(cls.propertyIsObject(prop)){ + QString code="\tforeach($this->get"+prop+"() as $o)\n\t\t"; + code+="$root->appendChild($o->toXml($xml,\""+prop+"\"));\n"; + return code; + }else{ + //there is no way to create lists of attributes, hence we always create elements + QString code="\tforeach($this->getstrlist_"+prop+"() as $e)\n\t\t"; + code+="$root->appendChild($xml->createElement(\""+prop+"\",xq($e)));\n"; + return code; + } + } + //non lists: + QString code="\t$p=$this->get"+prop+"();\n\tif($p!==null)"; + //is it an attribute? + if(cls.propertyIsAttribute(prop)) + return code+"\t$root->setAttribute(\""+prop+"\",$this->getstr_"+prop+"());\n"; + //is it an element? + if(cls.propertyIsElement(prop)) + return code+"\t$root->appendChild($xml->createElement(\""+prop+"\",xq($this->getstr_"+prop+"())));\n"; + //is it a class? + if(cls.propertyIsObject(prop)) + return code+"$root->appendChild($p->toXml($xml,\""+prop+"\"));\n"; + //anything else? + qDebug("Warning: end of WocPHPServerOut::propertyToXml - this code should not be reachable."); + return "//internal generator error!\n"; +} + +void WocPHPServerOut::newTransaction(const WocTransaction&trn) +{ + //create file + QString cn=trnClassName(trn); + QString fn="wtr_"+trn.name(); + addLoad(cn,fn); + fn=m_subdir+"/"+fn+m_fileext; + QFile tf(m_basedir+"/"+fn); + if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: cannot create PHP object file %s.",fn.toAscii().data()); + emit errorFound(); + return; + } + tf.write(PHPSTART); + + //// + //generate code + QString code="/* TRANSLATOR "+cn+" */\nclass "+cn+" extends WobTransaction{\n"; + //constructor + code+=trnConstruct(trn); + tf.write(code.toAscii()); + + //request handler: + code="public function handleRequest(){\n"; + + //security handling + switch(trn.authMode()){ + case WocTransaction::Checked: + code+="\t/*security check: authenticated and authorized*/\n"; + code+="\t"+m_authinit+";\n"; + code+="\tif(!"+m_isauth+"||!"+QString(m_hasrole).replace("%","\""+trn.name()+"\"")+")$this->notAuthenticated();\n"; + break; + case WocTransaction::Auth: + code+="\t/*security check: authenticated*/\n"; + code+="\t"+m_authinit+";\n"; + code+="\tif(!"+m_isauth+")$this->notAuthenticated();\n"; + break; + default: + code+="\t/*no security check, open function*/\n"; + break;//none + } + + //parse low level XML + code+="\t/*low level XML parsing*/\n"; + code+="\tglobal $HTTP_RAW_POST_DATA;\n\tif(isset($HTTP_RAW_POST_DATA))$txt=$HTTP_RAW_POST_DATA;else $txt=\"\";\n"; + code+="\t$xml=new DOMDocument;\n\tif(!$xml->loadXML($txt))$this->xmlParserError();\n"; + code+="\t$root=$xml->documentElement;\n"; + + //parse inputs + code+=trnInput(trn); + + //call + if(trn.hasCall("php")){ + code+="\t/*call actual functionality:*/\n"; + code+="\ttry{"+trn.callFunction("php")+"}catch(Exception $e){$this->handleException($e);}\n"; + }else{ + code+="\t/*normally here would be the PHP call, but it is missing from the config*/\n"; + code+="\t$this->abortNotImplemented();\nreturn;\n"; + qDebug("Warning: transaction %s does not have a PHP call!",trn.name().toAscii().data()); + } + + //encode outputs/handle errors + code+=trnOutput(trn); + + code+="}\n"; + tf.write(code.toAscii()); + + //getters/setters + tf.write(trnGetSet(trn).toAscii()); + + //direct execution + tf.write(trnExecute(trn).toAscii()); + + //privileges + tf.write(trnPrivileges(trn).toAscii()); + + //end + code="\n//end of class\n}\n"; + tf.write(code.toAscii()); + tf.write(PHPEND); + tf.close(); + + //// + //generate loader code + code="\tcase \""+trn.name()+"\":$trn=new "+cn+";$trn->handleRequest();break;\n"; + m_transact.write(code.toAscii()); +} + +QString WocPHPServerOut::trnConstruct(const WocTransaction&trn) +{ + QString code="public function __construct(){\n\t$this->ainput=array("; + QStringList sl=trn.inputNames(); + for(int i=0;i"; + if(trn.isListType(trn.inputType(sl[i])))code+="array()"; + else code+="false"; + } + code+=");\n"; + code+="\t$this->tinput=array("; + for(int i=0;i\""; + code+=trn.inputType(sl[i]); + code+="\""; + } + code+=");\n"; + + + code+="\t$this->aoutput=array("; + sl=trn.outputNames(); + for(int i=0;i"; + if(trn.isListType(trn.outputType(sl[i])))code+="array()"; + else code+="false"; + } + code+=");\n"; + code+="\t$this->toutput=array("; + for(int i=0;i\""; + code+=trn.outputType(sl[i]); + code+="\""; + } + code+=");\n}\n"; + return code; +} + +QString WocPHPServerOut::trnInput(const WocTransaction&trn) +{ + QString code="\t/*start of input parsing*/\n"; + code+="\ttry{\n"; + QStringList sl=trn.inputNames(); + for(int i=0;igetAttribute(\""+sl[i]+"\")"; + if(trn.isIntType(t))code+="+0"; + if(trn.isBoolType(t))code+="==\"yes\""; + code+=";\n"; + }else{ + if(trn.isListType(t)){ + QString pt=trn.plainType(t); + code+="\t\tforeach(WObject::elementsByTagName($root,\""+sl[i]+"\") as $el){\n"; + if(trn.isObjectType(t)){ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"][]=WO"+pt+"::fromXml($xml,$el);\n"; + }else if(trn.isBlobType(t)){ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"][]=base64_decode($el->textContent);\n"; + }else{ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"][]=$el->textContent"; + if(trn.isIntType(t))code+="+0"; + if(trn.isBoolType(t))code+="==\"yes\""; + code+=";\n"; + } + code+="\t\t}\n"; + }else{ + code+="\t\tforeach(WObject::elementsByTagName($root,\""+sl[i]+"\") as $el){\n"; + if(trn.isObjectType(t)){ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"]=WO"+t+"::fromXml($xml,$el);\n"; + }else if(trn.isBlobType(t)){ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"]=base64_decode($el->textContent);\n"; + }else{ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"]=$el->textContent"; + if(trn.isIntType(t))code+="+0"; + code+=";\n"; + } + code+="\t\t}\n"; + } + } + } + code+="\t}catch(Exception $e){$this->handleException($e);}\n"; + code+="\t/*end of input parsing*/\n"; + return code; +} + +QString WocPHPServerOut::trnOutput(const WocTransaction&trn) +{ + QStringList sl=trn.outputNames(); + QString code="\t/*start of output encoding*/\n"; + code+="\ttry{\n\t\t$xml=new DOMDocument;\n"; + code+="\t\t$root=$xml->createElement(\"WobResponse\");\n"; + for(int i=0;iaoutput[\""+sl[i]+"\"]);\n"; + }else{ + if(trn.isListType(t)){ + if(trn.isObjectType(t)){ + code+="\t\tforeach($this->aoutput[\""+sl[i]+"\"] as $o)\n"; + code+="\t\t\tif(is_a($o,\"WO"+trn.plainType(t)+"\"))\n"; + code+="\t\t\t\t$root->appendChild($o->toXml"+trn.typeSerializer(t)+"($xml,\""+sl[i]+"\"));\n"; + }else if(trn.isBlobType(t)){ + code+="\t\tforeach($this->aoutput[\""+sl[i]+"\"] as $v)\n"; + code+="\t\t\t$root->appendChild($xml->createElement(\""+sl[i]+"\",base64_encode($v)));\n"; + }else{ + code+="\t\tforeach($this->aoutput[\""+sl[i]+"\"] as $v)\n"; + code+="\t\t\t$root->appendChild($xml->createElement(\""+sl[i]+"\",xq($v)));\n"; + } + }else{ + if(trn.isObjectType(t)){ + code+="\t\t$o=$this->aoutput[\""+sl[i]+"\"];\n"; + code+="\t\tif(is_a($o,\"WO"+trn.plainType(t)+"\"))\n"; + code+="\t\t\t$root->appendChild($o->toXml"+trn.typeSerializer(t)+"($xml,\""+sl[i]+"\"));\n"; + }else if(trn.isBlobType(t)){ + code+="\t\t$root->appendChild($xml->createElement(\""+sl[i]+"\",base64_encode($this->aoutput[\""+sl[i]+"\"])));\n"; + }else{ + code+="\t\t$root->appendChild($xml->createElement(\""+sl[i]+"\",xq($this->aoutput[\""+sl[i]+"\"])));\n"; + } + } + } + } + code+="\t\t$xml->appendChild($root);\n"; + code+="\t\theader(\"X-WobResponse-Status: Ok\");\n"; + code+="\t\tprint($xml->saveXml());\n"; + code+="\t}catch(Exception $e){$this->handleException($e);}\n"; + code+="\t/*end of output*/\n"; + return code; +} + +QString WocPHPServerOut::trnGetSet(const WocTransaction&trn) +{ + QString code; + //getters + QStringList sl=trn.inputNames(); + for(int i=0;iainput[\""+sl[i]+"\"];}\n"; + } + //setters + sl=trn.outputNames(); + for(int i=0;iaoutput[\""+sl[i]+"\"][]=$vv;\n"; + add+="\tif(is_a($vv,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+sl[i]+"\"][]=$vv;\n"; + }else{ + code+="\t\t$this->aoutput[\""+sl[i]+"\"][]=\"\".$vv;\n"; + add+="\t$this->aoutput[\""+sl[i]+"\"][]=\"\".$vv;\n"; + } + code+="\t}\n"; + add+="}\n"; + }else{ + if(trn.isIntType(t)){ + code+="\tif(is_numeric($v))$this->aoutput[\""+sl[i]+"\"]=$v+0;\n"; + }else + if(trn.isBoolType(t)){ + code+="\tif(is_bool($v))$this->aoutput[\""+sl[i]+"\"]=$v!=false;\n"; + }else + if(trn.isObjectType(t)){ + code+="\tif(is_a($v,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+sl[i]+"\"]=$v;\n"; + }else{ + code+="\t$this->aoutput[\""+sl[i]+"\"]=\"\".$v;\n"; + } + } + code+="}\n"+add; + } + + + return code; +} + +QString WocPHPServerOut::trnExecute(const WocTransaction&trn) +{ + QStringList in=trn.inputNames(); + QString code="static public function execute("; + for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PHPOUT_H +#define WOC_PHPOUT_H + +#include + +#include "processor.h" + +class QDomElement; + +/**generates output for a PHP server side*/ +class WocPHPServerOut:public WocOutput +{ + public: + /**initializes the output object*/ + WocPHPServerOut(const QDomElement&); + protected: + /**writes any last words after parsing finished*/ + virtual void finalize(); + /**creates a class*/ + virtual void newClass(const WocClass&); + /**creates a table*/ + virtual void newTable(const WocTable&); + /**creates a transaction*/ + virtual void newTransaction(const WocTransaction&); + private: + QString m_basedir,m_subdir,m_fileext; + QString m_isauth,m_hasrole,m_username,m_authinit; + QFile m_loader,m_schema,m_transact; + + /**helper: adds a loader line for a class to autoload.php*/ + void addLoad(QString classname,QString filename); + + /**helper: generates PHP code to transform a class property to XML*/ + QString propertyToXml(const WocClass&,QString); + /**helper: generate class constructor*/ + QString classConstruct(const WocClass&); + /**helper: generate class internal enums*/ + QString classEnums(const WocClass&); + /**helper: generate class internal props*/ + QString classProperties(const WocClass&); + /**helper: generate class internal serializers*/ + QString classSerializers(const WocClass&); + /**helper: generate class internal deserializers*/ + QString classDeserializers(const WocClass&); + /**helper: generate class internal mappers*/ + QString classMappings(const WocClass&); + /**helper: generate property validator*/ + QString classPropertyValidator(const WocClass&,QString); + /**helper: generate getters for list properties*/ + QString classPropertyListGetters(const WocClass&,QString); + /**helper: generate setters for list properties*/ + QString classPropertyListSetters(const WocClass&,QString); + /**helper: generate getters for scalar properties*/ + QString classPropertyScalarGetters(const WocClass&,QString); + /**helper: generate setters for sclar properties*/ + QString classPropertyScalarSetters(const WocClass&,QString); + + /**helper: create info functions (mainly version info) at the start*/ + void transInfo(); + /**helper: create info functions (mainly version info) at the end*/ + void transInfo2(); + + /**helper: create transaction constructor*/ + QString trnConstruct(const WocTransaction&); + /**helper: create transaction input parser*/ + QString trnInput(const WocTransaction&); + /**helper: create transaction output serializer*/ + QString trnOutput(const WocTransaction&); + /**helper: create getters and setters*/ + QString trnGetSet(const WocTransaction&); + /**helper: create direct execution code for web interface*/ + QString trnExecute(const WocTransaction&); + /**helper: create privilege check code for web interface*/ + QString trnPrivileges(const WocTransaction&); + + /**helper: return the PHP-class-name of a WocClass*/ + QString className(const WocClass&c){return "WO"+c.name();} + /**helper: return the PHP-class-name of a WocClass plus Abstract if it is abstract*/ + QString abstractClassName(const WocClass&c){return "WO"+c.name()+QString(c.isAbstract("php")?"Abstract":"");} + + /**helper: returns the PHP-class-name for a WocTransaction*/ + QString trnClassName(const WocTransaction&t){return "WTr"+t.name();} +}; + +#endif diff --git a/woc/processor.cpp b/woc/processor.cpp new file mode 100644 index 0000000..8da690c --- /dev/null +++ b/woc/processor.cpp @@ -0,0 +1,1223 @@ +// +// C++ Implementation: processor +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "processor.h" + +#include "phpout.h" +#include "qtout.h" +#include "htmlout.h" + +#include "domquery.h" + +#include +#include +#include +#include + +QListelementsByTagName(const QDomElement&root,QString tag) +{ + QDomNodeList cn=root.childNodes(); + QListret; + for(int i=0;i nl=elementsByTagName(el,"AuditTables"); + for(int i=0;imaxv)maxv=cv; + } + if(minv==maxv) + m_svnRev=QString::number(maxv); + else + m_svnRev=QString::number(minv)+"-"+QString::number(maxv); + } + //parse for repository path + MDomNodeList nl=MDomQuery(doc,"/*/entry"); + for(int i=0;i0)m_svnUrl=rl[0]; + rl=MDomQuery(el,"repository/root"); + if(rl.size()>0)m_svnRoot=rl[0]; + break;//we can stop now + } + } + } + //svn status + svn.start(m_svnExe,QStringList()<<"status"<<"--xml"<<"--non-interactive"<<"."); + svn.waitForFinished(); + if(svn.exitCode()!=0){ + qDebug("Warning: error while calling svn status."); + m_svnRev+=" uncertain"; + return; + }else{ + QDomDocument doc; + if(!doc.setContent(svn.readAllStandardOutput())){ + qDebug("Warning: unable to parse output of svn status."); + m_svnRev+=" uncertain"; + return; + } + QStringList rl=MDomQuery(doc,"/status/target/entry/wc-status/@item"); + bool ismod=false; + for(int i=0;ihasClass(m_name)){ + qDebug("Error: double definition of class %s at line %i column %i.",m_name.toAscii().data(),cls.lineNumber(),cls.columnNumber()); + m_valid=false; + return; + } + if(!symok.exactMatch(m_name)){ + qDebug("Error: Illegal class name %s.",m_name.toAscii().data()); + m_valid=false; + return; + } + qDebug("Info: parsing class %s",m_name.toAscii().data()); + m_sbase=cls.attribute("serverbase","WObject"); + m_cbase=cls.attribute("clientbase","WObject"); + //scan properties + QList nl=elementsByTagName(cls,"Property"); + for(int i=0;iev; + //check whether there is a reference + if(el.hasAttribute("refColumn")){ + QStringList ref=el.attribute("refColumn").split(":"); + if(ref.size()!=2){ + qDebug("Error: illegal enum reference in class %s enum %s.",m_name.toAscii().data(),nm.toAscii().data()); + m_valid=false; + return; + } + if(!woc->hasTable(ref[0])){ + qDebug("Error: enum reference in class %s enum %s points to non-existant table.",m_name.toAscii().data(),nm.toAscii().data()); + m_valid=false; + return; + } + WocTable tab=woc->table(ref[0]); + if(!tab.hasColumn(ref[1])){ + qDebug("Error: enum reference in class %s enum %s points to non-existant column.",m_name.toAscii().data(),nm.toAscii().data()); + m_valid=false; + return; + } + ev=tab.columnEnums(ref[1]); + } + //scan values + QList nl2=elementsByTagName(el,"Value"); + int nxval=0; + for(int j=0;jmap; + QList nl2=elementsByTagName(el,"Map"); + for(int j=0;j nl3=elementsByTagName(el2,"Call"); + for(int k=0;khasClass(t); +} + +bool WocClass::propertyIsEnum(QString p)const +{ + QString t=propertyPlainType(p); + //default types take precedence over enums + if(attrtypes.contains(t))return false; + if(elemtypes.contains(t))return false; + //enums + return hasEnumType(t); +} + +bool WocClass::propertyIsList(QString p)const +{ + if(propertyType(p).startsWith("List:"))return true; + else return false; +} + +QMap WocClass::mapping(QString m)const +{ + if(!m_maps.contains(m))return QMap(); + QList sml=m_maps[m]; + QMapret; + for(int i=0;i sml=m_maps[m]; + QStringList ret; + for(int i=0;i sml=m_maps[table]; + for(int i=0;ihasTable(m_name)){ + qDebug("Error: double definition of table %s.",m_name.toAscii().data()); + m_valid=false; + return; + } + if(!good.exactMatch(m_name)){ + qDebug("Error: table %s does not have a regular name.",m_name.toAscii().data()); + m_valid=false; + return; + } + m_backup=str2bool(tbl.attribute("backup","0")); + m_base=tbl.attribute("base","WobTable"); + m_audit=str2bool(tbl.attribute("audit","0")); + qDebug("Info: parsing table %s",m_name.toAscii().data()); + //Columns + QList nl=elementsByTagName(tbl,"Column"); + for(int i=0;i cl=parseColumn(el,m_name); + if(!cl.first)return; + if(hasColumn(cl.second.name)){ + qDebug("Error: double definition of column %s in table %s.",cl.second.name.toAscii().data(),m_name.toAscii().data()); + m_valid=false; + return; + } + m_columns.append(cl.second); + } + //Audit Columns + nl=elementsByTagName(tbl,"AuditColumn"); + for(int i=0;i cl=parseColumn(el,m_name); + if(!cl.first)return; + m_auditcolumns.append(cl.second); + } + + //Foreign getter methods + nl=elementsByTagName(tbl,"Foreign"); + for(int i=0;i(el.attribute("method"),el.attribute("via"))); + //TODO: validate foreign getter + //docu + QString s=el.text().trimmed(); + if(s!="")m_fordocs.insert(el.attribute("method"),s); + } + + //Presets + nl=elementsByTagName(tbl,"Preset"); + for(int i=0;ips; + QList nl2=elementsByTagName(el,"V"); + for(int j=0;j0)m_presets.append(ps); + } + + //Docu + nl=elementsByTagName(tbl,"Doc"); + for(int i=0;i WocTable::parseColumn(const QDomElement&el,QString m_name) +{ + s_col cl; + QRegExp good("[a-z][a-z0-9_]*",Qt::CaseInsensitive); + cl.name=el.attribute("name"); + //check name syntax, check it is not doubled + if(!good.exactMatch(cl.name)){ + qDebug("Error: table %s column %s does not have a regular name.",m_name.toAscii().data(),cl.name.toAscii().data()); + return QPair(false,s_col()); + } + cl.isprime=str2bool(el.attribute("primarykey","0")); + cl.isunique=str2bool(el.attribute("unique","0")); + cl.isindex=str2bool(el.attribute("index","0")); + if(cl.isprime)cl.isnull=false; + else cl.isnull=true; + if(el.hasAttribute("null")) + cl.isnull=str2bool(el.attribute("null")); + else if(el.hasAttribute("notnull")) + cl.isnull=!str2bool(el.attribute("notnull","0")); + cl.type=el.attribute("type"); + //TODO: validate type + cl.foreign=el.attribute("foreignkey"); + WocProcessor*woc=WocProcessor::instance(); + //check foreign key exists + if(cl.foreign!=""){ + QStringList fgn=cl.foreign.split(":"); + if(fgn.size()!=2){ + qDebug("Error: table %s column %s: foreign key definition must use syntax 'table:column'",m_name.toAscii().data(),cl.name.toAscii().data()); + return QPair(false,s_col()); + } + if(!woc->hasTable(fgn[0])){ + qDebug("Error: table %s column %s: foreign key target table %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),fgn[0].toAscii().data()); + return QPair(false,s_col()); + } + if(!woc->table(fgn[0]).hasColumn(fgn[1])){ + qDebug("Error: table %s column %s: foreign key target table/column %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),cl.foreign.toAscii().data()); + return QPair(false,s_col()); + } + } + cl.defaultval=el.attribute("default"); + //TODO: validate default against type + QList nl2=elementsByTagName(el,"Value"); + int nxval=0; + //enum values + for(int j=0;j(true,cl); +} + +QStringList WocTable::columns()const +{ + QStringList r; + for(int i=0;i WocTable::columnEnums(QString c)const +{ + for(int i=0;i(); +} + +QList WocTable::getEnums()const +{ + QList r; + for(int i=0;iWocTable::m_staticauditcolumns; +void WocTable::parseAuditStatic(const QDomElement&el) +{ + QList nl=elementsByTagName(el,"Column"); + for(int i=0;icl=parseColumn(el2,"(global audit settings)"); + if(!cl.first){ + WocProcessor::instance()->errorFound(); + return; + } + m_staticauditcolumns.append(cl.second); + } +} + +WocTable WocTable::auditTable()const +{ + WocTable adt; + adt.m_valid=m_valid; + adt.m_backup=m_backup; + adt.m_audit=false; + adt.m_name=m_name+"_audit";//enhance the name + adt.m_base="WobTable";//revert to default + adt.m_foreign=m_foreign; + adt.m_fordocs=m_fordocs; + adt.m_docstrings=m_docstrings; + //these stay empty: m_presets, m_auditcolumns + + //now for the complicated stuff + //create primary key + s_col cl; + cl.name="auditid";cl.type="seq64";cl.doc="additional primary key for auditing"; + cl.isindex=cl.isunique=cl.isnull=false;cl.isprime=true; + adt.m_columns.append(cl); + //copy common columns + adt.m_columns.append(m_staticauditcolumns); + //copy normal columns + for(int i=0;i nl=elementsByTagName(root,"Input"); + for(int i=0;i nl2=elementsByTagName(el,"Var"); + for(int j=0;j(nm,tp)); + //docu + QString s=el2.text().trimmed(); + if(s!="")m_indoc.insert(nm,s); + } + } + //call tag + nl=elementsByTagName(root,"Call"); + for(int j=0;j nl2=elementsByTagName(el,"Var"); + for(int j=0;j(nm,tp)); + //docu + QString s=el2.text().trimmed(); + if(s!="")m_outdoc.insert(nm,s); + } + } + //docu + nl=elementsByTagName(root,"Doc"); + for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PROCESSOR_H +#define WOC_PROCESSOR_H + +#include +#include +#include +#include +#include + +class QDomElement; + +QListelementsByTagName(const QDomElement&,QString); + +inline bool str2bool(QString s) +{ + bool b; + int i=s.toInt(&b,0); + if(b)return i?true:false; + s=s.toLower(); + if(s=="yes"||s=="y"||s=="on"||s=="true"||s=="t")return true; + return false; +} + + +/**helper structure to store enums in classes and tables*/ +struct WocEnum { + QString name,doc; + int val; + WocEnum(){val=0;} + WocEnum(QString n,int v,QString d=""){name=n;val=v;doc=d;} +}; + +/**stores a communication class including serialization and deserialization information*/ +class WocClass +{ + public: + /**parses XML to create itself*/ + WocClass(const QDomElement&); + + /**returns whether parsing was successful and this instance represents a valid communication class*/ + bool isValid()const{return m_valid;} + + /**returns the class name*/ + QString name()const{return m_name;} + /**returns the name of the class it is derived from (on the server side) - default: WObject*/ + QString serverBaseClass()const{return m_sbase;} + /**returns the parent class of the class on client side- default: WObject*/ + QString clientBaseClass()const{return m_cbase;} + + /**returns true of it has a property with this name*/ + bool hasProperty(QString)const; + /**returns a list of all property names*/ + QStringList propertyNames()const; + /**returns the type string of the property, including "List:" if applicable*/ + QString propertyType(QString)const; + /**returns the plain type string of the property without "List:"*/ + QString propertyPlainType(QString)const; + /**returns whether this property identifies the object instance*/ + bool propertyIsIdentity(QString)const; + /**returns whether this property is abstract*/ + bool propertyIsAbstract(QString)const; + /**returns whether this property is serialized as XML attribute*/ + bool propertyIsAttribute(QString)const; + /**returns whether this property is serialized as XML element*/ + bool propertyIsElement(QString)const; + /**returns whether this property has an enum type*/ + bool propertyIsEnum(QString)const; + /**returns whether the property is an object*/ + bool propertyIsObject(QString)const; + /**returns whether the property is a list of values (false for scalars)*/ + bool propertyIsList(QString)const; + /**returns whether the property type is integer*/ + bool propertyIsInt(QString p)const{QString pt=propertyPlainType(p);return pt=="int" || pt=="int32" || pt=="int64";} + /**returns whether the property type is boolean*/ + bool propertyIsBool(QString p)const{return propertyPlainType(p)=="bool";} + /**returns whether the property type is string*/ + bool propertyIsString(QString p)const{QString pt=propertyPlainType(p);return pt=="string"||pt=="astring";} + /**returns whether the property type is blob*/ + bool propertyIsBlob(QString p)const{QString pt=propertyPlainType(p);return pt=="blob";} + + /**returns whether the class is abstract in the requested language (needs to be customized); it is automatically abstract if any property is abstract*/ + bool isAbstract(QString)const; + /**returns the languages in which the class is conditionally abstract*/ + QStringList abstractLangs()const{return m_cabstract;} + + /**returns the names of all enum types of this class*/ + QStringList enumTypes()const{return m_enumvals.keys();} + /**returns true if the given enum type exists in this class*/ + bool hasEnumType(QString t)const{return m_enumvals.contains(t);} + /**returns a list of enum values as name-value pairs*/ + QList enumValues(QString t)const{return m_enumvals[t];} + + /**returns true if the given mapping exists*/ + bool hasMapping(QString m)const{return m_maps.contains(m);} + /**returns the names of all tables for which a mapping exists*/ + QStringList mappingTables()const{return m_maps.keys();} + /**returns the (correctly ordered) properties for a mapping*/ + QStringList mappingProperties(QString)const; + /**returns the specific mapping; map key=property, map value=column*/ + QMap mapping(QString m)const; + /**returns the method for a specific mapping or an empty string if it does not exist in the specified language*/ + QString mapMethod(QString table,QString property,QString lang)const; + + /**returns documentation for this class*/ + QStringList docStrings()const{return m_docstrings;} + /**returns documentation for a property*/ + QString propDoc(QString p)const + {if(m_propdoc.contains(p))return m_propdoc[p];else return "";} + + private: + //valid: parsing the WOLF succeeded + //abstract: the class is declared abstract (isAbstract may return true even if this is false) + //cabstract: conditional abstract - just for one or two languages; abstract overrides cabstract! + bool m_valid,m_abstract; + QStringList m_cabstract; + //name: class name + //base: name of parent class (s=server, c=client) + QString m_name,m_sbase,m_cbase; + //property info + struct s_prop{ + QString name,type; + bool isid,isabstract; + }; + QList m_props; + //mappings: "table-name" => List of ("column-name","property-name") + struct s_map{ + QString column,property; + QMapmethod;//lang->method + }; + QMap >m_maps; + //enum types: "type-name" => List of ("constant-name",int-constant-value) + QMap >m_enumvals; + //serializers: "name" => List of properties (syntax Objects: "propertyname/Serializer" +// QMap m_serial; + + //docu + QStringList m_docstrings; + QMapm_propdoc; + + //helper: contains predefined types sorted by serialization type + static const QStringList attrtypes,elemtypes; +}; + +/**stores the internal representation of a database table and its abstraction class*/ +class WocTable +{ + public: + /**initializes an invalid table*/ + WocTable(); + /**initializes a table from XML*/ + WocTable(const QDomElement&); + + /**returns whether this instance is valid, ie. whether parsing was successful*/ + bool isValid()const{return m_valid;} + + /**returns the table name*/ + QString name()const{return m_name;} + /**returns whether the table is marked for backup*/ + bool inBackup()const{return m_backup;} + /**returns the parent class of the table class - default: WobTable*/ + QString baseClass()const{return m_base;} + + /**returns whether the table has a column with this name*/ + bool hasColumn(QString)const; + /**returns a list of all defined column names*/ + QStringList columns()const; + /**returns the list of all primary key columns*/ + QStringList primaryColumns()const; + /**returns the data type of the column*/ + QString columnType(QString)const; + /**returns whether the column allows NULLs*/ + bool columnIsNull(QString)const; + /**returns whether the column is part of the primary key*/ + bool columnIsPrimary(QString)const; + /**returns whether the column has a default*/ + bool columnHasDefault(QString)const; + /**returns the default value of the column (empty string if there is none)*/ + QString columnDefault(QString)const; + /**returns whether the column is a foreign key*/ + bool columnIsForeign(QString)const; + /**returns the foreign key reference of the column in the format table:column*/ + QString columnForeign(QString)const; + /**returns whether the column has an index*/ + bool columnIsIndexed(QString)const; + /**returns whether the column has a unique constraint*/ + bool columnIsUnique(QString)const; + /**returns enum definitions of the column - each pair contains the symbolic name in first and the assigned integer value in second*/ + QList columnEnums(QString)const; + /**returns the insert call of a column for a specific language; empty string if there is none*/ + QString columnCall(QString col,QString lang)const; + + /**returns all enum definitions of the table; see also columnEnums */ + QList getEnums()const; + + /**returns a list of all foreign definitions - methods that return data from other tables*/ + QStringList foreigns()const; + /**returns the definition of a specific foreign table query method*/ + QString foreignQuery(QString)const; + /**returns whether a foreign table query method exists*/ + bool haveForeign(QString)const; + + /**returns a list of all preset values (to be generated when the DB is created); + each entry in the list is a dictionary with the column name as key and the intended preset value as value - each entry of the list is one DB row, each key-value-pair in the map is one preset value in that row*/ + QList > presets()const{return m_presets;} + + /**parses the static part of auditing*/ + static void parseAuditStatic(const QDomElement&); + /**returns whether the table is auditable*/ + bool isAuditable()const{return m_audit;} + /**creates and returns the table instance that represents the audit table*/ + WocTable auditTable()const; + /**returns the names of audit columns (except auditid)*/ + QStringList auditColumns()const; + + /**returns table documentation*/ + QStringList docStrings()const{return m_docstrings;} + /**returns column documentation*/ + QString columnDoc(QString c)const; + /**returns foreign getter documentation*/ + QString foreignDoc(QString c)const + {if(m_fordocs.contains(c))return m_fordocs[c];else return "";} + + private: + bool m_valid,m_backup,m_audit; + QString m_name,m_base; + struct s_col { + QString name,type,foreign,defaultval,doc; + bool isnull,isprime,isindex,isunique; + QListenumvals; + QMapmethodcalls; + }; + QListm_columns,m_auditcolumns; + static QListm_staticauditcolumns; + QList >m_foreign; + QList >m_presets; + + QStringList m_docstrings; + QMapm_fordocs; + + //helper method: parses a single column element + static QPair parseColumn(const QDomElement&,QString); +}; + +/**internal representation of a transaction*/ +class WocTransaction +{ + public: + /**initializes a transaction from XML*/ + WocTransaction(const QDomElement&); + /**returns whether parsing it was successful*/ + bool isValid()const{return m_valid;} + + /**returns the name of the transaction*/ + QString name()const{return m_name;} + + /**returns whether an input variable exists*/ + bool hasInput(QString v)const; + /**returns the names of all inputs in the order of definition*/ + QStringList inputNames()const; + /**returns the type of an input variable*/ + QString inputType(QString)const; + + /**returns whether an output variable exists*/ + bool hasOutput(QString v)const; + /**returns the names of all outputs in the order of definition*/ + QStringList outputNames()const; + /**returns the type of an output variable*/ + QString outputType(QString)const; + + /**returns whether a specific language binding exists for a call*/ + bool hasCall(QString c)const{return m_call.contains(c);} + /**returns the called function*/ + QString callFunction(QString c)const{return m_call[c];} + + /**authentication mode*/ + enum AuthMode { + /**default: need a valid session and the privilege*/ + Checked, + /**only need to be authenticated, every valid user can do it*/ + Auth, + /**available even to anonymous/unauthenticated users*/ + Open + }; + AuthMode authMode()const{return m_mode;} + + /**returns true if the type given is a list*/ + bool isListType(QString t)const{return t.startsWith("List:");} + /**returns the type without list or xml qualifiers*/ + QString plainType(QString t)const{ + if(t.startsWith("List:"))t=t.mid(5); + QStringList l=t.split("/",QString::SkipEmptyParts); + if(l.size()>0)t=l[0];else t="unknown"; + return t; + } + /**returns the XML serializer for Object types*/ + QString typeSerializer(QString t)const{ + QStringList l=t.split("/",QString::SkipEmptyParts); + if(l.size()>1)return l[1]; + else return ""; + } + /**returns true if the type is integer*/ + bool isIntType(QString t)const{QString pt=plainType(t);return pt=="int" || pt=="int32" || pt=="int64";} + /**returns true if the type is boolean*/ + bool isBoolType(QString t)const{return plainType(t)=="bool";} + /**returns true if the type is a string*/ + bool isStringType(QString t)const{QString p=plainType(t);return p=="astring"||p=="string";} + /**returns true if the type is a blob*/ + bool isBlobType(QString t)const{QString p=plainType(t);return p=="blob";} + /**returns true if the type is to be encoded as attribute*/ + bool isAttributeType(QString t)const{return t=="astring"||t=="int"||t=="int32"||t=="int64"||t=="bool";} + /**returns true if the type is to be encoded as element*/ + bool isElementType(QString t)const{return !isAttributeType(t);} + /**return true if the type is an object type*/ + bool isObjectType(QString t)const{QString p=plainType(t);return p!="astring"&&p!="string"&&p!="int"&&p!="int32"&&p!="int64"&&p!="bool"&&p!="blob";} + + /**return the documentation of the transaction*/ + QStringList docStrings()const{return m_docstrings;} + /**return docu of input element*/ + QString inputDoc(QString v)const + {if(m_indoc.contains(v))return m_indoc[v];else return "";} + /**return docu of output element*/ + QString outputDoc(QString v)const + {if(m_outdoc.contains(v))return m_outdoc[v];else return "";} + /**return docu of a privilege*/ + QString privilegeDoc(QString p)const + {if(m_privdoc.contains(p))return m_privdoc[p];else return "";} + + /**return privileges that exist inside this transaction*/ + QStringList privileges()const{return m_privileges;} + private: + QString m_name; + bool m_valid; + AuthMode m_mode; + QMap m_call; + QList >m_input,m_output; + QStringList m_privileges; + //docu + QStringList m_docstrings; + QMapm_indoc,m_outdoc,m_privdoc; +}; + +/**base class of all output generators*/ +class WocOutput:public QObject +{ + Q_OBJECT + public: + /**the constructor should set up and initialize the environment of the generator*/ + WocOutput(); + /**currently there is no guarantee that the destructor is ever called.*/ + virtual ~WocOutput(); + + protected slots: + /**called whenever the parser finds a new class in the XML input; some references might not exist yet*/ + virtual void newClass(const WocClass&)=0; + /**called whenever the parser finds a new table in the XML input; the parser guarantees that tables it depends on already exist (it will throw an error otherwise)*/ + virtual void newTable(const WocTable&)=0; + /**called whenever the parser finds a new transaction; the parser guarantees that all referenced types exist (it will throw an error otherwise)*/ + virtual void newTransaction(const WocTransaction&)=0; + /**called when the parsing is complete: it should clean up the generators environment; it may not be called if woc stops with an error*/ + virtual void finalize()=0; + signals: + void errorFound(); +}; + +/**central processing singleton*/ +class WocProcessor:public QObject +{ + Q_OBJECT + public: + WocProcessor(); + + /**called from main loop to parse a file*/ + bool processFile(QString); + /**called from main loop to finalize its work*/ + void finalize(); + + /**returns the instance of the processor (if it exists yet)*/ + static WocProcessor* instance(){return inst;} + + /**returns the base directory of the project (all other pathes are relative to it)*/ + QString baseDir()const{return m_baseDir;} + /**returns the directory where WOLFs are found, should normally not be used outside this class*/ + QString wobDir()const{return m_wobDir;} + /**returns the project name (default="WobProject")*/ + QString projectName()const{return m_projname;} + /**returns the current communication protocol version*/ + QString verComm()const{return m_verComm;} + /**returns the communication protocol version that is at least needed to be compatible*/ + QString verNeedComm()const{return m_verNeedComm;} + /**returns a human readable version string*/ + QString verHR()const{return m_verHR;} + /**returns the SVN revision of the project: it contains two tokens, the first one is the current revision or min-max if the working copy contains mixed revisions; the second token contains the word "vanilla" if there are no local modifications, or "modified" if there are local modifications*/ + QString svnRevision()const{return m_svnRev;} + /**returns the SVN Repository Root*/ + QString svnRepositoryRoot()const{return m_svnRoot;} + /**returns the complete SVN Repository URL*/ + QString svnRepositoryUrl()const{return m_svnUrl;} + /**returns the variable name that will contain the database driver instance*/ + QString dbInst()const{return m_dbInst;} + /**returns the variable name that will contain the database schema object*/ + QString dbSchema()const{return m_dbSchema;} + /**returns the database schema version*/ + QString dbVersion()const{return m_dbVer;} + + /**returns whether a table exists*/ + bool hasTable(QString)const; + /**returns the requested table*/ + WocTable table(QString)const; + + /**returns whether a class exists*/ + bool hasClass(QString)const; + + /**returns a list of transaction names*/ + QStringList transactionNames()const; + /**returns a list of class names*/ + QStringList classNames()const; + /**returns a list of table names*/ + QStringList tableNames()const; + + /**returns global docu*/ + QStringList docStrings()const{return m_docstrings;} + + /**returns the qualified names of all privileges*/ + QStringList privilegeNames()const; + signals: + void sfinalize(); + void newClass(const WocClass&); + void newTable(const WocTable&); + void newTransaction(const WocTransaction&); + public slots: + void errorFound(); + private: + QString m_baseDir,m_wobDir,m_verComm,m_verNeedComm,m_verHR,m_projname; + QString m_svnTarget,m_svnRev,m_svnExe,m_svnRoot,m_svnUrl; + QString m_dbInst,m_dbSchema,m_dbVer; + QStringList m_docstrings; + bool m_error; + + QList m_tables; + QList m_classes; + QList m_transactions; + + static WocProcessor*inst; + + /**helper: calls SVN and parses its output*/ + void callSvn(); +}; + + +#endif diff --git a/woc/qtout.cpp b/woc/qtout.cpp new file mode 100644 index 0000000..3762836 --- /dev/null +++ b/woc/qtout.cpp @@ -0,0 +1,821 @@ +// +// C++ Implementation: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "qtout.h" + +#include +#include + +//start section of all header files +static const QByteArray HDRSTART= + "//AUTOMATICALLY GENERATED FILE\n" + "//DO NOT EDIT THIS FILE DIRECTLY, USE THE XML SOURCE!\n" + "#ifndef WOBGEN_%\n" + "#define WOBGEN_%\n\n"; +//end section of all header files +static const QByteArray HDREND="\n//END OF AUTOMATICALLY GENERATED FILE\n#endif\n"; + +//start section of all source files +static const QByteArray SRCSTART= + "//AUTOMATICALLY GENERATED FILE\n" + "//DO NOT EDIT THIS FILE DIRECTLY, USE THE XML SOURCE!\n" + "#include \"%.h\"\n" + "#include \n" + "#include \n"; +//end section of all source files +static const QByteArray SRCEND="\n//END OF AUTOMATICALLY GENERATED FILE\n"; + +WocQtClientOut::WocQtClientOut(QDomElement&el) +{ + qDebug("Info: creating Qt Client Output Generator."); + m_basedir=WocProcessor::instance()->baseDir()+"/"+el.attribute("sourceDir","."); + m_subdir=el.attribute("subDir","qtwob"); + m_clean=str2bool(el.attribute("clean","0")); + m_prefix=el.attribute("classPrefix","Wob"); + //get/create directory + QDir d(m_basedir+"/"+m_subdir); + if(!d.exists())QDir(".").mkpath(m_basedir+"/"+m_subdir); + + //create project file + m_pri.setFileName(m_basedir+"/"+m_subdir+"/"+el.attribute("priInclude","qtwob.pri")); + if(!m_pri.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create Qt project file %s.",m_pri.fileName().toAscii().data()); + emit errorFound(); + return; + } + m_pri.write(QByteArray("#AUTOMATICALLY GENERATED FILE - DONT CHANGE!\n")); + + //create interface class + WocProcessor*woc=WocProcessor::instance(); + QString pn=woc->projectName(); + m_ifacecpp.setFileName(m_basedir+"/"+m_subdir+"/"+m_prefix+"Interface.cpp"); + if(!m_ifacecpp.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create Qt interface file %s.",m_ifacecpp.fileName().toAscii().data()); + emit errorFound(); + return; + } + m_ifacecpp.write(QByteArray(SRCSTART).replace('%',m_prefix+"Interface")); + m_iface.setFileName(m_basedir+"/"+m_subdir+"/"+m_prefix+"Interface.h"); + if(!m_iface.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create Qt interface file %s.",m_iface.fileName().toAscii().data()); + emit errorFound(); + return; + } + m_iface.write(QByteArray(HDRSTART).replace("%",m_prefix.toAscii()+"INTERFACE_H")); + m_iface.write(QByteArray("#include \""+m_prefix.toAscii()+"Include.h\"\n#include \"WInterface.h\"\n")); + m_iface.write(QByteArray("#include \n")); + m_iface.write(QString("class "+m_prefix+"Interface:public WInterface\n{\n Q_OBJECT\n").toAscii()); + m_iface.write(QString(" public:\n "+m_prefix+"Interface(QString name=\""+pn+"\"):WInterface(name){}\n").toAscii()); + m_iface.write(QString(" static "+m_prefix+"Interface*instance(QString name=\""+pn+"\")\n\t{return qobject_cast<"+m_prefix+"Interface*>(WInterface::instance(name));}\n\n").toAscii()); + m_iface.write(QString(" static QString commVersion(){return \""+woc->verComm()+"\";}\n").toAscii()); + m_iface.write(QString(" static QString needCommVersion(){return \""+woc->verNeedComm()+"\";}\n").toAscii()); + m_iface.write(QString(" static QString version(){return \""+woc->verHR()+"\";}\n").toAscii()); + m_iface.write(QString(" static QString svnVersion(){return \""+woc->svnRevision()+"\";}\n\n").toAscii()); + m_iface.write(QString(" static QString svnRepositoryRoot(){return \""+woc->svnRepositoryRoot()+"\";}\n\n").toAscii()); + m_iface.write(QString(" static QString svnRepositoryUrl(){return \""+woc->svnRepositoryUrl()+"\";}\n\n").toAscii()); + + //create all includer + m_hdr.setFileName(m_basedir+"/"+m_subdir+"/"+m_prefix+"Include.h"); + if(!m_hdr.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create Qt header file %s.",m_hdr.fileName().toAscii().data()); + emit errorFound(); + return; + } + m_hdr.write(QByteArray(HDRSTART).replace("%",m_prefix.toAscii()+"INCLUDE_H")); + addFile(m_prefix.toAscii()+"Interface"); +} + +WocQtClientOut::~WocQtClientOut(){} + +void WocQtClientOut::finalize() +{ + trnList(); + m_ifacecpp.write(SRCEND); + m_ifacecpp.close(); + m_iface.write(QByteArray("};\n")+HDREND); + m_iface.close(); + m_pri.write(QByteArray("\n#END OF AUTOGENERATED PRI FILE\n")); + m_pri.close(); + m_hdr.write(HDREND); + m_hdr.close(); + //cleanup directory (remove untouched normal files, assume remainder is harmless) + QDir d(m_basedir+"/"+m_subdir); + if(m_clean){ + QStringList ent=d.entryList(QDir::Files); + for(int i=0;i\n\n"; + QStringList k=cls.propertyNames(); + for(int i=0;iev=cls.enumValues(k[i]); + if(ev.size()<1){ + qDebug("Error: enums must have at least one member - class %s enum %s",cls.name().toAscii().data(),k[i].toAscii().data()); + emit errorFound(); + return; + } + for(int j=0;j1)var=pv[1]; + //is it a list + if(cls.propertyIsList(prop)){ + scd+="\tfor(int i=0;i\n"; + for(int i=0;i\n"; + } + for(int i=0;i\n"; + } + hcd+="\nclass "+cn+":public WTransaction\n{\n"; + hdr.write(hcd.toAscii()); + + //create properties + QString inlist,clist; + hcd=" private:\n"; + for(int i=0;iprojectName()+"\""; + //define parametric constructor + hcd=" public:\n"; + hcd+="\t"+cn+"("+inlist+defparm+");\n"; + //parametric constructor implementation + scd+=cn+"::"+cn+"("+inlist+")\n\t:WTransaction(iface)\n{\n"; + for(int i=0;itransactionNames(); + QStringList p=WocProcessor::instance()->privilegeNames(); + QStringList pp=p; + for(int i=0;i "+m_prefix+"Interface::allKnownRights()\n{\n"; + code+="\tQList ret;ret"; + for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_QTOUT_H +#define WOC_QTOUT_H + +#include "processor.h" + +#include "mfile.h" + +class QDomElement; + +class WocQtClientOut:public WocOutput +{ + public: + WocQtClientOut(QDomElement&); + ~WocQtClientOut(); + protected: + virtual void finalize(); + virtual void newClass(const WocClass&); + virtual void newTable(const WocTable&); + virtual void newTransaction(const WocTransaction&); + private: + QString m_basedir,m_subdir,m_prefix; + MFile m_pri,m_iface,m_ifacecpp,m_hdr; + bool m_clean; + + /**helper: adds a file to the project file*/ + void addFile(QString basename); + /**helper: generate enums for classes*/ + void classEnums(const WocClass&,MFile&,MFile&,QString); + /**helper: generate properties*/ + void classProperties(const WocClass&,MFile&,MFile&); + /**helper: generate constructors/deserializer/copiers*/ + void classDeserializer(const WocClass&,MFile&,MFile&,QString); + /**helper: generate serializers*/ + void classSerializers(const WocClass&,MFile&,MFile&,QString); + /**helper: generate a proper Qt type for a property*/ + QString qttype(const WocClass&,QString,bool dolist=true); + + enum InOut{In,Out}; + /**helper: generate a proper QT type for a transaction variable*/ + 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 generates the transaction input encoding*/ + QString trnInput(const WocTransaction&); + /**helper generates the transaction output decoding*/ + QString trnOutput(const WocTransaction&); + /**helper generates enums and strings for all transactions*/ + void trnList(); +}; + +#endif diff --git a/woc/woc.cpp b/woc/woc.cpp new file mode 100644 index 0000000..05b4dd8 --- /dev/null +++ b/woc/woc.cpp @@ -0,0 +1,36 @@ +// +// C++ Implementation: woc +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include +#include + +#include "processor.h" + +int main(int argc,char**argv) +{ + QCoreApplication app(argc,argv); + //get arguments + QStringList args=app.arguments(); + args.removeFirst(); + //process files + WocProcessor proc; + for(int i=0;i