From: konrad Date: Mon, 26 Jul 2010 20:54:38 +0000 (+0000) Subject: refactored woc to prepare for new targets X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=18ab2034ff3c26f82c139d1c5eb4e052ba197cfe;p=web%2Fkonrad%2Fpack.git refactored woc to prepare for new targets git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@573 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/woc/phpclass.cpp b/woc/phpclass.cpp new file mode 100644 index 0000000..1019988 --- /dev/null +++ b/woc/phpclass.cpp @@ -0,0 +1,531 @@ +// +// C++ Implementation: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "phpout.h" +#include "phpclass.h" + +#include +#include + +#include "phpconst.h" + +WocPHPClass::WocPHPClass(WocPHPOut* p) +{ + m_parent=p; + connect(this,SIGNAL(errorFound()),p,SIGNAL(errorFound())); +} + +void WocPHPClass::finalize() +{ +} + +void WocPHPClass::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()); + + //prop to array conversion + tf.write(classPropertiesList(cls).toAscii()); + + //end of class + code="\n//end of class\n};\n"; + tf.write(code.toAscii()); + + tf.write(PHPEND); + tf.close(); +} + +QString WocPHPClass::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 WocPHPClass::classPropertiesList(const WocClass&cls) +{ + QString code; + QStringList k=cls.propertyNames(); + code+="public function propertyArray(){\n\treturn array("; + for(int i=0;i"; + //is it a list? + if(cls.propertyIsList(k[i])){ + //lists... + //object? + if(cls.propertyIsObject(k[i])) + code+="array_map(\"WObject::objectToArray\",$this->prop_"+k[i]+")"; + else + code+="$this->prop_"+k[i]; + }else{ + //non-lists... + //object? + if(cls.propertyIsObject(k[i])) + code+="WObject::objectToArray($this->prop_"+k[i]+")"; + else + code+="$this->prop_"+k[i]; + } + } + code+=");\n}\n"; + + return code; +} + +QString WocPHPClass::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 WocPHPClass::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 WocPHPClass::classMappings(const WocClass&cls) +{ + //don't do it for client mode (clients do not have a DB) + if(m_parent->ptable==0)return QString(); + //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 WocPHPClass::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"; + //is it an attribute? + if(cls.propertyIsAttribute(prop)) + return code+"\tif($p!==null)$root->setAttribute(\""+prop+"\",$this->getstr_"+prop+"());\n"; + //is it an element? + if(cls.propertyIsElement(prop)) + return code+"\tif($p!==null)$root->appendChild($xml->createElement(\""+prop+"\",xq($this->getstr_"+prop+"())));\n"; + //is it a class? + if(cls.propertyIsObject(prop)) + return code+"\tif(is_a($p,\"WO"+cls.propertyPlainType(prop)+"\"))$root->appendChild($p->toXml($xml,\""+prop+"\"));\n"; + //anything else? + qDebug("Warning: end of WocPHPClass::propertyToXml - this code should not be reachable."); + return "//internal generator error!\n"; +} diff --git a/woc/phpclass.h b/woc/phpclass.h new file mode 100644 index 0000000..fc67a26 --- /dev/null +++ b/woc/phpclass.h @@ -0,0 +1,67 @@ +// +// C++ Interface: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PHPOUT_CLASS_H +#define WOC_PHPOUT_CLASS_H + + +class WocPHPOut; +class WocClass; + +#include + +/**generates output for a PHP server side*/ +class WocPHPClass:public QObject +{ + Q_OBJECT + public: + /**initializes the output object*/ + WocPHPClass(WocPHPOut*); + /**writes any last words after parsing finished*/ + virtual void finalize(); + /**creates a class*/ + virtual void newClass(const WocClass&); + + protected: + WocPHPOut*m_parent; + + /**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: generate the property to array converter, eg. for renderers like for Twig*/ + QString classPropertiesList(const WocClass&); + signals: + void errorFound(); +}; + +#endif diff --git a/woc/phpconst.h b/woc/phpconst.h new file mode 100644 index 0000000..718dac7 --- /dev/null +++ b/woc/phpconst.h @@ -0,0 +1,33 @@ +// +// C++ Implementation: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PHP_CONST_H +#define WOC_PHP_CONST_H + +static const QByteArray PHPSTART(""); + +#ifndef WOC_PHP_NO_WRAP +#define m_basedir m_parent->m_basedir +#define m_subdir m_parent->m_subdir +#define m_fileext m_parent->m_fileext +#define m_transbase m_parent->m_transbase +#define m_loader m_parent->m_loader +#define m_schema m_parent->m_schema +#define m_transact m_parent->m_transact +#define className m_parent->className +#define abstractClassName m_parent->abstractClassName +#define trnClassName m_parent->trnClassName +#define addLoad m_parent->addLoad +#endif + +#endif diff --git a/woc/phpctrans.cpp b/woc/phpctrans.cpp new file mode 100644 index 0000000..3719a5e --- /dev/null +++ b/woc/phpctrans.cpp @@ -0,0 +1,419 @@ +// +// C++ Implementation: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "phpout.h" +#include "phpctrans.h" + +#include +#include + +#include "phpconst.h" + +static const QByteArray TRANSACTCLASS("class WobTransaction extends WobTransactionBase\n{\n"); +static const QByteArray TRANSACTSTART(" static public function handle(){\n try{switch(WobTransactionBase::getTransactionName()){\n"); +static const QByteArray TRANSACTEND("\tdefault:WobTransactionBase::noSuchTransaction();break;\n }}catch(WobTransactionError $er){$er->printXml();}\n }\n"); + +WocPHPClientTransaction::WocPHPClientTransaction(WocPHPOut*p ): WocPHPTransaction(p) +{ + //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 WocPHPClientTransaction::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 WocPHPClientTransaction::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;inotAuthenticated();\n"; + break; + case WocTransaction::Auth: + code+="\t/*security check: authenticated*/\n"; + code+="\tif(!$this->isAuthenticated())$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+="\t$this->commitTransaction();\n}\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 WocPHPClientTransaction::trnConstruct(const WocTransaction&trn) +{ + QString code="public function __construct(){\n\tparent::__construct();\n"; + code+="\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 WocPHPClientTransaction::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 WocPHPClientTransaction::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-"+trn.name()+"\");\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 WocPHPClientTransaction::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]+"\"];}\n"; + QString add; + QString t=trn.outputType(sl[i]); + code+="public function set"+sl[i]+"($v){\n"; + if(trn.isListType(t)){ + add="public function add"+sl[i]+"($vv){\n"; + code+="\t$this->aoutput[\""+sl[i]+"\"]=array();\n"; + code+="\tforeach($v as $vv){\n"; + if(trn.isIntType(t)){ + code+="\t\tif(is_numeric($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv+0;\n"; + add+="\tif(is_numeric($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv+0;\n"; + }else + if(trn.isBoolType(t)){ + code+="\t\tif(is_bool($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv!=false;\n"; + add+="\tif(is_bool($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv!=false;\n"; + }else + if(trn.isObjectType(t)){ + code+="\t\tif(is_a($vv,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+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 WocPHPClientTransaction::trnExecute(const WocTransaction&trn) +{ + //the execute function is split into a static and non-static part, + //since the code from the wolf file assumes to be inside the instance + QStringList in=trn.inputNames(); + //static wrapper for execution + QString code="static public function execute("; + for(int i=0;ihandleException($ex);\n\t}\n"; + code+="\tself::$running=\"\";\n}\n"; + return code; +} + +QString WocPHPClientTransaction::trnPrivileges(const WocTransaction&trn) +{ + //privilege inventory + QString code; + code+="static public function privileges(){\n\treturn array("; + QString cn=trnClassName(trn); + QStringList priv=trn.privileges(); + for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PHPOUT_CTRANS_H +#define WOC_PHPOUT_CTRANS_H + +#include "phpout.h" + + +/**generates output for a PHP server side*/ +class WocPHPClientTransaction:public WocPHPTransaction +{ + public: + /**initializes the output object*/ + WocPHPClientTransaction(WocPHPOut*); + protected: + /**writes any last words after parsing finished*/ + virtual void finalize(); + /**creates a transaction*/ + virtual void newTransaction(const WocTransaction&); + private: + + /**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&); +}; + +#endif diff --git a/woc/phpdb.cpp b/woc/phpdb.cpp new file mode 100644 index 0000000..e99e938 --- /dev/null +++ b/woc/phpdb.cpp @@ -0,0 +1,221 @@ +// +// C++ Implementation: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "phpout.h" +#include "phpdb.h" + +#include + +#include "phpconst.h" + +static const QByteArray SCHEMASTART("class WobSchema extends WobSchemaBase\n{\nfunction __construct(){\n\tparent::__construct();\n"); +static const QByteArray SCHEMAEND("}};\n"); + +WocPHPTable::WocPHPTable(WocPHPOut* p) + :m_parent(p) +{ + connect(this,SIGNAL(errorFound()),p,SIGNAL(errorFound())); + + //create schema file + m_schema.setFileName(m_basedir+"/"+m_subdir+"/schema"+m_fileext); + if(!m_schema.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: PHP Server Generator - cannot create DB schema file."); + emit errorFound(); + return; + } + m_schema.write(PHPSTART); + m_schema.write(SCHEMASTART); + m_schema.write(("\tself::$sversion=\""+WocProcessor::instance()->dbVersion()+"\";\n").toAscii()); + addLoad("WobSchema","schema"); +} + +void WocPHPTable::finalize() +{ + if(m_schema.isOpen()){ + m_schema.write(SCHEMAEND); + m_schema.write(PHPEND); + m_schema.close(); + } +} + +void WocPHPTable::newTable(const WocTable&tbl) +{ + if(!m_loader.isOpen())return; + WocProcessor *woc=WocProcessor::instance(); + //create table file + QString fn=m_subdir+"/wt_"+tbl.name()+m_fileext; + QFile tf(m_basedir+"/"+fn); + if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: cannot create PHP table file %s.",fn.toAscii().data()); + emit errorFound(); + return; + } + tf.write(PHPSTART); + QString code="/* TRANSLATOR WT"+tbl.name()+" */\nclass WT"+tbl.name()+" extends "+tbl.baseClass()+"\n{\n"; + //initializer + code+="protected function __construct(array $data,$isfromdb){parent::__construct($data,$isfromdb,\""+tbl.name()+"\");}\n\n"; + + //static new instance for insert only + code+="public static function newRow(array $data=array()){return new WT"+tbl.name()+"($data,false);}\n\n"; + + //static get instance + QStringList cols=tbl.columns(); + QStringList pcols=tbl.primaryColumns(); + //header + code+="public static function getFromDB("; + 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+="\tself::$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()); +} diff --git a/woc/phpdb.h b/woc/phpdb.h new file mode 100644 index 0000000..5c9193d --- /dev/null +++ b/woc/phpdb.h @@ -0,0 +1,35 @@ +// +// C++ Interface: phpout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PHPOUT_DB_H +#define WOC_PHPOUT_DB_H + +#include "phpout.h" + +/**generates output for a PHP server side*/ +class WocPHPTable:public QObject +{ + Q_OBJECT + public: + /**initializes the output object*/ + WocPHPTable(WocPHPOut*); + /**writes any last words after parsing finished*/ + virtual void finalize(); + /**creates a class*/ + virtual void newTable(const WocTable&); + private: + WocPHPOut*m_parent; + signals: + void errorFound(); +}; + +#endif diff --git a/woc/phpout.cpp b/woc/phpout.cpp index 211bc0a..c204e26 100644 --- a/woc/phpout.cpp +++ b/woc/phpout.cpp @@ -11,22 +11,31 @@ // #include "phpout.h" +#include "phpdb.h" +#include "phpctrans.h" +#include "phpstrans.h" +#include "phpclass.h" #include #include -static const QByteArray PHPSTART(""); +#define WOC_PHP_NO_WRAP +#include "phpconst.h" static const QByteArray SCHEMASTART("class WobSchema extends WobSchemaBase\n{\nfunction __construct(){\n\tparent::__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(){\n try{switch(WobTransactionBase::getTransactionName()){\n"); -static const QByteArray TRANSACTEND("\tdefault:WobTransactionBase::noSuchTransaction();break;\n }}catch(WobTransactionError $er){$er->printXml();}\n }\n"); - WocPHPServerOut::WocPHPServerOut(const QDomElement&el) + :WocPHPOut(el) +{ + pclass=new WocPHPClass(this); + ptable=new WocPHPTable(this); + ptrans=new WocPHPServerTransaction(this); +} + +WocPHPOut::WocPHPOut(const QDomElement&el) { + pclass=0;ptable=0;ptrans=0; qDebug("Info: creating PHP Server Output Generator."); m_basedir=WocProcessor::instance()->baseDir()+"/"+el.attribute("sourceDir","."); m_subdir=el.attribute("subDir","phpwob"); @@ -50,1094 +59,45 @@ WocPHPServerOut::WocPHPServerOut(const QDomElement&el) } m_loader.write(PHPSTART); m_loader.write(QString("$d=dirname(__FILE__);\n").toAscii()); - //create schema file - m_schema.setFileName(m_basedir+"/"+m_subdir+"/schema"+m_fileext); - if(!m_schema.open(QIODevice::ReadWrite|QIODevice::Truncate)){ - qDebug("Error: PHP Server Generator - cannot create DB schema file."); - emit errorFound(); - return; - } - m_schema.write(PHPSTART); - m_schema.write(SCHEMASTART); - m_schema.write(("\tself::$sversion=\""+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;ifinalize(); + if(ptable)ptable->finalize(); + if(ptrans)ptrans->finalize(); if(m_loader.isOpen()){ m_loader.write(PHPEND); m_loader.close(); } - if(m_schema.isOpen()){ - m_schema.write(SCHEMAEND); - m_schema.write(PHPEND); - m_schema.close(); - } - if(m_transact.isOpen()){ - m_transact.write(TRANSACTEND); - transInfo2(); - m_transact.write("};\n"); - m_transact.write(PHPEND); - m_transact.close(); - } } -void WocPHPServerOut::newTable(const WocTable&tbl) -{ - if(!m_loader.isOpen())return; - WocProcessor *woc=WocProcessor::instance(); - //create table file - QString fn=m_subdir+"/wt_"+tbl.name()+m_fileext; - QFile tf(m_basedir+"/"+fn); - if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){ - qDebug("Error: cannot create PHP table file %s.",fn.toAscii().data()); - emit errorFound(); - return; - } - tf.write(PHPSTART); - QString code="/* TRANSLATOR WT"+tbl.name()+" */\nclass WT"+tbl.name()+" extends "+tbl.baseClass()+"\n{\n"; - //initializer - code+="protected function __construct(array $data,$isfromdb){parent::__construct($data,$isfromdb,\""+tbl.name()+"\");}\n\n"; - - //static new instance for insert only - code+="public static function newRow(array $data=array()){return new WT"+tbl.name()+"($data,false);}\n\n"; - - //static get instance - QStringList cols=tbl.columns(); - QStringList pcols=tbl.primaryColumns(); - //header - code+="public static function getFromDB("; - 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+="\tself::$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) +void WocPHPOut::addLoad(QString cn,QString fn) { QString ld="wob_autoclass(\""+cn+"\",$d.\"/"+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()); - - //prop to array conversion - tf.write(classPropertiesList(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::classPropertiesList(const WocClass&cls) -{ - QString code; - QStringList k=cls.propertyNames(); - code+="public function propertyArray(){\n\treturn array("; - for(int i=0;i"; - //is it a list? - if(cls.propertyIsList(k[i])){ - //lists... - //object? - if(cls.propertyIsObject(k[i])) - code+="array_map(\"WObject::objectToArray\",$this->prop_"+k[i]+")"; - else - code+="$this->prop_"+k[i]; - }else{ - //non-lists... - //object? - if(cls.propertyIsObject(k[i])) - code+="WObject::objectToArray($this->prop_"+k[i]+")"; - else - code+="$this->prop_"+k[i]; - } - } - code+=");\n}\n"; - - 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) +void WocPHPOut::newTransaction(const WocTransaction&trn) { - 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"; - //is it an attribute? - if(cls.propertyIsAttribute(prop)) - return code+"\tif($p!==null)$root->setAttribute(\""+prop+"\",$this->getstr_"+prop+"());\n"; - //is it an element? - if(cls.propertyIsElement(prop)) - return code+"\tif($p!==null)$root->appendChild($xml->createElement(\""+prop+"\",xq($this->getstr_"+prop+"())));\n"; - //is it a class? - if(cls.propertyIsObject(prop)) - return code+"\tif(is_a($p,\"WO"+cls.propertyPlainType(prop)+"\"))$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"; + if(ptrans)ptrans->newTransaction(trn); } -void WocPHPServerOut::newTransaction(const WocTransaction&trn) +void WocPHPOut::newClass(const WocClass& cls) { - //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 "+m_transbase+"{\n"; - //constructor - code+=trnConstruct(trn); - tf.write(code.toAscii()); - - //request handler: - code="public function handleRequest(){\n"; - code+="\t$this->startTransaction("+QString(trn.isDbUpdating()?"true":"false")+");\n"; - - //security handling - switch(trn.authMode()){ - case WocTransaction::Checked: - code+="\t/*security check: authenticated and authorized*/\n"; - code+="\tif(!$this->isAuthorized(\""+trn.name()+"\""+"))$this->notAuthenticated();\n"; - break; - case WocTransaction::Auth: - code+="\t/*security check: authenticated*/\n"; - code+="\tif(!$this->isAuthenticated())$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+="\t$this->commitTransaction();\n}\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()); + if(pclass)pclass->newClass(cls); } -QString WocPHPServerOut::trnConstruct(const WocTransaction&trn) +void WocPHPOut::newTable(const WocTable& tbl) { - QString code="public function __construct(){\n\tparent::__construct();\n"; - code+="\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; + if(ptable)ptable->newTable(tbl); } -QString WocPHPServerOut::trnInput(const WocTransaction&trn) +WocPHPTransaction::WocPHPTransaction(WocPHPOut* p) { - 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-"+trn.name()+"\");\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; + m_parent=p; + connect(this,SIGNAL(errorFound()),p,SIGNAL(errorFound())); } -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]+"\"];}\n"; - QString add; - QString t=trn.outputType(sl[i]); - code+="public function set"+sl[i]+"($v){\n"; - if(trn.isListType(t)){ - add="public function add"+sl[i]+"($vv){\n"; - code+="\t$this->aoutput[\""+sl[i]+"\"]=array();\n"; - code+="\tforeach($v as $vv){\n"; - if(trn.isIntType(t)){ - code+="\t\tif(is_numeric($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv+0;\n"; - add+="\tif(is_numeric($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv+0;\n"; - }else - if(trn.isBoolType(t)){ - code+="\t\tif(is_bool($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv!=false;\n"; - add+="\tif(is_bool($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv!=false;\n"; - }else - if(trn.isObjectType(t)){ - code+="\t\tif(is_a($vv,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+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) -{ - //the execute function is split into a static and non-static part, - //since the code from the wolf file assumes to be inside the instance - QStringList in=trn.inputNames(); - //static wrapper for execution - QString code="static public function execute("; - for(int i=0;ihandleException($ex);\n\t}\n"; - code+="\tself::$running=\"\";\n}\n"; - return code; -} - -QString WocPHPServerOut::trnPrivileges(const WocTransaction&trn) -{ - //privilege inventory - QString code; - code+="static public function privileges(){\n\treturn array("; - QString cn=trnClassName(trn); - QStringList priv=trn.privileges(); - for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "phpout.h" +#include "phpstrans.h" + +#include +#include + +#include "phpconst.h" + +static const QByteArray TRANSACTCLASS("class WobTransaction extends WobTransactionBase\n{\n"); +static const QByteArray TRANSACTSTART(" static public function handle(){\n try{switch(WobTransactionBase::getTransactionName()){\n"); +static const QByteArray TRANSACTEND("\tdefault:WobTransactionBase::noSuchTransaction();break;\n }}catch(WobTransactionError $er){$er->printXml();}\n }\n"); + +WocPHPServerTransaction::WocPHPServerTransaction(WocPHPOut*p ): WocPHPTransaction(p) +{ + //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 WocPHPServerTransaction::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 WocPHPServerTransaction::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;inotAuthenticated();\n"; + break; + case WocTransaction::Auth: + code+="\t/*security check: authenticated*/\n"; + code+="\tif(!$this->isAuthenticated())$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+="\t$this->commitTransaction();\n}\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 WocPHPServerTransaction::trnConstruct(const WocTransaction&trn) +{ + QString code="public function __construct(){\n\tparent::__construct();\n"; + code+="\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 WocPHPServerTransaction::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 WocPHPServerTransaction::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-"+trn.name()+"\");\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 WocPHPServerTransaction::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]+"\"];}\n"; + QString add; + QString t=trn.outputType(sl[i]); + code+="public function set"+sl[i]+"($v){\n"; + if(trn.isListType(t)){ + add="public function add"+sl[i]+"($vv){\n"; + code+="\t$this->aoutput[\""+sl[i]+"\"]=array();\n"; + code+="\tforeach($v as $vv){\n"; + if(trn.isIntType(t)){ + code+="\t\tif(is_numeric($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv+0;\n"; + add+="\tif(is_numeric($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv+0;\n"; + }else + if(trn.isBoolType(t)){ + code+="\t\tif(is_bool($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv!=false;\n"; + add+="\tif(is_bool($vv))$this->aoutput[\""+sl[i]+"\"][]=$vv!=false;\n"; + }else + if(trn.isObjectType(t)){ + code+="\t\tif(is_a($vv,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+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 WocPHPServerTransaction::trnExecute(const WocTransaction&trn) +{ + //the execute function is split into a static and non-static part, + //since the code from the wolf file assumes to be inside the instance + QStringList in=trn.inputNames(); + //static wrapper for execution + QString code="static public function execute("; + for(int i=0;ihandleException($ex);\n\t}\n"; + code+="\tself::$running=\"\";\n}\n"; + return code; +} + +QString WocPHPServerTransaction::trnPrivileges(const WocTransaction&trn) +{ + //privilege inventory + QString code; + code+="static public function privileges(){\n\treturn array("; + QString cn=trnClassName(trn); + QStringList priv=trn.privileges(); + for(int i=0;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PHPOUT_STRANS_H +#define WOC_PHPOUT_STRANS_H + +#include "phpout.h" + + +/**generates output for a PHP server side*/ +class WocPHPServerTransaction:public WocPHPTransaction +{ + public: + /**initializes the output object*/ + WocPHPServerTransaction(WocPHPOut*); + protected: + /**writes any last words after parsing finished*/ + virtual void finalize(); + /**creates a transaction*/ + virtual void newTransaction(const WocTransaction&); + private: + + /**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&); +}; + +#endif diff --git a/woc/procclass.cpp b/woc/procclass.cpp new file mode 100644 index 0000000..2170fb3 --- /dev/null +++ b/woc/procclass.cpp @@ -0,0 +1,324 @@ +// +// 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 + +/****************************************************************************** + * WocClass + ******************************************************************************/ + +WocClass::WocClass(const QDomElement&cls) +{ + //scan basics + m_valid=true; + m_abstract=str2bool(cls.attribute("abstract","0")); + WocProcessor *woc=WocProcessor::instance(); + QRegExp symok("[a-z_][a-z0-9_]*",Qt::CaseInsensitive); + m_name=cls.attribute("name"); + if(m_name==""){ + qDebug("Error: unnamed class at line %i column %i.",cls.lineNumber(),cls.columnNumber()); + m_valid=false; + return; + } + if(woc->hasClass(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;i, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PROCESSOR_CLASS_H +#define WOC_PROCESSOR_CLASS_H + +#include +#include +#include +#include +#include + +/**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; +}; + +#endif diff --git a/woc/processor.cpp b/woc/processor.cpp index e8184be..bb224c1 100644 --- a/woc/processor.cpp +++ b/woc/processor.cpp @@ -344,887 +344,3 @@ WocOutput::WocOutput() } WocOutput::~WocOutput(){} - -/****************************************************************************** - * WocClass - ******************************************************************************/ - -WocClass::WocClass(const QDomElement&cls) -{ - //scan basics - m_valid=true; - m_abstract=str2bool(cls.attribute("abstract","0")); - WocProcessor *woc=WocProcessor::instance(); - QRegExp symok("[a-z_][a-z0-9_]*",Qt::CaseInsensitive); - m_name=cls.attribute("name"); - if(m_name==""){ - qDebug("Error: unnamed class at line %i column %i.",cls.lineNumber(),cls.columnNumber()); - m_valid=false; - return; - } - if(woc->hasClass(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;idbUpdatingDefault(); - //input tag - QList 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 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;} - - /**returns whether this transaction is considered to update the database*/ - bool isDbUpdating()const{return m_update;} - private: - QString m_name; - bool m_valid,m_update; - 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 diff --git a/woc/proctable.cpp b/woc/proctable.cpp new file mode 100644 index 0000000..8122163 --- /dev/null +++ b/woc/proctable.cpp @@ -0,0 +1,444 @@ +// +// 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 + + +/****************************************************************************** + * WocTable + ******************************************************************************/ + +WocTable::WocTable() +{ + m_backup=m_valid=m_audit=false; +} + +WocTable::WocTable(const QDomElement&tbl) +{ + m_valid=true; + //parse XML + m_name=tbl.attribute("name"); + WocProcessor*woc=WocProcessor::instance(); + QRegExp good("[a-z][a-z0-9_]*",Qt::CaseInsensitive); + //check name syntax, check it does not exist yet + if(woc->hasTable(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, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_PROCESSOR_TABLE_H +#define WOC_PROCESSOR_TABLE_H + +#include +#include +#include +#include +#include + + +/**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); +}; + + +#endif diff --git a/woc/proctrans.cpp b/woc/proctrans.cpp new file mode 100644 index 0000000..99ef997 --- /dev/null +++ b/woc/proctrans.cpp @@ -0,0 +1,187 @@ +// +// 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 + +/****************************************************************************** + * WocTransaction + ******************************************************************************/ + +WocTransaction::WocTransaction(const QDomElement&root) +{ + m_valid=true; + m_mode=Checked; + QRegExp rval("[a-z][a-z0-9_]*",Qt::CaseInsensitive); + //get basics + m_name=root.attribute("name"); + if(!rval.exactMatch(m_name)){ + qDebug("Error: invalid transaction name %s.",m_name.toAscii().data()); + m_valid=false; + return; + } + qDebug("Info: parsing transaction %s",m_name.toAscii().data()); + if(root.hasAttribute("mode")){ + QString m=root.attribute("mode").toLower(); + if(m=="checked")m_mode=Checked;else + if(m=="auth")m_mode=Auth;else + if(m=="open")m_mode=Open; + else{ + qDebug("Error: invalid transaction mode %s in transaction %s, must be checked, auth, or open.",m.toAscii().data(),m_name.toAscii().data()); + m_valid=false; + return; + } + } + if(root.hasAttribute("updating")) + m_update=str2bool(root.attribute("updating")); + else + m_update=WocProcessor::instance()->dbUpdatingDefault(); + //input tag + QList 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_TRANS_H +#define WOC_PROCESSOR_TRANS_H + +#include +#include +#include +#include +#include + +/**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;} + + /**returns whether this transaction is considered to update the database*/ + bool isDbUpdating()const{return m_update;} + private: + QString m_name; + bool m_valid,m_update; + AuthMode m_mode; + QMap m_call; + QList >m_input,m_output; + QStringList m_privileges; + //docu + QStringList m_docstrings; + QMapm_indoc,m_outdoc,m_privdoc; +}; + +#endif diff --git a/woc/qtclass.cpp b/woc/qtclass.cpp new file mode 100644 index 0000000..8aff833 --- /dev/null +++ b/woc/qtclass.cpp @@ -0,0 +1,374 @@ +// +// C++ Implementation: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "qtout.h" +#include "qtclass.h" + +#include +#include + +#include "qtconst.h" + +WocQtClass::WocQtClass(WocQtOut* p) +{ + m_parent=p; + connect(this,SIGNAL(errorFound()),p,SIGNAL(errorFound())); +} + +WocQtClass::~WocQtClass() +{ +} + +void WocQtClass::finalize() +{ +} + + +void WocQtClass::newClass(const WocClass&cls) +{ + QString cn=m_prefix+"O"+cls.name(); + QString cna=cn; + if(cls.isAbstract("qt"))cna+="Abstract"; + addFile(cna); + MFile hdr(m_basedir+"/"+m_subdir+"/"+cna+".h"); + MFile src(m_basedir+"/"+m_subdir+"/"+cna+".cpp"); + if(!hdr.open(QIODevice::WriteOnly|QIODevice::Truncate) || + !src.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + qDebug("Error: cannot create class files for class %s.",cn.toAscii().data()); + emit errorFound(); + return; + } + //lead in + hdr.write(QByteArray(HDRSTART).replace("%",cna.toAscii())); + src.write(QByteArray(SRCSTART).replace("%",cna.toAscii())); + + QString hcd; + QString scd; + //includes + hcd="#include \""+cls.clientBaseClass()+".h\"\n#include \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, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_QTOUT_CLASS_H +#define WOC_QTOUT_CLASS_H + +#include "mfile.h" +#include + +class QDomElement; +class WocClass; +class WocQtOut; + +class WocQtClass:public QObject +{ + Q_OBJECT + public: + WocQtClass(WocQtOut*); + ~WocQtClass(); + virtual void finalize(); + virtual void newClass(const WocClass&); + private: + WocQtOut*m_parent; + + /**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); + signals: + void errorFound(); +}; + +#endif diff --git a/woc/qtconst.h b/woc/qtconst.h new file mode 100644 index 0000000..214b216 --- /dev/null +++ b/woc/qtconst.h @@ -0,0 +1,50 @@ +// +// C++ Implementation: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_QT_CONST_H +#define WOC_QT_CONST_H + +//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"; + +#ifndef QT_OUT_NO_WRAP +#define m_basedir m_parent->m_basedir +#define m_subdir m_parent->m_subdir +#define m_prefix m_parent->m_prefix +#define m_transbase m_parent->m_transbase +#define m_pri m_parent->m_pri +#define m_iface m_parent->m_iface +#define m_ifacecpp m_parent->m_ifacecpp +#define m_hdr m_parent->m_hdr +#define m_clean m_parent->m_clean +#define qttype m_parent->qttype +#define qtobjtype m_parent->qtobjtype +#define addFile m_parent->addFile +#endif + +#endif diff --git a/woc/qtctrans.cpp b/woc/qtctrans.cpp new file mode 100644 index 0000000..e38b36e --- /dev/null +++ b/woc/qtctrans.cpp @@ -0,0 +1,330 @@ +// +// C++ Implementation: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "qtout.h" +#include "qtctrans.h" + +#include +#include + +#include "qtconst.h" + +WocQtClientTransaction::WocQtClientTransaction(WocQtOut*p) + :WocQtTransaction(p) +{} +WocQtClientTransaction::~WocQtClientTransaction(){} + +void WocQtClientTransaction::finalize() +{ + trnList(); +} + +void WocQtClientTransaction::newTransaction(const WocTransaction&trn) +{ + QString cn=m_prefix+"T"+trn.name(); + addFile(cn); + MFile hdr(m_basedir+"/"+m_subdir+"/"+cn+".h"); + MFile src(m_basedir+"/"+m_subdir+"/"+cn+".cpp"); + if(!hdr.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(); + return; + } + //basics + QStringList in=trn.inputNames(); + QStringList out=trn.outputNames(); + //lead in + hdr.write(QByteArray(HDRSTART).replace("%",cn.toAscii())); + src.write(QByteArray(SRCSTART).replace("%",cn.toAscii())); + QString hcd; + QString scd; + hcd="#include \""+m_transbase+".h\"\n"; + scd+="#include \"WInterface.h\"\n#include \n"; + for(int i=0;i\n"; + } + for(int i=0;i\n"; + } + hcd+="\nclass "+cn+":public "+m_transbase+"\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:"+m_transbase+"(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_CTRANS_H +#define WOC_QTOUT_CTRANS_H + +#include "qtout.h" + +class WocQtOut; +class WocTransaction; +class WocClass; + +class WocQtClientTransaction:public WocQtTransaction +{ + public: + WocQtClientTransaction(WocQtOut*); + ~WocQtClientTransaction(); + virtual void finalize(); + virtual void newTransaction(const WocTransaction&); + private: + /**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/qtdb.cpp b/woc/qtdb.cpp new file mode 100644 index 0000000..217945a --- /dev/null +++ b/woc/qtdb.cpp @@ -0,0 +1,19 @@ +// +// C++ Implementation: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#include "qtout.h" +#include "qtdb.h" + +WocQtTable::WocQtTable(WocQtOut*){} +WocQtTable::~WocQtTable(){} +void WocQtTable::finalize(){} +void WocQtTable::newTable(const WocTable&){} diff --git a/woc/qtdb.h b/woc/qtdb.h new file mode 100644 index 0000000..15c1768 --- /dev/null +++ b/woc/qtdb.h @@ -0,0 +1,34 @@ +// +// C++ Interface: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_QTOUT_DB_H +#define WOC_QTOUT_DB_H + +#include "processor.h" + +#include "mfile.h" + +class QDomElement; +class WocQtOut; + +class WocQtTable +{ + public: + WocQtTable(WocQtOut*); + ~WocQtTable(); + virtual void finalize(); + virtual void newTable(const WocTable&); + private: + WocQtOut*m_parent; +}; + +#endif diff --git a/woc/qtout.cpp b/woc/qtout.cpp index b483d75..b4bf783 100644 --- a/woc/qtout.cpp +++ b/woc/qtout.cpp @@ -11,31 +11,21 @@ // #include "qtout.h" +#include "qtctrans.h" +#include "qtstrans.h" +#include "qtclass.h" +#include "qtdb.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"; +#define QT_OUT_NO_WRAP +#include "qtconst.h" -//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) +WocQtOut::WocQtOut(QDomElement&el) { + qclass=0;qtable=0;qtrans=0; + qDebug("Info: creating Qt Client Output Generator."); m_basedir=WocProcessor::instance()->baseDir()+"/"+el.attribute("sourceDir","."); m_subdir=el.attribute("subDir","qtwob"); @@ -96,11 +86,14 @@ WocQtClientOut::WocQtClientOut(QDomElement&el) addFile(m_prefix.toAscii()+"Interface"); } -WocQtClientOut::~WocQtClientOut(){} +WocQtOut::~WocQtOut(){} -void WocQtClientOut::finalize() +void WocQtOut::finalize() { - trnList(); + if(qclass)qclass->finalize(); + if(qtable)qtable->finalize(); + if(qtrans)qtrans->finalize(); + //finish sources m_ifacecpp.write(SRCEND); m_ifacecpp.close(); m_iface.write(QByteArray("};\n")+HDREND); @@ -121,139 +114,29 @@ void WocQtClientOut::finalize() } } -void WocQtClientOut::newTable(const WocTable&){/*not needed, Qt client is a few levels higher*/} - -void WocQtClientOut::newClass(const WocClass&cls) +void WocQtOut::newTable(const WocTable&tbl) { - QString cn=m_prefix+"O"+cls.name(); - QString cna=cn; - if(cls.isAbstract("qt"))cna+="Abstract"; - addFile(cna); - MFile hdr(m_basedir+"/"+m_subdir+"/"+cna+".h"); - MFile src(m_basedir+"/"+m_subdir+"/"+cna+".cpp"); - if(!hdr.open(QIODevice::WriteOnly|QIODevice::Truncate) || - !src.open(QIODevice::WriteOnly|QIODevice::Truncate)){ - qDebug("Error: cannot create class files for class %s.",cn.toAscii().data()); - emit errorFound(); - return; - } - //lead in - hdr.write(QByteArray(HDRSTART).replace("%",cna.toAscii())); - src.write(QByteArray(SRCSTART).replace("%",cna.toAscii())); - - QString hcd; - QString scd; - //includes - hcd="#include \""+cls.clientBaseClass()+".h\"\n#include \n\n"; - QStringList k=cls.propertyNames(); - for(int i=0;inewTable(tbl); +} - //class declaration - hcd+="class "+cna+":public "+cls.clientBaseClass()+"\n{\n"; - hdr.write(hcd.toAscii()); - - //enums - classEnums(cls,hdr,src,cna); - - //properties - classProperties(cls,hdr,src); - - //serializer - classSerializers(cls,hdr,src,cna); - - //deserializer (constructor) - classDeserializer(cls,hdr,src,cna); - - //lead out - hdr.write(QByteArray("\n};\n")); - hdr.write(QByteArray(HDREND).replace("%",cna.toAscii())); - src.write(QByteArray(SRCEND).replace("%",cna.toAscii())); +void WocQtOut::newClass(const WocClass&cls) +{ + if(qclass)qclass->newClass(cls); } -void WocQtClientOut::classEnums(const WocClass&cls,MFile&hdr,MFile&src,QString cn) +void WocQtOut::newTransaction(const WocTransaction&trn) { - QStringList k=cls.enumTypes(); - if(k.size()==0)return; - QString hcd=" public:\n"; - QString scd; - 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;jnewTransaction(trn); } -void WocQtClientOut::classProperties(const WocClass&cls,MFile&hdr,MFile&) +void WocQtOut::addFile(QString bn) { - QStringList k=cls.propertyNames(); - if(k.size()==0)return; - QString hcd,scd; - //declare members - hcd=" protected:\n"; - for(int i=0;i1)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 "+m_transbase+"\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:"+m_transbase+"(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 +// +// + +#include "qtout.h" +#include "qtstrans.h" + +WocQtServerTransaction::WocQtServerTransaction(WocQtOut*p) + :WocQtTransaction(p) +{ +} +WocQtServerTransaction::~WocQtServerTransaction(){} +void WocQtServerTransaction::finalize(){} +void WocQtServerTransaction::newTransaction(const WocTransaction&){} diff --git a/woc/qtstrans.h b/woc/qtstrans.h new file mode 100644 index 0000000..5bfd58d --- /dev/null +++ b/woc/qtstrans.h @@ -0,0 +1,29 @@ +// +// C++ Interface: qtout +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef WOC_QTOUT_STRANS_H +#define WOC_QTOUT_STRANS_H + +#include "qtout.h" + +class WocQtServerTransaction:public WocQtTransaction +{ + public: + WocQtServerTransaction(WocQtOut*); + ~WocQtServerTransaction(); + virtual void finalize(); + virtual void newTransaction(const WocTransaction&); + private: + WocQtOut*m_parent; +}; + +#endif diff --git a/woc/woc.pro b/woc/woc.pro index 0d0a4ad..4877b2c 100644 --- a/woc/woc.pro +++ b/woc/woc.pro @@ -13,16 +13,38 @@ RCC_DIR = .ctmp SOURCES+= \ processor.cpp \ + procclass.cpp \ + proctrans.cpp \ + proctable.cpp \ woc.cpp \ qtout.cpp \ + qtclass.cpp \ + qtdb.cpp \ + qtctrans.cpp \ + qtstrans.cpp \ phpout.cpp \ + phpclass.cpp \ + phpctrans.cpp \ + phpstrans.cpp \ + phpdb.cpp \ htmlout.cpp \ mfile.cpp \ domquery.cpp HEADERS+= \ processor.h \ + procclass.h \ + proctrans.h \ + proctable.h \ phpout.h \ + phpdb.h \ + phpclass.h \ + phpctrans.h \ + phpstrans.h \ qtout.h \ + qtclass.h \ + qtdb.h \ + qtctrans.h \ + qtstrans.cpp \ htmlout.h \ mfile.h \ domquery.h