--- /dev/null
+//
+// C++ Implementation: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "phpout.h"
+#include "phpclass.h"
+
+#include <QDir>
+#include <QDomElement>
+
+#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;i<k.size();i++){
+ code+="protected $prop_"+k[i];
+ if(!cls.propertyIsList(k[i]))code+="=null";
+ code+=";\n";
+ }
+ code+="public function __construct()\n{\n\tparent::__construct();\n";
+ for(int i=0;i<k.size();i++)
+ if(cls.propertyIsList(k[i]))
+ code+="\t$this->prop_"+k[i]+"=array();\n";
+ code+="}\n";
+ return code;
+}
+
+QString WocPHPClass::classEnums(const WocClass&cls)
+{
+ QString code;
+ QStringList k=cls.enumTypes();
+ for(int i=0;i<k.size();i++){
+ code+="//enum "+k[i]+"\n";
+ QList<WocEnum>ev=cls.enumValues(k[i]);
+ for(int j=0;j<ev.size();j++)
+ code+="const "+ev[j].name+"="+QString::number(ev[j].val)+";\n";
+ }
+ return code;
+}
+
+QString WocPHPClass::classProperties(const WocClass&cls)
+{
+ QString code;
+ QStringList k=cls.propertyNames();
+ for(int i=0;i<k.size();i++){
+ code+="\n";
+ //generate validator
+ code+=classPropertyValidator(cls,k[i]);
+ //generic getter
+ code+="public function get"+k[i]+"(){return $this->prop_"+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<k.size();i++){
+ if(i)code+=",";
+ code+="\n\t\t\""+k[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)){
+ QList<WocEnum>ev=cls.enumValues(cls.propertyPlainType(prop));
+ code+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n";
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tif($value=="+QString::number(ev[j].val)+")return true;\n";
+ }
+ code+="\t\treturn false;\n\t}else{\n";
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tif($value==\""+ev[j].name+"\")return true;\n";
+ }
+ code+="\t\treturn false;\n\t}\n";
+ }else
+ if(cls.propertyIsInt(prop))
+ code+="\treturn is_numeric($value);\n";
+ else
+ if(cls.propertyIsString(prop)||cls.propertyIsBlob(prop))
+ code+="\treturn true;\n";//TODO: special handling for astring
+ else
+ if(cls.propertyIsBool(prop))
+ code+="\treturn is_bool($value);\n";
+ else
+ if(cls.propertyIsObject(prop))
+ code+="\treturn is_a($value,\"WO"+cls.propertyPlainType(prop)+"\");\n";
+ else{
+ qDebug("Warning: unable to generate validator for class %s property %s: unknown type.",cls.name().toAscii().data(),prop.toAscii().data());
+ code+="\treturn false;\n";
+ }
+ code+="}\n";
+
+ return code;
+}
+
+QString WocPHPClass::classPropertyListGetters(const WocClass&cls,QString prop)
+{
+ QString code;
+ if(cls.propertyIsString(prop))
+ code+="public function getstrlist_"+prop+"(){return $this->prop_"+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<WocEnum> ev=cls.enumValues(cls.propertyPlainType(prop));
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tcase "+QString::number(ev[j].val)+":$ret[]=\""+ev[j].name+"\";break;\n";
+ }
+ code+="\t\tdefault:$ret[]=null;break;\n\t}\n\treturn $ret;\n}\n";
+ }
+
+ return code;
+}
+
+QString WocPHPClass::classPropertyListSetters(const WocClass&cls,QString prop)
+{
+ QString code;
+ code+="public function clear_"+prop+"(){$this->prop_"+prop+"=array();}\n";
+ QString acode;//body of add_ function, see below
+ code+="public function set"+prop+"(array $values){\n";
+ if(cls.propertyIsEnum(prop)){
+ QList<WocEnum>ev=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;j<ev.size();j++){
+ code+="\t\t\tif($value=="+QString::number(ev[j].val)+"){\n";
+ code+="\t\t\t\t$prop[]="+QString::number(ev[j].val)+";\n";
+ code+="\t\t\t}else\n";
+ acode+="\t\tif($value=="+QString::number(ev[j].val)+"){\n";
+ acode+="\t\t\t$this->prop_"+prop+"[]="+QString::number(ev[j].val)+";\n";
+ acode+="\t\t\treturn true;\n\t\t}\n";
+ }
+ code+="\t\t\treturn false;\n\t\t}else{\n";
+ acode+="\t\treturn false;\n\t}else{\n";
+ for(int j=0;j<ev.size();j++){
+ code+="\t\t\tif($value==\""+ev[j].name+"\"){\n";
+ code+="\t\t\t\t$prop[]="+QString::number(ev[j].val)+";\n";
+ code+="\n\t\t\t}else\n";
+ acode+="\t\tif($value==\""+ev[j].name+"\"){\n";
+ acode+="\t\t\t$this->prop_"+prop+"[]="+QString::number(ev[j].val)+";\n";
+ acode+="\t\t\treturn true;\n\t\t}\n";
+ }
+ code+="\t\t\treturn false;\n\t\t}\n\t}\n";
+ code+="\t$this->prop_"+prop+"=$prop;\n";
+ code+="\treturn true;\n";
+ acode+="\t\treturn false;\n\t}\n";
+ }else
+ if(cls.propertyIsInt(prop)){
+ code+="\t$prop=array();\n\tforeach($values as $value)\n";
+ code+="\t\tif(is_numeric($value)){\n\t\t\t$prop[]=0+$value;\n\t\t}else return false;\n";
+ code+="\t$this->prop_"+prop+"=$prop;\n\treturn true;\n";
+ acode+="\tif(is_numeric($value)){\n";
+ acode+="\t\t$this->prop_"+prop+"=0+$value;\n\t\treturn true;\n\t}else return false;\n";
+ }else
+ if(cls.propertyIsBool(prop)){
+ code+="\t$prop=array();\n\tforeach($values as $value)\n";
+ code+="\t\tif(is_bool($value))$prop[]=$value!=false;else\n";
+ code+="\t\tif($value==\"yes\")$prop[]=true;else\n";
+ code+="\t\tif($value==\"no\")$prop[]=false;else return false;\n";
+ code+="\t$this->prop_"+prop+"=$prop;\n\treturn true;\n";
+ acode+="\tif(is_bool($value)){\n";
+ acode+="\t\t$this->prop_"+prop+"=$value!=false;\n\t\treturn true;\n\t}else return false;\n";
+ }else
+ if(cls.propertyIsString(prop)||cls.propertyIsBlob(prop)){
+ code+="\t$prop=array();\n\tforeach($values as $value)$prop[]=\"\".$value;\n";
+ code+="\t$this->prop_"+prop+"=$prop;\n\treturn true;\n";
+ //TODO: special handling for astring
+ acode+="\t$this->prop_"+prop+"[]=\"\".$value;\n\treturn true;\n";
+ }else
+ if(cls.propertyIsObject(prop)){
+ code+="\t$prop=array();\n\tforeach($values as $value)\n";
+ code+="\t\tif(is_a($value,\"WO"+cls.propertyPlainType(prop)+"\"))\n";
+ code+="\t\t\t$prop[]=$value;\n";
+ code+="\t\telse return false;\n";
+ code+="\t$this->prop_"+prop+"=$prop;\n";
+ code+="\treturn true;\n";
+ acode+="\tif(is_a($value,\"WO"+cls.propertyPlainType(prop)+"\")){\n";
+ acode+="\t\t$this->prop_"+prop+"[]=$value;\n";
+ acode+="\t\treturn true;\n";
+ acode+="\t}else return false;\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";
+ code+="public function add_"+prop+"($value){\n"+acode+"}\n";
+
+ return code;
+}
+
+QString WocPHPClass::classPropertyScalarGetters(const WocClass&cls,QString prop)
+{
+ QString code;
+ if(cls.propertyIsString(prop))
+ code+="public function getstr_"+prop+"(){return $this->prop_"+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<WocEnum> ev=cls.enumValues(cls.propertyPlainType(prop));
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tcase "+QString::number(ev[j].val)+":return translate(\""+abstractClassName(cls)+"\",\""+ev[j].name+"\");\n";
+ }
+ code+="\t\tdefault:return null;\n\t}\n}\n";
+ }
+
+ return code;
+}
+
+QString WocPHPClass::classPropertyScalarSetters(const WocClass&cls,QString prop)
+{
+ QString code;
+ code+="public function set"+prop+"($value){\n";
+ if(cls.propertyIsEnum(prop)){
+ QList<WocEnum>ev=cls.enumValues(cls.propertyPlainType(prop));
+ code+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n";
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tif($value=="+QString::number(ev[j].val)+"){\n";
+ code+="\t\t\t$this->prop_"+prop+"="+QString::number(ev[j].val)+";\n";
+ code+="\t\t\treturn true;\n\t\t}\n";
+ }
+ code+="\t\treturn false;\n\t}else{\n";
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tif($value==\""+ev[j].name+"\"){\n";
+ code+="\t\t\t$this->prop_"+prop+"="+QString::number(ev[j].val)+";\n";
+ code+="\t\t\treturn true;\n\t\t}\n";
+ }
+ code+="\t\treturn false;\n\t}\n";
+ }else
+ if(cls.propertyIsInt(prop))
+ code+="\tif(is_numeric($value)){\n\t\t$this->prop_"+prop+"=0+$value;\n\t\treturn true;\n\t}else return false;\n";
+ else
+ if(cls.propertyIsBool(prop)){
+ code+="\tif(is_bool($value))$this->prop_"+prop+"=$value!=false;else\n";
+ code+="\tif($value==\"yes\")$this->prop_"+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;j<p.size();j++)
+ code+=propertyToXml(cls,p[j]);
+ //return result
+ code+="\treturn $root;\n}\n";
+ return code;
+}
+
+QString WocPHPClass::classDeserializers(const WocClass&cls)
+{
+ QString code;
+ QStringList k;
+ code+="\nstatic public function fromString($txt){\n\t$xml=new DomDocument;\n";
+ code+="\tif(!$xml->loadXml(trim($txt)))";
+ code+="\n\t\tthrow WobXmlException(translate(\""+abstractClassName(cls)+"\",\"Unable to deserialize object of type "+className(cls)+": invalid XML.\"));";
+ code+="\n\treturn self::fromXml($xml,$xml->documentElement);\n}\n";
+ code+="static public function fromXml($xml,$elem){\n\t$data=new "+className(cls)+"();\n";
+ k=cls.propertyNames();
+ for(int i=0;i<k.size();i++){
+ //scan properties
+ if(cls.propertyIsList(k[i])){
+ code+="\t$data->clear_"+k[i]+"();\n";
+ code+="\tforeach(WObject::elementsByTagName($elem,\""+k[i]+"\") as $el){\n";
+ if(cls.propertyIsObject(k[i])){
+ code+="\t\t$data->add_"+k[i]+"(WO"+cls.propertyPlainType(k[i])+"::fromXml($xml,$el));\n";
+ }else if(cls.propertyIsBlob(k[i])){
+ code+="\t\t$data->add_"+k[i]+"(base64_decode($el->textContent));\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;i<k.size();i++){
+ WocTable tab=WocProcessor::instance()->table(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";
+ QMap<QString,QString>map=cls.mapping(k[i]);
+ QStringList mapk=cls.mappingProperties(k[i]);
+ for(int j=0;j<mapk.size();j++){
+ QString meth=cls.mapMethod(k[i],mapk[j],"php");
+ if(meth!="")code+="\t$data->prop_"+mapk[j]+"="+meth+";\n";
+ else code+="\t$data->prop_"+mapk[j]+"=$table->"+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<count($table);$i++)$ret[]=self::fromTable"+k[i]+"($table[$i]);\n";
+ code+="\treturn $ret;\n}\n";
+ //reverse mapping
+ code+="public function toTable"+k[i]+"(&$table){\n";
+ for(int j=0;j<mapk.size();j++){
+ //do not reverse translate method conversions
+ QString meth=cls.mapMethod(k[i],mapk[j],"php").trimmed();
+ if(meth!="")continue;
+ //check that column exists
+ if(tab.hasColumn(map[mapk[j]])){
+ code+="\tif($this->prop_"+mapk[j]+"!==null && $table->"+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";
+}
--- /dev/null
+//
+// C++ Interface: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QObject>
+
+/**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
--- /dev/null
+//
+// C++ Implementation: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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("<?\n//THIS IS AN AUTOGENERATED FILE, DONT CHANGE!\n\n");
+static const QByteArray PHPEND("\n//END OF AUTOGENERATED FILE\n?>");
+
+#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
--- /dev/null
+//
+// C++ Implementation: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "phpout.h"
+#include "phpctrans.h"
+
+#include <QDir>
+#include <QDomElement>
+
+#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;i<tns.size();i++){
+ if(i)code+=",";
+ code+="\n\t\ttranslate(\"_TransactionNames\",\""+tns[i]+"\")";
+ }
+ code+=");\n }\n";
+ //privilege names
+ code+="static public function privilegeNames(){\n\treturn array(";
+ QStringList priv=woc->privilegeNames();
+ for(int i=0;i<priv.size();i++){
+ if(i)code+=",\n\t\t";else code+="\n\t\t";
+ code+="translate(\"_PrivilegeNames\",\""+priv[i]+"\")";
+ }
+ code+="\n\t);\n}\n";
+
+ m_transact.write(code.toAscii());
+}
+
+void WocPHPClientTransaction::finalize()
+{
+ if(m_transact.isOpen()){
+ m_transact.write(TRANSACTEND);
+ transInfo2();
+ m_transact.write("};\n");
+ m_transact.write(PHPEND);
+ m_transact.close();
+ }
+}
+
+
+void WocPHPClientTransaction::newTransaction(const WocTransaction&trn)
+{
+ //create file
+ QString cn=trnClassName(trn);
+ QString fn="wtr_"+trn.name();
+ addLoad(cn,fn);
+ fn=m_subdir+"/"+fn+m_fileext;
+ QFile tf(m_basedir+"/"+fn);
+ if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){
+ qDebug("Error: cannot create PHP object file %s.",fn.toAscii().data());
+ emit errorFound();
+ return;
+ }
+ tf.write(PHPSTART);
+
+ ////
+ //generate code
+ QString code="/* TRANSLATOR "+cn+" */\nclass "+cn+" extends "+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());
+}
+
+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<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[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<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[i]+"\"=>\"";
+ code+=trn.inputType(sl[i]);
+ code+="\"";
+ }
+ code+=");\n";
+
+
+ code+="\t$this->aoutput=array(";
+ sl=trn.outputNames();
+ for(int i=0;i<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[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<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[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;i<sl.size();i++){
+ QString t=trn.inputType(sl[i]);
+ if(trn.isAttributeType(t)){
+ code+="\t\t$this->ainput[\""+sl[i]+"\"]=$root->getAttribute(\""+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;i<sl.size();i++){
+ QString t=trn.outputType(sl[i]);
+ if(trn.isAttributeType(t)){
+ code+="\t\t$root->setAttribute(\""+sl[i]+"\",$this->aoutput[\""+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;i<sl.size();i++){
+ code+="public function get"+sl[i]+"(){return $this->ainput[\""+sl[i]+"\"];}\n";
+ }
+ //setters
+ sl=trn.outputNames();
+ for(int i=0;i<sl.size();i++){
+ code+="public function result"+sl[i]+"(){return $this->aoutput[\""+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;i<in.size();i++){
+ if(i)code+=",";
+ code+="$"+in[i];
+ }
+ code+=")\n{\n\t$inst=new "+trnClassName(trn)+";\n";
+ code+="\t$inst->do_execute(";
+ for(int i=0;i<in.size();i++){
+ if(i)code+=",";
+ code+="$"+in[i];
+ }
+ code+=");\n";
+ code+="\treturn $inst;\n}\n";
+ //actual non-static implementation
+ code+="private function do_execute(";
+ for(int i=0;i<in.size();i++){
+ if(i)code+=",";
+ code+="$"+in[i];
+ }
+ code+=")\n{\n";
+ for(int i=0;i<in.size();i++)
+ code+="\t$this->ainput[\""+in[i]+"\"]=$"+in[i]+";\n";
+ code+="\tself::$running=\""+trn.name()+"\";\n";
+ code+="\ttry{"+trn.callFunction("php")+"}\n\tcatch(Exception $ex){\n";
+ code+="\t\tself::$running=\"\";\n\t\t$this->handleException($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<priv.size();i++){
+ if(i)code+=",\n\t\t";else code+="\n\t\t";
+ code+="\""+priv[i]+"\"";
+ }
+ code+="\n\t);\n}\n";
+ //constants for use by custom code
+ for(int i=0;i<priv.size();i++)
+ code+="const Priv_"+priv[i]+"=\""+priv[i]+"\";\n";
+ //check method
+ code+="public function havePrivilege($priv){\n";
+ code+="\tif(!in_array($priv,self::privileges()))return false;\n";
+ code+="\treturn $this->isAuthorized(\""+trn.name()+":\".$priv);\n}\n";
+
+ return code;
+}
--- /dev/null
+//
+// C++ Interface: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
--- /dev/null
+//
+// C++ Implementation: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "phpout.h"
+#include "phpdb.h"
+
+#include <QDir>
+
+#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;i<pcols.size();i++){
+ if(i)code+=",";
+ code+="$"+pcols[i];
+ }
+ QString dbi="$"+woc->dbInst();
+ //DB query
+ code+="){\n\tglobal "+dbi+";\n\t$res="+dbi+"->select(\""+tbl.name()+"\",\"*\",\"";
+ for(int i=0;i<pcols.size();i++){
+ if(i)code+=" AND ";
+ code+=pcols[i]+"=\"."+dbi+"->escapeColumn(\""+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;i<cols.size();i++){
+ //automatic resolution of internal foreign keys
+ if(tbl.columnIsForeign(cols[i])){
+ code+="public function getObjectFor"+cols[i]+"(){\n\tglobal "+dbi+";\n\treturn WT";
+ QStringList foreign=tbl.columnForeign(cols[i]).split(":");
+ code+=foreign[0]+"::selectFromDB(\""+foreign[1]+"=\"."+dbi+"->escapeColumn(\""+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";
+ QList<WocEnum>ens=tbl.columnEnums(cols[i]);
+ QList<int>envs;
+ for(int j=0;j<ens.size();j++){
+ int v=ens[j].val;
+ if(envs.contains(v))continue;
+ envs.append(v);
+ code+="||$v=="+QString::number(v);
+ }
+ code+=")return true;else return false;}\n\n";
+ }
+ }
+
+ //reverse resolution of configured foreign keys
+ QStringList fs=tbl.foreigns();
+ for(int i=0;i<fs.size();i++){
+ QString via=tbl.foreignQuery(fs[i]);
+ //parse via
+ QStringList v1=via.split("=");
+ if(v1.size()!=2){
+ qDebug("Warning: Foreign clause %s of table %s has illegal syntax. Should be foreigntable:column=localcolumn.",fs[i].toAscii().data(),tbl.name().toAscii().data());
+ continue;
+ }
+ QString local=v1[1].trimmed();
+ QStringList foreign=v1[0].split(":");
+ if(foreign.size()!=2){
+ qDebug("Warning: Foreign clause %s of table %s has illegal syntax. Should be foreigntable:column=localcolumn.",fs[i].toAscii().data(),tbl.name().toAscii().data());
+ continue;
+ }
+ code+="public function "+fs[i]+"(){\n\tglobal "+dbi+";\n\treturn WT"+foreign[0]+"::selectFromDB(\""+foreign[1]+"=\"."+dbi+"->escapeColumn(\"";
+ code+=foreign[0]+"\",\""+foreign[1]+"\",$this->"+local+"));\n}\n\n";
+ }
+
+ //create enum constants
+ QList<WocEnum>ens=tbl.getEnums();
+ for(int i=0;i<ens.size();i++){
+ code+="const "+ens[i].name+"="+QString::number(ens[i].val)+";\n";
+ }
+
+ //hasproperty function
+ code+="public function hasProperty($p){switch($p){\n";
+ for(int i=0;i<cols.size();i++)
+ code+="\tcase \""+cols[i]+"\":\n";
+ QStringList aps=tbl.auditColumns();
+ for(int i=0;i<aps.size();i++)
+ code+="\tcase \""+aps[i]+"\":\n";
+ code+="\t\treturn true;\n\tdefault:return false;}}\n";
+
+ //create audit stuff
+ if(tbl.isAuditable()){
+ code+="public function isAuditable(){return true;}\n";
+ code+="protected function createAudit(){$ad=WT"+tbl.name()+"_audit::newRow($this->data);\n";
+ code+="\treturn $ad->insert();\n}\n";
+ }
+
+ //create newKey function
+ code+="public function newKey(){\n\tparent::newKey();\n";
+ for(int i=0;i<cols.size();i++){
+ QString c=tbl.columnCall(cols[i],"php");
+ if(c=="")continue;
+ code+="\t$this->cdata[\""+cols[i]+"\"]="+c+";\n";
+ }
+ code+="}\n";
+
+ //write table class
+ code+="};\n";
+ tf.write(code.toAscii());
+ tf.write(PHPEND);
+ tf.close();
+
+ //extend schema file
+ //column definitions
+ code="\tself::$scheme[\""+tbl.name()+"\"]=array(";
+ for(int i=0;i<cols.size();i++){
+ if(i)code+=",";
+ code+="\n\t\t\""+cols[i]+"\"=>array(\"";
+ 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<pcols.size();i++){
+ if(i)code+=",";
+ code+="\""+pcols[i]+"\"";
+ }
+ code+=")";
+ }
+ code+="\n\t);\n";
+ if(tbl.inBackup())code+="\tself::$backup[]=\""+tbl.name()+"\";\n";
+ //write presets
+ QList<QMap<QString,QString> >presets=tbl.presets();
+ if(presets.size()>0){
+ code+="\tself::$preset[\""+tbl.name()+"\"]=array(";
+ for(int i=0;i<presets.size();i++){
+ if(i)code+=",";
+ code+="\n\t\tarray(";
+ QStringList k=presets[i].keys();
+ for(int j=0;j<k.size();j++){
+ if(j)code+=",";
+ code+="\""+k[j]+"\"=>"+presets[i][k[j]];
+ }
+ code+=")";
+ }
+ code+="\n\t);\n";
+ }
+
+ //write
+ m_schema.write(code.toAscii());
+
+ //create autoloading
+ addLoad("WT"+tbl.name(),"wt_"+tbl.name());
+}
--- /dev/null
+//
+// C++ Interface: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
//
#include "phpout.h"
+#include "phpdb.h"
+#include "phpctrans.h"
+#include "phpstrans.h"
+#include "phpclass.h"
#include <QDir>
#include <QDomElement>
-static const QByteArray PHPSTART("<?\n//THIS IS AN AUTOGENERATED FILE, DONT CHANGE!\n\n");
-static const QByteArray PHPEND("\n//END OF AUTOGENERATED FILE\n?>");
+#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");
}
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;i<tns.size();i++){
- if(i)code+=",";
- code+="\n\t\ttranslate(\"_TransactionNames\",\""+tns[i]+"\")";
- }
- code+=");\n }\n";
- //privilege names
- code+="static public function privilegeNames(){\n\treturn array(";
- QStringList priv=woc->privilegeNames();
- for(int i=0;i<priv.size();i++){
- if(i)code+=",\n\t\t";else code+="\n\t\t";
- code+="translate(\"_PrivilegeNames\",\""+priv[i]+"\")";
- }
- code+="\n\t);\n}\n";
-
- m_transact.write(code.toAscii());
-}
-
-void WocPHPServerOut::finalize()
+void WocPHPOut::finalize()
{
+ if(pclass)pclass->finalize();
+ 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;i<pcols.size();i++){
- if(i)code+=",";
- code+="$"+pcols[i];
- }
- QString dbi="$"+woc->dbInst();
- //DB query
- code+="){\n\tglobal "+dbi+";\n\t$res="+dbi+"->select(\""+tbl.name()+"\",\"*\",\"";
- for(int i=0;i<pcols.size();i++){
- if(i)code+=" AND ";
- code+=pcols[i]+"=\"."+dbi+"->escapeColumn(\""+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;i<cols.size();i++){
- //automatic resolution of internal foreign keys
- if(tbl.columnIsForeign(cols[i])){
- code+="public function getObjectFor"+cols[i]+"(){\n\tglobal "+dbi+";\n\treturn WT";
- QStringList foreign=tbl.columnForeign(cols[i]).split(":");
- code+=foreign[0]+"::selectFromDB(\""+foreign[1]+"=\"."+dbi+"->escapeColumn(\""+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";
- QList<WocEnum>ens=tbl.columnEnums(cols[i]);
- QList<int>envs;
- for(int j=0;j<ens.size();j++){
- int v=ens[j].val;
- if(envs.contains(v))continue;
- envs.append(v);
- code+="||$v=="+QString::number(v);
- }
- code+=")return true;else return false;}\n\n";
- }
- }
-
- //reverse resolution of configured foreign keys
- QStringList fs=tbl.foreigns();
- for(int i=0;i<fs.size();i++){
- QString via=tbl.foreignQuery(fs[i]);
- //parse via
- QStringList v1=via.split("=");
- if(v1.size()!=2){
- qDebug("Warning: Foreign clause %s of table %s has illegal syntax. Should be foreigntable:column=localcolumn.",fs[i].toAscii().data(),tbl.name().toAscii().data());
- continue;
- }
- QString local=v1[1].trimmed();
- QStringList foreign=v1[0].split(":");
- if(foreign.size()!=2){
- qDebug("Warning: Foreign clause %s of table %s has illegal syntax. Should be foreigntable:column=localcolumn.",fs[i].toAscii().data(),tbl.name().toAscii().data());
- continue;
- }
- code+="public function "+fs[i]+"(){\n\tglobal "+dbi+";\n\treturn WT"+foreign[0]+"::selectFromDB(\""+foreign[1]+"=\"."+dbi+"->escapeColumn(\"";
- code+=foreign[0]+"\",\""+foreign[1]+"\",$this->"+local+"));\n}\n\n";
- }
-
- //create enum constants
- QList<WocEnum>ens=tbl.getEnums();
- for(int i=0;i<ens.size();i++){
- code+="const "+ens[i].name+"="+QString::number(ens[i].val)+";\n";
- }
-
- //hasproperty function
- code+="public function hasProperty($p){switch($p){\n";
- for(int i=0;i<cols.size();i++)
- code+="\tcase \""+cols[i]+"\":\n";
- QStringList aps=tbl.auditColumns();
- for(int i=0;i<aps.size();i++)
- code+="\tcase \""+aps[i]+"\":\n";
- code+="\t\treturn true;\n\tdefault:return false;}}\n";
-
- //create audit stuff
- if(tbl.isAuditable()){
- code+="public function isAuditable(){return true;}\n";
- code+="protected function createAudit(){$ad=WT"+tbl.name()+"_audit::newRow($this->data);\n";
- code+="\treturn $ad->insert();\n}\n";
- }
-
- //create newKey function
- code+="public function newKey(){\n\tparent::newKey();\n";
- for(int i=0;i<cols.size();i++){
- QString c=tbl.columnCall(cols[i],"php");
- if(c=="")continue;
- code+="\t$this->cdata[\""+cols[i]+"\"]="+c+";\n";
- }
- code+="}\n";
-
- //write table class
- code+="};\n";
- tf.write(code.toAscii());
- tf.write(PHPEND);
- tf.close();
-
- //extend schema file
- //column definitions
- code="\tself::$scheme[\""+tbl.name()+"\"]=array(";
- for(int i=0;i<cols.size();i++){
- if(i)code+=",";
- code+="\n\t\t\""+cols[i]+"\"=>array(\"";
- 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<pcols.size();i++){
- if(i)code+=",";
- code+="\""+pcols[i]+"\"";
- }
- code+=")";
- }
- code+="\n\t);\n";
- if(tbl.inBackup())code+="\tself::$backup[]=\""+tbl.name()+"\";\n";
- //write presets
- QList<QMap<QString,QString> >presets=tbl.presets();
- if(presets.size()>0){
- code+="\tself::$preset[\""+tbl.name()+"\"]=array(";
- for(int i=0;i<presets.size();i++){
- if(i)code+=",";
- code+="\n\t\tarray(";
- QStringList k=presets[i].keys();
- for(int j=0;j<k.size();j++){
- if(j)code+=",";
- code+="\""+k[j]+"\"=>"+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;i<k.size();i++){
- code+="protected $prop_"+k[i];
- if(!cls.propertyIsList(k[i]))code+="=null";
- code+=";\n";
- }
- code+="public function __construct()\n{\n\tparent::__construct();\n";
- for(int i=0;i<k.size();i++)
- if(cls.propertyIsList(k[i]))
- code+="\t$this->prop_"+k[i]+"=array();\n";
- code+="}\n";
- return code;
-}
-
-QString WocPHPServerOut::classEnums(const WocClass&cls)
-{
- QString code;
- QStringList k=cls.enumTypes();
- for(int i=0;i<k.size();i++){
- code+="//enum "+k[i]+"\n";
- QList<WocEnum>ev=cls.enumValues(k[i]);
- for(int j=0;j<ev.size();j++)
- code+="const "+ev[j].name+"="+QString::number(ev[j].val)+";\n";
- }
- return code;
-}
-
-QString WocPHPServerOut::classProperties(const WocClass&cls)
-{
- QString code;
- QStringList k=cls.propertyNames();
- for(int i=0;i<k.size();i++){
- code+="\n";
- //generate validator
- code+=classPropertyValidator(cls,k[i]);
- //generic getter
- code+="public function get"+k[i]+"(){return $this->prop_"+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<k.size();i++){
- if(i)code+=",";
- code+="\n\t\t\""+k[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)){
- QList<WocEnum>ev=cls.enumValues(cls.propertyPlainType(prop));
- code+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n";
- for(int j=0;j<ev.size();j++){
- code+="\t\tif($value=="+QString::number(ev[j].val)+")return true;\n";
- }
- code+="\t\treturn false;\n\t}else{\n";
- for(int j=0;j<ev.size();j++){
- code+="\t\tif($value==\""+ev[j].name+"\")return true;\n";
- }
- code+="\t\treturn false;\n\t}\n";
- }else
- if(cls.propertyIsInt(prop))
- code+="\treturn is_numeric($value);\n";
- else
- if(cls.propertyIsString(prop)||cls.propertyIsBlob(prop))
- code+="\treturn true;\n";//TODO: special handling for astring
- else
- if(cls.propertyIsBool(prop))
- code+="\treturn is_bool($value);\n";
- else
- if(cls.propertyIsObject(prop))
- code+="\treturn is_a($value,\"WO"+cls.propertyPlainType(prop)+"\");\n";
- else{
- qDebug("Warning: unable to generate validator for class %s property %s: unknown type.",cls.name().toAscii().data(),prop.toAscii().data());
- code+="\treturn false;\n";
- }
- code+="}\n";
-
- return code;
-}
-
-QString WocPHPServerOut::classPropertyListGetters(const WocClass&cls,QString prop)
-{
- QString code;
- if(cls.propertyIsString(prop))
- code+="public function getstrlist_"+prop+"(){return $this->prop_"+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<WocEnum> ev=cls.enumValues(cls.propertyPlainType(prop));
- for(int j=0;j<ev.size();j++){
- code+="\t\tcase "+QString::number(ev[j].val)+":$ret[]=\""+ev[j].name+"\";break;\n";
- }
- code+="\t\tdefault:$ret[]=null;break;\n\t}\n\treturn $ret;\n}\n";
- }
-
- return code;
-}
-
-QString WocPHPServerOut::classPropertyListSetters(const WocClass&cls,QString prop)
-{
- QString code;
- code+="public function clear_"+prop+"(){$this->prop_"+prop+"=array();}\n";
- QString acode;//body of add_ function, see below
- code+="public function set"+prop+"(array $values){\n";
- if(cls.propertyIsEnum(prop)){
- QList<WocEnum>ev=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;j<ev.size();j++){
- code+="\t\t\tif($value=="+QString::number(ev[j].val)+"){\n";
- code+="\t\t\t\t$prop[]="+QString::number(ev[j].val)+";\n";
- code+="\t\t\t}else\n";
- acode+="\t\tif($value=="+QString::number(ev[j].val)+"){\n";
- acode+="\t\t\t$this->prop_"+prop+"[]="+QString::number(ev[j].val)+";\n";
- acode+="\t\t\treturn true;\n\t\t}\n";
- }
- code+="\t\t\treturn false;\n\t\t}else{\n";
- acode+="\t\treturn false;\n\t}else{\n";
- for(int j=0;j<ev.size();j++){
- code+="\t\t\tif($value==\""+ev[j].name+"\"){\n";
- code+="\t\t\t\t$prop[]="+QString::number(ev[j].val)+";\n";
- code+="\n\t\t\t}else\n";
- acode+="\t\tif($value==\""+ev[j].name+"\"){\n";
- acode+="\t\t\t$this->prop_"+prop+"[]="+QString::number(ev[j].val)+";\n";
- acode+="\t\t\treturn true;\n\t\t}\n";
- }
- code+="\t\t\treturn false;\n\t\t}\n\t}\n";
- code+="\t$this->prop_"+prop+"=$prop;\n";
- code+="\treturn true;\n";
- acode+="\t\treturn false;\n\t}\n";
- }else
- if(cls.propertyIsInt(prop)){
- code+="\t$prop=array();\n\tforeach($values as $value)\n";
- code+="\t\tif(is_numeric($value)){\n\t\t\t$prop[]=0+$value;\n\t\t}else return false;\n";
- code+="\t$this->prop_"+prop+"=$prop;\n\treturn true;\n";
- acode+="\tif(is_numeric($value)){\n";
- acode+="\t\t$this->prop_"+prop+"=0+$value;\n\t\treturn true;\n\t}else return false;\n";
- }else
- if(cls.propertyIsBool(prop)){
- code+="\t$prop=array();\n\tforeach($values as $value)\n";
- code+="\t\tif(is_bool($value))$prop[]=$value!=false;else\n";
- code+="\t\tif($value==\"yes\")$prop[]=true;else\n";
- code+="\t\tif($value==\"no\")$prop[]=false;else return false;\n";
- code+="\t$this->prop_"+prop+"=$prop;\n\treturn true;\n";
- acode+="\tif(is_bool($value)){\n";
- acode+="\t\t$this->prop_"+prop+"=$value!=false;\n\t\treturn true;\n\t}else return false;\n";
- }else
- if(cls.propertyIsString(prop)||cls.propertyIsBlob(prop)){
- code+="\t$prop=array();\n\tforeach($values as $value)$prop[]=\"\".$value;\n";
- code+="\t$this->prop_"+prop+"=$prop;\n\treturn true;\n";
- //TODO: special handling for astring
- acode+="\t$this->prop_"+prop+"[]=\"\".$value;\n\treturn true;\n";
- }else
- if(cls.propertyIsObject(prop)){
- code+="\t$prop=array();\n\tforeach($values as $value)\n";
- code+="\t\tif(is_a($value,\"WO"+cls.propertyPlainType(prop)+"\"))\n";
- code+="\t\t\t$prop[]=$value;\n";
- code+="\t\telse return false;\n";
- code+="\t$this->prop_"+prop+"=$prop;\n";
- code+="\treturn true;\n";
- acode+="\tif(is_a($value,\"WO"+cls.propertyPlainType(prop)+"\")){\n";
- acode+="\t\t$this->prop_"+prop+"[]=$value;\n";
- acode+="\t\treturn true;\n";
- acode+="\t}else return false;\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";
- code+="public function add_"+prop+"($value){\n"+acode+"}\n";
-
- return code;
-}
-
-QString WocPHPServerOut::classPropertyScalarGetters(const WocClass&cls,QString prop)
-{
- QString code;
- if(cls.propertyIsString(prop))
- code+="public function getstr_"+prop+"(){return $this->prop_"+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<WocEnum> ev=cls.enumValues(cls.propertyPlainType(prop));
- for(int j=0;j<ev.size();j++){
- code+="\t\tcase "+QString::number(ev[j].val)+":return translate(\""+abstractClassName(cls)+"\",\""+ev[j].name+"\");\n";
- }
- code+="\t\tdefault:return null;\n\t}\n}\n";
- }
-
- return code;
-}
-
-QString WocPHPServerOut::classPropertyScalarSetters(const WocClass&cls,QString prop)
-{
- QString code;
- code+="public function set"+prop+"($value){\n";
- if(cls.propertyIsEnum(prop)){
- QList<WocEnum>ev=cls.enumValues(cls.propertyPlainType(prop));
- code+="\tif(is_numeric($value)){\n\t\t$value=$value+0;\n";
- for(int j=0;j<ev.size();j++){
- code+="\t\tif($value=="+QString::number(ev[j].val)+"){\n";
- code+="\t\t\t$this->prop_"+prop+"="+QString::number(ev[j].val)+";\n";
- code+="\t\t\treturn true;\n\t\t}\n";
- }
- code+="\t\treturn false;\n\t}else{\n";
- for(int j=0;j<ev.size();j++){
- code+="\t\tif($value==\""+ev[j].name+"\"){\n";
- code+="\t\t\t$this->prop_"+prop+"="+QString::number(ev[j].val)+";\n";
- code+="\t\t\treturn true;\n\t\t}\n";
- }
- code+="\t\treturn false;\n\t}\n";
- }else
- if(cls.propertyIsInt(prop))
- code+="\tif(is_numeric($value)){\n\t\t$this->prop_"+prop+"=0+$value;\n\t\treturn true;\n\t}else return false;\n";
- else
- if(cls.propertyIsBool(prop)){
- code+="\tif(is_bool($value))$this->prop_"+prop+"=$value!=false;else\n";
- code+="\tif($value==\"yes\")$this->prop_"+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;j<p.size();j++)
- code+=propertyToXml(cls,p[j]);
- //return result
- code+="\treturn $root;\n}\n";
- return code;
-}
-
-QString WocPHPServerOut::classDeserializers(const WocClass&cls)
-{
- QString code;
- QStringList k;
- code+="\nstatic public function fromString($txt){\n\t$xml=new DomDocument;\n";
- code+="\tif(!$xml->loadXml(trim($txt)))";
- code+="\n\t\tthrow WobXmlException(translate(\""+abstractClassName(cls)+"\",\"Unable to deserialize object of type "+className(cls)+": invalid XML.\"));";
- code+="\n\treturn self::fromXml($xml,$xml->documentElement);\n}\n";
- code+="static public function fromXml($xml,$elem){\n\t$data=new "+className(cls)+"();\n";
- k=cls.propertyNames();
- for(int i=0;i<k.size();i++){
- //scan properties
- if(cls.propertyIsList(k[i])){
- code+="\t$data->clear_"+k[i]+"();\n";
- code+="\tforeach(WObject::elementsByTagName($elem,\""+k[i]+"\") as $el){\n";
- if(cls.propertyIsObject(k[i])){
- code+="\t\t$data->add_"+k[i]+"(WO"+cls.propertyPlainType(k[i])+"::fromXml($xml,$el));\n";
- }else if(cls.propertyIsBlob(k[i])){
- code+="\t\t$data->add_"+k[i]+"(base64_decode($el->textContent));\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;i<k.size();i++){
- WocTable tab=WocProcessor::instance()->table(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";
- QMap<QString,QString>map=cls.mapping(k[i]);
- QStringList mapk=cls.mappingProperties(k[i]);
- for(int j=0;j<mapk.size();j++){
- QString meth=cls.mapMethod(k[i],mapk[j],"php");
- if(meth!="")code+="\t$data->prop_"+mapk[j]+"="+meth+";\n";
- else code+="\t$data->prop_"+mapk[j]+"=$table->"+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<count($table);$i++)$ret[]=self::fromTable"+k[i]+"($table[$i]);\n";
- code+="\treturn $ret;\n}\n";
- //reverse mapping
- code+="public function toTable"+k[i]+"(&$table){\n";
- for(int j=0;j<mapk.size();j++){
- //do not reverse translate method conversions
- QString meth=cls.mapMethod(k[i],mapk[j],"php").trimmed();
- if(meth!="")continue;
- //check that column exists
- if(tab.hasColumn(map[mapk[j]])){
- code+="\tif($this->prop_"+mapk[j]+"!==null && $table->"+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<sl.size();i++){
- if(i)code+=",";
- code+="\""+sl[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<sl.size();i++){
- if(i)code+=",";
- code+="\""+sl[i]+"\"=>\"";
- code+=trn.inputType(sl[i]);
- code+="\"";
- }
- code+=");\n";
-
-
- code+="\t$this->aoutput=array(";
- sl=trn.outputNames();
- for(int i=0;i<sl.size();i++){
- if(i)code+=",";
- code+="\""+sl[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<sl.size();i++){
- if(i)code+=",";
- code+="\""+sl[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;i<sl.size();i++){
- QString t=trn.inputType(sl[i]);
- if(trn.isAttributeType(t)){
- code+="\t\t$this->ainput[\""+sl[i]+"\"]=$root->getAttribute(\""+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;i<sl.size();i++){
- QString t=trn.outputType(sl[i]);
- if(trn.isAttributeType(t)){
- code+="\t\t$root->setAttribute(\""+sl[i]+"\",$this->aoutput[\""+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;i<sl.size();i++){
- code+="public function get"+sl[i]+"(){return $this->ainput[\""+sl[i]+"\"];}\n";
- }
- //setters
- sl=trn.outputNames();
- for(int i=0;i<sl.size();i++){
- code+="public function result"+sl[i]+"(){return $this->aoutput[\""+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;i<in.size();i++){
- if(i)code+=",";
- code+="$"+in[i];
- }
- code+=")\n{\n\t$inst=new "+trnClassName(trn)+";\n";
- code+="\t$inst->do_execute(";
- for(int i=0;i<in.size();i++){
- if(i)code+=",";
- code+="$"+in[i];
- }
- code+=");\n";
- code+="\treturn $inst;\n}\n";
- //actual non-static implementation
- code+="private function do_execute(";
- for(int i=0;i<in.size();i++){
- if(i)code+=",";
- code+="$"+in[i];
- }
- code+=")\n{\n";
- for(int i=0;i<in.size();i++)
- code+="\t$this->ainput[\""+in[i]+"\"]=$"+in[i]+";\n";
- code+="\tself::$running=\""+trn.name()+"\";\n";
- code+="\ttry{"+trn.callFunction("php")+"}\n\tcatch(Exception $ex){\n";
- code+="\t\tself::$running=\"\";\n\t\t$this->handleException($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<priv.size();i++){
- if(i)code+=",\n\t\t";else code+="\n\t\t";
- code+="\""+priv[i]+"\"";
- }
- code+="\n\t);\n}\n";
- //constants for use by custom code
- for(int i=0;i<priv.size();i++)
- code+="const Priv_"+priv[i]+"=\""+priv[i]+"\";\n";
- //check method
- code+="public function havePrivilege($priv){\n";
- code+="\tif(!in_array($priv,self::privileges()))return false;\n";
- code+="\treturn $this->isAuthorized(\""+trn.name()+":\".$priv);\n}\n";
-
- return code;
-}
class QDomElement;
+class WocPHPOut;
+class WocPHPClass;
+class WocPHPTable;
+class WocPHPClientTransaction;
+class WocPHPServerTransaction;
+
+class WocPHPTransaction:public QObject
+{
+ Q_OBJECT
+ public:
+ WocPHPTransaction(WocPHPOut*);
+ virtual void finalize()=0;
+ virtual void newTransaction(const WocTransaction&)=0;
+ protected:
+ WocPHPOut*m_parent;
+ signals:
+ void errorFound();
+};
+
/**generates output for a PHP server side*/
-class WocPHPServerOut:public WocOutput
+class WocPHPOut:public WocOutput
{
public:
/**initializes the output object*/
- WocPHPServerOut(const QDomElement&);
+ WocPHPOut(const QDomElement&);
protected:
/**writes any last words after parsing finished*/
virtual void finalize();
virtual void newTable(const WocTable&);
/**creates a transaction*/
virtual void newTransaction(const WocTransaction&);
- private:
+
+ friend class WocPHPClass;
+ friend class WocPHPTable;
+ friend class WocPHPTransaction;
+ friend class WocPHPClientTransaction;
+ friend class WocPHPServerTransaction;
+
QString m_basedir,m_subdir,m_fileext;
QString m_transbase;
QFile m_loader,m_schema,m_transact;
/**helper: adds a loader line for a class to autoload.php*/
void addLoad(QString classname,QString filename);
- /**helper: generates PHP code to transform a class property to XML*/
- QString propertyToXml(const WocClass&,QString);
- /**helper: generate class constructor*/
- QString classConstruct(const WocClass&);
- /**helper: generate class internal enums*/
- QString classEnums(const WocClass&);
- /**helper: generate class internal props*/
- QString classProperties(const WocClass&);
- /**helper: generate class internal serializers*/
- QString classSerializers(const WocClass&);
- /**helper: generate class internal deserializers*/
- QString classDeserializers(const WocClass&);
- /**helper: generate class internal mappers*/
- QString classMappings(const WocClass&);
- /**helper: generate property validator*/
- QString classPropertyValidator(const WocClass&,QString);
- /**helper: generate getters for list properties*/
- QString classPropertyListGetters(const WocClass&,QString);
- /**helper: generate setters for list properties*/
- QString classPropertyListSetters(const WocClass&,QString);
- /**helper: generate getters for scalar properties*/
- QString classPropertyScalarGetters(const WocClass&,QString);
- /**helper: generate setters for sclar properties*/
- QString classPropertyScalarSetters(const WocClass&,QString);
- /**helper: generate the property to array converter, eg. for renderers like for Twig*/
- QString classPropertiesList(const WocClass&);
-
- /**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&);
+ WocPHPClass*pclass;
+ WocPHPTable*ptable;
+ WocPHPTransaction*ptrans;
/**helper: return the PHP-class-name of a WocClass*/
QString className(const WocClass&c){return "WO"+c.name();}
QString trnClassName(const WocTransaction&t){return "WTr"+t.name();}
};
+class WocPHPServerOut:public WocPHPOut
+{
+ public:
+ /**initializes the output object*/
+ WocPHPServerOut(const QDomElement&);
+};
+
#endif
--- /dev/null
+//
+// C++ Implementation: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "phpout.h"
+#include "phpstrans.h"
+
+#include <QDir>
+#include <QDomElement>
+
+#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;i<tns.size();i++){
+ if(i)code+=",";
+ code+="\n\t\ttranslate(\"_TransactionNames\",\""+tns[i]+"\")";
+ }
+ code+=");\n }\n";
+ //privilege names
+ code+="static public function privilegeNames(){\n\treturn array(";
+ QStringList priv=woc->privilegeNames();
+ for(int i=0;i<priv.size();i++){
+ if(i)code+=",\n\t\t";else code+="\n\t\t";
+ code+="translate(\"_PrivilegeNames\",\""+priv[i]+"\")";
+ }
+ code+="\n\t);\n}\n";
+
+ m_transact.write(code.toAscii());
+}
+
+void WocPHPServerTransaction::finalize()
+{
+ if(m_transact.isOpen()){
+ m_transact.write(TRANSACTEND);
+ transInfo2();
+ m_transact.write("};\n");
+ m_transact.write(PHPEND);
+ m_transact.close();
+ }
+}
+
+
+void WocPHPServerTransaction::newTransaction(const WocTransaction&trn)
+{
+ //create file
+ QString cn=trnClassName(trn);
+ QString fn="wtr_"+trn.name();
+ addLoad(cn,fn);
+ fn=m_subdir+"/"+fn+m_fileext;
+ QFile tf(m_basedir+"/"+fn);
+ if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){
+ qDebug("Error: cannot create PHP object file %s.",fn.toAscii().data());
+ emit errorFound();
+ return;
+ }
+ tf.write(PHPSTART);
+
+ ////
+ //generate code
+ QString code="/* TRANSLATOR "+cn+" */\nclass "+cn+" extends "+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());
+}
+
+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<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[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<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[i]+"\"=>\"";
+ code+=trn.inputType(sl[i]);
+ code+="\"";
+ }
+ code+=");\n";
+
+
+ code+="\t$this->aoutput=array(";
+ sl=trn.outputNames();
+ for(int i=0;i<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[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<sl.size();i++){
+ if(i)code+=",";
+ code+="\""+sl[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;i<sl.size();i++){
+ QString t=trn.inputType(sl[i]);
+ if(trn.isAttributeType(t)){
+ code+="\t\t$this->ainput[\""+sl[i]+"\"]=$root->getAttribute(\""+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;i<sl.size();i++){
+ QString t=trn.outputType(sl[i]);
+ if(trn.isAttributeType(t)){
+ code+="\t\t$root->setAttribute(\""+sl[i]+"\",$this->aoutput[\""+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;i<sl.size();i++){
+ code+="public function get"+sl[i]+"(){return $this->ainput[\""+sl[i]+"\"];}\n";
+ }
+ //setters
+ sl=trn.outputNames();
+ for(int i=0;i<sl.size();i++){
+ code+="public function result"+sl[i]+"(){return $this->aoutput[\""+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;i<in.size();i++){
+ if(i)code+=",";
+ code+="$"+in[i];
+ }
+ code+=")\n{\n\t$inst=new "+trnClassName(trn)+";\n";
+ code+="\t$inst->do_execute(";
+ for(int i=0;i<in.size();i++){
+ if(i)code+=",";
+ code+="$"+in[i];
+ }
+ code+=");\n";
+ code+="\treturn $inst;\n}\n";
+ //actual non-static implementation
+ code+="private function do_execute(";
+ for(int i=0;i<in.size();i++){
+ if(i)code+=",";
+ code+="$"+in[i];
+ }
+ code+=")\n{\n";
+ for(int i=0;i<in.size();i++)
+ code+="\t$this->ainput[\""+in[i]+"\"]=$"+in[i]+";\n";
+ code+="\tself::$running=\""+trn.name()+"\";\n";
+ code+="\ttry{"+trn.callFunction("php")+"}\n\tcatch(Exception $ex){\n";
+ code+="\t\tself::$running=\"\";\n\t\t$this->handleException($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<priv.size();i++){
+ if(i)code+=",\n\t\t";else code+="\n\t\t";
+ code+="\""+priv[i]+"\"";
+ }
+ code+="\n\t);\n}\n";
+ //constants for use by custom code
+ for(int i=0;i<priv.size();i++)
+ code+="const Priv_"+priv[i]+"=\""+priv[i]+"\";\n";
+ //check method
+ code+="public function havePrivilege($priv){\n";
+ code+="\tif(!in_array($priv,self::privileges()))return false;\n";
+ code+="\treturn $this->isAuthorized(\""+trn.name()+":\".$priv);\n}\n";
+
+ return code;
+}
--- /dev/null
+//
+// C++ Interface: phpout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
--- /dev/null
+//
+// C++ Implementation: processor
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QDir>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QProcess>
+
+/******************************************************************************
+ * 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<QDomElement> nl=elementsByTagName(cls,"Property");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ s_prop p;
+ p.name=el.attribute("name");
+ if(!symok.exactMatch(p.name)){
+ qDebug("Error: Illegal property %s in class %s.",p.name.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(hasProperty(p.name)){
+ qDebug("Error: Double definition of property %s in class %s.",p.name.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ p.type=el.attribute("type");
+ p.isid=str2bool(el.attribute("id","0"));
+ p.isabstract=str2bool(el.attribute("abstract","0"));
+ m_props.append(p);
+ //docu
+ QString s=el.text().trimmed();
+ if(s!="")m_propdoc.insert(p.name,s);
+ }
+ //scan enums
+ nl=elementsByTagName(cls,"Enum");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QString nm=el.attribute("name");
+ if(!symok.exactMatch(nm)){
+ qDebug("Error: Illegal enum type %s in class %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(hasEnumType(nm)){
+ qDebug("Error: Double definition of enum type %s in class %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QList<WocEnum>ev;
+ //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<QDomElement> nl2=elementsByTagName(el,"Value");
+ int nxval=0;
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString n=el2.attribute("name");
+ if(n==""){
+ qDebug("Warning: anonymous enum value in class %s enum %s. Ignoring it.",m_name.toAscii().data(),nm.toAscii().data());
+ continue;
+ }
+ nxval=el2.attribute("value",QString::number(nxval)).toInt(0,0);
+ ev.append(WocEnum(n,nxval,el2.text().trimmed()));
+ nxval++;
+ //TODO: check that value name does not exist yet
+ }
+ m_enumvals.insert(nm,ev);
+ }
+ //scan mappings
+ nl=elementsByTagName(cls,"Mapping");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QString name=el.attribute("table");
+ if(!symok.exactMatch(name)){
+ qDebug("Error: Illegal mapping %s in class %s.",name.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(hasMapping(name)){
+ qDebug("Error: Double definition of mapping %s in class %s.",name.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QList<s_map>map;
+ QList<QDomElement> nl2=elementsByTagName(el,"Map");
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ s_map sm;
+ sm.column=el2.attribute("column");
+ sm.property=el2.attribute("property");
+ if(sm.property=="")sm.property=sm.column;
+ if(sm.column=="")sm.column=sm.property;
+ if(sm.column==""){
+ qDebug("Warning: empty mapping in class %s mapping %s. Ignoring it.",m_name.toAscii().data(),name.toAscii().data());
+ continue;
+ }
+ QList<QDomElement> nl3=elementsByTagName(el2,"Call");
+ for(int k=0;k<nl3.size();k++){
+ QDomElement el3=nl3.at(k).toElement();
+ if(el3.isNull())continue;
+ QString lang=el3.attribute("lang");
+ QString meth=el3.attribute("method","false");
+ sm.method.insert(lang,meth);
+ }
+ map.append(sm);
+ }
+ m_maps.insert(name,map);
+ }
+ //docu
+ nl=elementsByTagName(cls,"Doc");
+ for(int i=0;i<nl.size();i++){
+ QString s=nl.at(i).toElement().text().trimmed();
+ if(s!="")m_docstrings<<s;
+ }
+ //check abstraction
+ if(!m_abstract && isAbstract("")){
+ qDebug("Warning: class %s should be declared abstract.",m_name.toAscii().data());
+ }
+ //conditional abstraction (must be after check or we'll get false positives)
+ nl=elementsByTagName(cls,"Abstract");
+ for(int i=0;i<nl.size();i++){
+ QString s=nl.at(i).toElement().attribute("lang").trimmed();
+ if(s!="")m_cabstract<<s;
+ }
+}
+
+bool WocClass::hasProperty(QString p)const
+{
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].name==p)return true;
+ return false;
+}
+
+QStringList WocClass::propertyNames()const
+{
+ QStringList r;
+ for(int i=0;i<m_props.size();i++)
+ r<<m_props[i].name;
+ return r;
+}
+
+QString WocClass::propertyType(QString p)const
+{
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].name==p)return m_props[i].type;
+ return "";
+}
+
+bool WocClass::propertyIsIdentity(QString p)const
+{
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].name==p)return m_props[i].isid;
+ return false;
+}
+
+bool WocClass::propertyIsAbstract(QString p)const
+{
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].name==p)return m_props[i].isabstract;
+ return false;
+}
+
+bool WocClass::isAbstract(QString l)const
+{
+ if(m_cabstract.contains(l))return true;
+ for(int i=0;i<m_props.size();i++)
+ if(m_props[i].isabstract)return true;
+ return m_abstract;
+}
+
+QString WocClass::propertyPlainType(QString p)const
+{
+ QString r=propertyType(p);
+ if(r.startsWith("List:"))return r.mid(5);
+ else return r;
+}
+
+const QStringList WocClass::attrtypes=QStringList()<<"astring"<<"int"<<"int32"<<"int64"<<"bool";
+bool WocClass::propertyIsAttribute(QString p)const
+{
+ QString t=propertyPlainType(p);
+ if(attrtypes.contains(t))return true;
+ if(hasEnumType(t))return true;
+ return false;
+}
+
+const QStringList WocClass::elemtypes=QStringList()<<"string"<<"blob";
+bool WocClass::propertyIsElement(QString p)const
+{
+ QString t=propertyPlainType(p);
+ if(elemtypes.contains(t))return true;
+ if(hasEnumType(t))return true;
+ return false;
+}
+
+bool WocClass::propertyIsObject(QString p)const
+{
+ QString t=propertyPlainType(p);
+ //default types take precedence over classes
+ if(attrtypes.contains(t))return false;
+ if(elemtypes.contains(t))return false;
+ //enums shadow classes
+ if(hasEnumType(t))return false;
+ //check that the class exists
+ return WocProcessor::instance()->hasClass(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<QString,QString> WocClass::mapping(QString m)const
+{
+ if(!m_maps.contains(m))return QMap<QString,QString>();
+ QList<s_map> sml=m_maps[m];
+ QMap<QString,QString>ret;
+ for(int i=0;i<sml.size();i++)
+ ret.insert(sml[i].property,sml[i].column);
+ return ret;
+}
+
+QStringList WocClass::mappingProperties(QString m)const
+{
+ if(!m_maps.contains(m))return QStringList();
+ QList<s_map> sml=m_maps[m];
+ QStringList ret;
+ for(int i=0;i<sml.size();i++)
+ ret<<sml[i].property;
+ return ret;
+}
+
+QString WocClass::mapMethod(QString table,QString property,QString lang)const
+{
+ if(!m_maps.contains(table))return "";
+ QList<s_map> sml=m_maps[table];
+ for(int i=0;i<sml.size();i++)
+ if(sml[i].property==property){
+ if(sml[i].method.contains(lang))return sml[i].method[lang];
+ else return "";
+ }
+ return "";
+}
--- /dev/null
+//
+// C++ Interface: processor
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOC_PROCESSOR_CLASS_H
+#define WOC_PROCESSOR_CLASS_H
+
+#include <QList>
+#include <QMap>
+#include <QObject>
+#include <QPair>
+#include <QStringList>
+
+/**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<WocEnum> 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<QString,QString> 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<s_prop> m_props;
+ //mappings: "table-name" => List of ("column-name","property-name")
+ struct s_map{
+ QString column,property;
+ QMap<QString,QString>method;//lang->method
+ };
+ QMap<QString,QList<s_map> >m_maps;
+ //enum types: "type-name" => List of ("constant-name",int-constant-value)
+ QMap<QString,QList<WocEnum> >m_enumvals;
+ //serializers: "name" => List of properties (syntax Objects: "propertyname/Serializer"
+// QMap<QString,QStringList> m_serial;
+
+ //docu
+ QStringList m_docstrings;
+ QMap<QString,QString>m_propdoc;
+
+ //helper: contains predefined types sorted by serialization type
+ static const QStringList attrtypes,elemtypes;
+};
+
+#endif
}
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<QDomElement> nl=elementsByTagName(cls,"Property");
- for(int i=0;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- s_prop p;
- p.name=el.attribute("name");
- if(!symok.exactMatch(p.name)){
- qDebug("Error: Illegal property %s in class %s.",p.name.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- if(hasProperty(p.name)){
- qDebug("Error: Double definition of property %s in class %s.",p.name.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- p.type=el.attribute("type");
- p.isid=str2bool(el.attribute("id","0"));
- p.isabstract=str2bool(el.attribute("abstract","0"));
- m_props.append(p);
- //docu
- QString s=el.text().trimmed();
- if(s!="")m_propdoc.insert(p.name,s);
- }
- //scan enums
- nl=elementsByTagName(cls,"Enum");
- for(int i=0;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- QString nm=el.attribute("name");
- if(!symok.exactMatch(nm)){
- qDebug("Error: Illegal enum type %s in class %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- if(hasEnumType(nm)){
- qDebug("Error: Double definition of enum type %s in class %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- QList<WocEnum>ev;
- //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<QDomElement> nl2=elementsByTagName(el,"Value");
- int nxval=0;
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- QString n=el2.attribute("name");
- if(n==""){
- qDebug("Warning: anonymous enum value in class %s enum %s. Ignoring it.",m_name.toAscii().data(),nm.toAscii().data());
- continue;
- }
- nxval=el2.attribute("value",QString::number(nxval)).toInt(0,0);
- ev.append(WocEnum(n,nxval,el2.text().trimmed()));
- nxval++;
- //TODO: check that value name does not exist yet
- }
- m_enumvals.insert(nm,ev);
- }
- //scan mappings
- nl=elementsByTagName(cls,"Mapping");
- for(int i=0;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- QString name=el.attribute("table");
- if(!symok.exactMatch(name)){
- qDebug("Error: Illegal mapping %s in class %s.",name.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- if(hasMapping(name)){
- qDebug("Error: Double definition of mapping %s in class %s.",name.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- QList<s_map>map;
- QList<QDomElement> nl2=elementsByTagName(el,"Map");
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- s_map sm;
- sm.column=el2.attribute("column");
- sm.property=el2.attribute("property");
- if(sm.property=="")sm.property=sm.column;
- if(sm.column=="")sm.column=sm.property;
- if(sm.column==""){
- qDebug("Warning: empty mapping in class %s mapping %s. Ignoring it.",m_name.toAscii().data(),name.toAscii().data());
- continue;
- }
- QList<QDomElement> nl3=elementsByTagName(el2,"Call");
- for(int k=0;k<nl3.size();k++){
- QDomElement el3=nl3.at(k).toElement();
- if(el3.isNull())continue;
- QString lang=el3.attribute("lang");
- QString meth=el3.attribute("method","false");
- sm.method.insert(lang,meth);
- }
- map.append(sm);
- }
- m_maps.insert(name,map);
- }
- //docu
- nl=elementsByTagName(cls,"Doc");
- for(int i=0;i<nl.size();i++){
- QString s=nl.at(i).toElement().text().trimmed();
- if(s!="")m_docstrings<<s;
- }
- //check abstraction
- if(!m_abstract && isAbstract("")){
- qDebug("Warning: class %s should be declared abstract.",m_name.toAscii().data());
- }
- //conditional abstraction (must be after check or we'll get false positives)
- nl=elementsByTagName(cls,"Abstract");
- for(int i=0;i<nl.size();i++){
- QString s=nl.at(i).toElement().attribute("lang").trimmed();
- if(s!="")m_cabstract<<s;
- }
-}
-
-bool WocClass::hasProperty(QString p)const
-{
- for(int i=0;i<m_props.size();i++)
- if(m_props[i].name==p)return true;
- return false;
-}
-
-QStringList WocClass::propertyNames()const
-{
- QStringList r;
- for(int i=0;i<m_props.size();i++)
- r<<m_props[i].name;
- return r;
-}
-
-QString WocClass::propertyType(QString p)const
-{
- for(int i=0;i<m_props.size();i++)
- if(m_props[i].name==p)return m_props[i].type;
- return "";
-}
-
-bool WocClass::propertyIsIdentity(QString p)const
-{
- for(int i=0;i<m_props.size();i++)
- if(m_props[i].name==p)return m_props[i].isid;
- return false;
-}
-
-bool WocClass::propertyIsAbstract(QString p)const
-{
- for(int i=0;i<m_props.size();i++)
- if(m_props[i].name==p)return m_props[i].isabstract;
- return false;
-}
-
-bool WocClass::isAbstract(QString l)const
-{
- if(m_cabstract.contains(l))return true;
- for(int i=0;i<m_props.size();i++)
- if(m_props[i].isabstract)return true;
- return m_abstract;
-}
-
-QString WocClass::propertyPlainType(QString p)const
-{
- QString r=propertyType(p);
- if(r.startsWith("List:"))return r.mid(5);
- else return r;
-}
-
-const QStringList WocClass::attrtypes=QStringList()<<"astring"<<"int"<<"int32"<<"int64"<<"bool";
-bool WocClass::propertyIsAttribute(QString p)const
-{
- QString t=propertyPlainType(p);
- if(attrtypes.contains(t))return true;
- if(hasEnumType(t))return true;
- return false;
-}
-
-const QStringList WocClass::elemtypes=QStringList()<<"string"<<"blob";
-bool WocClass::propertyIsElement(QString p)const
-{
- QString t=propertyPlainType(p);
- if(elemtypes.contains(t))return true;
- if(hasEnumType(t))return true;
- return false;
-}
-
-bool WocClass::propertyIsObject(QString p)const
-{
- QString t=propertyPlainType(p);
- //default types take precedence over classes
- if(attrtypes.contains(t))return false;
- if(elemtypes.contains(t))return false;
- //enums shadow classes
- if(hasEnumType(t))return false;
- //check that the class exists
- return WocProcessor::instance()->hasClass(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<QString,QString> WocClass::mapping(QString m)const
-{
- if(!m_maps.contains(m))return QMap<QString,QString>();
- QList<s_map> sml=m_maps[m];
- QMap<QString,QString>ret;
- for(int i=0;i<sml.size();i++)
- ret.insert(sml[i].property,sml[i].column);
- return ret;
-}
-
-QStringList WocClass::mappingProperties(QString m)const
-{
- if(!m_maps.contains(m))return QStringList();
- QList<s_map> sml=m_maps[m];
- QStringList ret;
- for(int i=0;i<sml.size();i++)
- ret<<sml[i].property;
- return ret;
-}
-
-QString WocClass::mapMethod(QString table,QString property,QString lang)const
-{
- if(!m_maps.contains(table))return "";
- QList<s_map> sml=m_maps[table];
- for(int i=0;i<sml.size();i++)
- if(sml[i].property==property){
- if(sml[i].method.contains(lang))return sml[i].method[lang];
- else return "";
- }
- return "";
-}
-
-
-/******************************************************************************
- * 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<QDomElement> nl=elementsByTagName(tbl,"Column");
- for(int i=0;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- QPair<bool,s_col> 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<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- QPair<bool,s_col> 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<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- m_foreign.append(QPair<QString,QString>(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;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- QMap<QString,QString>ps;
- QList<QDomElement> nl2=elementsByTagName(el,"V");
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- if(!el2.hasAttribute("col") || (!el2.hasAttribute("val") && !el2.hasAttribute("code"))){
- qDebug("Error: table definition %s contains illegal preset.",m_name.toAscii().data());
- m_valid=false;
- return;
- }
- QString nm=el2.attribute("col");
- if(!hasColumn(nm)){
- qDebug("Error: table definition %s contains preset for invalid column %s.",m_name.toAscii().data(),nm.toAscii().data());
- m_valid=false;
- return;
- }
- QString v;
- if(el2.hasAttribute("val"))v="\""+el2.attribute("val").replace("\"","\\\"")+"\"";
- else v=el2.attribute("code");
- ps.insert(nm,v);
- }
- if(ps.size()>0)m_presets.append(ps);
- }
-
- //Docu
- nl=elementsByTagName(tbl,"Doc");
- for(int i=0;i<nl.size();i++){
- QString s=nl.at(i).toElement().text().trimmed();
- if(s!="")m_docstrings<<s;
- }
-
- //sanity checks
- //check we have any columns at all
- if(m_columns.size()==0){
- qDebug("Error: table %s does not have any columns.",m_name.toAscii().data());
- m_valid=false;
- return;
- }
- //check that we have a primary key
- if(primaryColumns().size()==0){
- qDebug("Warning: table %s does not have any primary key columns.",m_name.toAscii().data());
- }
-}
-
-
-QPair<bool,WocTable::s_col> 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<bool,s_col>(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<bool,s_col>(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<bool,s_col>(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<bool,s_col>(false,s_col());
- }
- }
- cl.defaultval=el.attribute("default");
- //TODO: validate default against type
- QList<QDomElement> nl2=elementsByTagName(el,"Value");
- int nxval=0;
- //enum values
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- QString n=el2.attribute("name");
- if(n==""){
- qDebug("Warning: anonymous enum value in table %s column %s. Ignoring it.",m_name.toAscii().data(),cl.name.toAscii().data());
- continue;
- }
- nxval=el2.attribute("value",QString::number(nxval)).toInt(0,0);
- cl.enumvals.append(WocEnum(n,nxval,el2.text().trimmed()));
- nxval++;
- }
- //default calls
- nl2=elementsByTagName(el,"Call");
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- QString lang=el2.attribute("lang");
- QString meth=el2.attribute("method","false");
- cl.methodcalls.insert(lang,meth);
- }
- //docu
- QDomNodeList nl3=el.childNodes();
- for(int j=0;j<nl3.size();j++){
- QDomNode n=nl3.at(j);
- if(n.isText()||n.isCDATASection())cl.doc+=" "+n.nodeValue();
- else
- if(n.isElement()&&n.nodeName()=="Doc")cl.doc+=" "+n.toElement().text();
- }
- cl.doc=cl.doc.trimmed();
-
- return QPair<bool,s_col>(true,cl);
-}
-
-QStringList WocTable::columns()const
-{
- QStringList r;
- for(int i=0;i<m_columns.size();i++)
- r<<m_columns[i].name;
- return r;
-}
-
-QStringList WocTable::auditColumns()const
-{
- QStringList r;
- for(int i=0;i<m_staticauditcolumns.size();i++)
- r<<m_staticauditcolumns[i].name;
- for(int i=0;i<m_auditcolumns.size();i++)
- r<<m_auditcolumns[i].name;
- return r;
-}
-
-QStringList WocTable::primaryColumns()const
-{
- QStringList r;
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].isprime)
- r<<m_columns[i].name;
- return r;
-}
-
-QString WocTable::columnType(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].type;
- return "";
-}
-
-bool WocTable::columnIsNull(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].isnull;
- return false;
-}
-
-bool WocTable::columnIsPrimary(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].isprime;
- return false;
-}
-
-bool WocTable::columnHasDefault(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].defaultval!="";
- return false;
-}
-
-QString WocTable::columnDefault(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].defaultval;
- return "";
-}
-
-bool WocTable::hasColumn(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return true;
- return false;
-}
-
-QList<WocEnum> WocTable::columnEnums(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].enumvals;
- return QList<WocEnum>();
-}
-
-QList<WocEnum> WocTable::getEnums()const
-{
- QList<WocEnum> r;
- for(int i=0;i<m_columns.size();i++)
- for(int j=0;j<m_columns[i].enumvals.size();j++)
- r.append(m_columns[i].enumvals[j]);
- return r;
-}
-bool WocTable::columnIsForeign(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].foreign!="";
- return false;
-}
-
-QString WocTable::columnForeign(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].foreign;
- return "";
-}
-
-bool WocTable::columnIsIndexed(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].isindex;
- return false;
-}
-
-bool WocTable::columnIsUnique(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].isunique;
- return false;
-}
-
-QString WocTable::columnDoc(QString c)const
-{
- for(int i=0;i<m_columns.size();i++)
- if(m_columns[i].name==c)
- return m_columns[i].doc;
- return "";
-}
-
-
-QStringList WocTable::foreigns()const
-{
- QStringList r;
- for(int i=0;i<m_foreign.size();i++)
- r<<m_foreign[i].first;
- return r;
-}
-
-QString WocTable::foreignQuery(QString f)const
-{
- for(int i=0;i<m_foreign.size();i++)
- if(m_foreign[i].first==f)
- return m_foreign[i].second;
- return "";
-}
-
-bool WocTable::haveForeign(QString f)const
-{
- for(int i=0;i<m_foreign.size();i++)
- if(m_foreign[i].first==f)
- return true;
- return false;
-}
-
-QString WocTable::columnCall(QString col,QString lang)const
-{
- for(int i=0;i<m_columns.size();i++){
- s_col cl=m_columns[i];
- if(cl.name==col){
- if(!cl.methodcalls.contains(lang))return "";
- else return cl.methodcalls[lang];
- }
- }
- return "";
-}
-
-QList<WocTable::s_col>WocTable::m_staticauditcolumns;
-void WocTable::parseAuditStatic(const QDomElement&el)
-{
- QList<QDomElement> nl=elementsByTagName(el,"Column");
- for(int i=0;i<nl.size();i++){
- QDomElement el2=nl.at(i).toElement();
- if(el2.isNull())continue;
- QPair<bool,s_col>cl=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<m_columns.size();i++){
- //get and reset
- cl=m_columns[i];
- cl.isprime=cl.isunique=false;
- cl.methodcalls.clear();
- if(cl.type.left(3)=="seq")cl.type="int"+cl.type.mid(3);
- //no foreign keys
- cl.foreign="";
- //add
- adt.m_columns.append(cl);
- }
- //copy local audit columns
- adt.m_columns.append(m_auditcolumns);
-
- //return result
- return adt;
-}
-
-
-/******************************************************************************
- * 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<QDomElement> nl=elementsByTagName(root,"Input");
- for(int i=0;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- //variables
- QList<QDomElement> nl2=elementsByTagName(el,"Var");
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- QString nm=el2.attribute("name");
- if(!rval.exactMatch(nm)){
- qDebug("Error: invalid input variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- if(hasInput(nm)){
- qDebug("Error: double definition of input variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- QString tp=el2.attribute("type");
- //TODO: validate type
- m_input.append(QPair<QString,QString>(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<nl.size();j++){
- QDomElement el=nl.at(j).toElement();
- if(el.isNull())continue;
- QString nm=el.attribute("lang");
- if(hasCall(nm)){
- qDebug("Error: double definition of input variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- QString mt=el.attribute("method");
- m_call.insert(nm,mt);
- }
- //output
- nl=elementsByTagName(root,"Output");
- for(int i=0;i<nl.size();i++){
- QDomElement el=nl.at(i).toElement();
- if(el.isNull())continue;
- //variables
- QList<QDomElement> nl2=elementsByTagName(el,"Var");
- for(int j=0;j<nl2.size();j++){
- QDomElement el2=nl2.at(j).toElement();
- if(el2.isNull())continue;
- QString nm=el2.attribute("name");
- if(!rval.exactMatch(nm)){
- qDebug("Error: invalid output variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- if(hasOutput(nm)){
- qDebug("Error: double definition of output variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
- m_valid=false;
- return;
- }
- QString tp=el2.attribute("type");
- //TODO: validate type
- m_output.append(QPair<QString,QString>(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<nl.size();i++){
- QString s=nl.at(i).toElement().text().trimmed();
- if(s!="")m_docstrings<<s;
- }
- //privileges
- nl=elementsByTagName(root,"Privilege");
- for(int i=0;i<nl.size();i++){
- QString s=nl.at(i).toElement().attribute("name").trimmed();
- if(s!="")m_privileges<<s;
- m_privdoc.insert(s,nl.at(i).toElement().text().trimmed());
- }
-}
-
-bool WocTransaction::hasInput(QString v)const
-{
- for(int i=0;i<m_input.size();i++)
- if(m_input[i].first==v)return true;
- return false;
-}
-
-QStringList WocTransaction::inputNames()const
-{
- QStringList r;
- for(int i=0;i<m_input.size();i++)
- r<<m_input[i].first;
- return r;
-}
-
-QString WocTransaction::inputType(QString v)const
-{
- for(int i=0;i<m_input.size();i++)
- if(m_input[i].first==v)return m_input[i].second;
- return "";
-}
-
-bool WocTransaction::hasOutput(QString v)const
-{
- for(int i=0;i<m_output.size();i++)
- if(m_output[i].first==v)return true;
- return false;
-}
-
-QStringList WocTransaction::outputNames()const
-{
- QStringList r;
- for(int i=0;i<m_output.size();i++)
- r<<m_output[i].first;
- return r;
-}
-
-QString WocTransaction::outputType(QString v)const
-{
- for(int i=0;i<m_output.size();i++)
- if(m_output[i].first==v)return m_output[i].second;
- return "";
-}
return false;
}
+#include "procclass.h"
+#include "proctable.h"
+#include "proctrans.h"
-/**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<WocEnum> 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<QString,QString> 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<s_prop> m_props;
- //mappings: "table-name" => List of ("column-name","property-name")
- struct s_map{
- QString column,property;
- QMap<QString,QString>method;//lang->method
- };
- QMap<QString,QList<s_map> >m_maps;
- //enum types: "type-name" => List of ("constant-name",int-constant-value)
- QMap<QString,QList<WocEnum> >m_enumvals;
- //serializers: "name" => List of properties (syntax Objects: "propertyname/Serializer"
-// QMap<QString,QStringList> m_serial;
-
- //docu
- QStringList m_docstrings;
- QMap<QString,QString>m_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<WocEnum> 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<WocEnum> 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<QMap<QString,QString> > 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;
- QList<WocEnum>enumvals;
- QMap<QString,QString>methodcalls;
- };
- QList<s_col>m_columns,m_auditcolumns;
- static QList<s_col>m_staticauditcolumns;
- QList<QPair<QString,QString> >m_foreign;
- QList<QMap<QString,QString> >m_presets;
-
- QStringList m_docstrings;
- QMap<QString,QString>m_fordocs;
-
- //helper method: parses a single column element
- static QPair<bool,s_col> 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<QString,QString> m_call;
- QList<QPair<QString,QString> >m_input,m_output;
- QStringList m_privileges;
- //docu
- QStringList m_docstrings;
- QMap<QString,QString>m_indoc,m_outdoc,m_privdoc;
-};
/**base class of all output generators*/
class WocOutput:public QObject
--- /dev/null
+//
+// C++ Implementation: processor
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QDir>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QProcess>
+
+
+/******************************************************************************
+ * 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<QDomElement> nl=elementsByTagName(tbl,"Column");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QPair<bool,s_col> 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<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QPair<bool,s_col> 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<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ m_foreign.append(QPair<QString,QString>(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;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ QMap<QString,QString>ps;
+ QList<QDomElement> nl2=elementsByTagName(el,"V");
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ if(!el2.hasAttribute("col") || (!el2.hasAttribute("val") && !el2.hasAttribute("code"))){
+ qDebug("Error: table definition %s contains illegal preset.",m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QString nm=el2.attribute("col");
+ if(!hasColumn(nm)){
+ qDebug("Error: table definition %s contains preset for invalid column %s.",m_name.toAscii().data(),nm.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QString v;
+ if(el2.hasAttribute("val"))v="\""+el2.attribute("val").replace("\"","\\\"")+"\"";
+ else v=el2.attribute("code");
+ ps.insert(nm,v);
+ }
+ if(ps.size()>0)m_presets.append(ps);
+ }
+
+ //Docu
+ nl=elementsByTagName(tbl,"Doc");
+ for(int i=0;i<nl.size();i++){
+ QString s=nl.at(i).toElement().text().trimmed();
+ if(s!="")m_docstrings<<s;
+ }
+
+ //sanity checks
+ //check we have any columns at all
+ if(m_columns.size()==0){
+ qDebug("Error: table %s does not have any columns.",m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ //check that we have a primary key
+ if(primaryColumns().size()==0){
+ qDebug("Warning: table %s does not have any primary key columns.",m_name.toAscii().data());
+ }
+}
+
+
+QPair<bool,WocTable::s_col> 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<bool,s_col>(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<bool,s_col>(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<bool,s_col>(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<bool,s_col>(false,s_col());
+ }
+ }
+ cl.defaultval=el.attribute("default");
+ //TODO: validate default against type
+ QList<QDomElement> nl2=elementsByTagName(el,"Value");
+ int nxval=0;
+ //enum values
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString n=el2.attribute("name");
+ if(n==""){
+ qDebug("Warning: anonymous enum value in table %s column %s. Ignoring it.",m_name.toAscii().data(),cl.name.toAscii().data());
+ continue;
+ }
+ nxval=el2.attribute("value",QString::number(nxval)).toInt(0,0);
+ cl.enumvals.append(WocEnum(n,nxval,el2.text().trimmed()));
+ nxval++;
+ }
+ //default calls
+ nl2=elementsByTagName(el,"Call");
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString lang=el2.attribute("lang");
+ QString meth=el2.attribute("method","false");
+ cl.methodcalls.insert(lang,meth);
+ }
+ //docu
+ QDomNodeList nl3=el.childNodes();
+ for(int j=0;j<nl3.size();j++){
+ QDomNode n=nl3.at(j);
+ if(n.isText()||n.isCDATASection())cl.doc+=" "+n.nodeValue();
+ else
+ if(n.isElement()&&n.nodeName()=="Doc")cl.doc+=" "+n.toElement().text();
+ }
+ cl.doc=cl.doc.trimmed();
+
+ return QPair<bool,s_col>(true,cl);
+}
+
+QStringList WocTable::columns()const
+{
+ QStringList r;
+ for(int i=0;i<m_columns.size();i++)
+ r<<m_columns[i].name;
+ return r;
+}
+
+QStringList WocTable::auditColumns()const
+{
+ QStringList r;
+ for(int i=0;i<m_staticauditcolumns.size();i++)
+ r<<m_staticauditcolumns[i].name;
+ for(int i=0;i<m_auditcolumns.size();i++)
+ r<<m_auditcolumns[i].name;
+ return r;
+}
+
+QStringList WocTable::primaryColumns()const
+{
+ QStringList r;
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].isprime)
+ r<<m_columns[i].name;
+ return r;
+}
+
+QString WocTable::columnType(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].type;
+ return "";
+}
+
+bool WocTable::columnIsNull(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].isnull;
+ return false;
+}
+
+bool WocTable::columnIsPrimary(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].isprime;
+ return false;
+}
+
+bool WocTable::columnHasDefault(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].defaultval!="";
+ return false;
+}
+
+QString WocTable::columnDefault(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].defaultval;
+ return "";
+}
+
+bool WocTable::hasColumn(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return true;
+ return false;
+}
+
+QList<WocEnum> WocTable::columnEnums(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].enumvals;
+ return QList<WocEnum>();
+}
+
+QList<WocEnum> WocTable::getEnums()const
+{
+ QList<WocEnum> r;
+ for(int i=0;i<m_columns.size();i++)
+ for(int j=0;j<m_columns[i].enumvals.size();j++)
+ r.append(m_columns[i].enumvals[j]);
+ return r;
+}
+bool WocTable::columnIsForeign(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].foreign!="";
+ return false;
+}
+
+QString WocTable::columnForeign(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].foreign;
+ return "";
+}
+
+bool WocTable::columnIsIndexed(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].isindex;
+ return false;
+}
+
+bool WocTable::columnIsUnique(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].isunique;
+ return false;
+}
+
+QString WocTable::columnDoc(QString c)const
+{
+ for(int i=0;i<m_columns.size();i++)
+ if(m_columns[i].name==c)
+ return m_columns[i].doc;
+ return "";
+}
+
+
+QStringList WocTable::foreigns()const
+{
+ QStringList r;
+ for(int i=0;i<m_foreign.size();i++)
+ r<<m_foreign[i].first;
+ return r;
+}
+
+QString WocTable::foreignQuery(QString f)const
+{
+ for(int i=0;i<m_foreign.size();i++)
+ if(m_foreign[i].first==f)
+ return m_foreign[i].second;
+ return "";
+}
+
+bool WocTable::haveForeign(QString f)const
+{
+ for(int i=0;i<m_foreign.size();i++)
+ if(m_foreign[i].first==f)
+ return true;
+ return false;
+}
+
+QString WocTable::columnCall(QString col,QString lang)const
+{
+ for(int i=0;i<m_columns.size();i++){
+ s_col cl=m_columns[i];
+ if(cl.name==col){
+ if(!cl.methodcalls.contains(lang))return "";
+ else return cl.methodcalls[lang];
+ }
+ }
+ return "";
+}
+
+QList<WocTable::s_col>WocTable::m_staticauditcolumns;
+void WocTable::parseAuditStatic(const QDomElement&el)
+{
+ QList<QDomElement> nl=elementsByTagName(el,"Column");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el2=nl.at(i).toElement();
+ if(el2.isNull())continue;
+ QPair<bool,s_col>cl=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<m_columns.size();i++){
+ //get and reset
+ cl=m_columns[i];
+ cl.isprime=cl.isunique=false;
+ cl.methodcalls.clear();
+ if(cl.type.left(3)=="seq")cl.type="int"+cl.type.mid(3);
+ //no foreign keys
+ cl.foreign="";
+ //add
+ adt.m_columns.append(cl);
+ }
+ //copy local audit columns
+ adt.m_columns.append(m_auditcolumns);
+
+ //return result
+ return adt;
+}
--- /dev/null
+//
+// C++ Interface: processor
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOC_PROCESSOR_TABLE_H
+#define WOC_PROCESSOR_TABLE_H
+
+#include <QList>
+#include <QMap>
+#include <QObject>
+#include <QPair>
+#include <QStringList>
+
+
+/**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<WocEnum> 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<WocEnum> 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<QMap<QString,QString> > 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;
+ QList<WocEnum>enumvals;
+ QMap<QString,QString>methodcalls;
+ };
+ QList<s_col>m_columns,m_auditcolumns;
+ static QList<s_col>m_staticauditcolumns;
+ QList<QPair<QString,QString> >m_foreign;
+ QList<QMap<QString,QString> >m_presets;
+
+ QStringList m_docstrings;
+ QMap<QString,QString>m_fordocs;
+
+ //helper method: parses a single column element
+ static QPair<bool,s_col> parseColumn(const QDomElement&,QString);
+};
+
+
+#endif
--- /dev/null
+//
+// C++ Implementation: processor
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QDir>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QProcess>
+
+/******************************************************************************
+ * 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<QDomElement> nl=elementsByTagName(root,"Input");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ //variables
+ QList<QDomElement> nl2=elementsByTagName(el,"Var");
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString nm=el2.attribute("name");
+ if(!rval.exactMatch(nm)){
+ qDebug("Error: invalid input variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(hasInput(nm)){
+ qDebug("Error: double definition of input variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QString tp=el2.attribute("type");
+ //TODO: validate type
+ m_input.append(QPair<QString,QString>(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<nl.size();j++){
+ QDomElement el=nl.at(j).toElement();
+ if(el.isNull())continue;
+ QString nm=el.attribute("lang");
+ if(hasCall(nm)){
+ qDebug("Error: double definition of input variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QString mt=el.attribute("method");
+ m_call.insert(nm,mt);
+ }
+ //output
+ nl=elementsByTagName(root,"Output");
+ for(int i=0;i<nl.size();i++){
+ QDomElement el=nl.at(i).toElement();
+ if(el.isNull())continue;
+ //variables
+ QList<QDomElement> nl2=elementsByTagName(el,"Var");
+ for(int j=0;j<nl2.size();j++){
+ QDomElement el2=nl2.at(j).toElement();
+ if(el2.isNull())continue;
+ QString nm=el2.attribute("name");
+ if(!rval.exactMatch(nm)){
+ qDebug("Error: invalid output variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ if(hasOutput(nm)){
+ qDebug("Error: double definition of output variable %s in transaction %s.",nm.toAscii().data(),m_name.toAscii().data());
+ m_valid=false;
+ return;
+ }
+ QString tp=el2.attribute("type");
+ //TODO: validate type
+ m_output.append(QPair<QString,QString>(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<nl.size();i++){
+ QString s=nl.at(i).toElement().text().trimmed();
+ if(s!="")m_docstrings<<s;
+ }
+ //privileges
+ nl=elementsByTagName(root,"Privilege");
+ for(int i=0;i<nl.size();i++){
+ QString s=nl.at(i).toElement().attribute("name").trimmed();
+ if(s!="")m_privileges<<s;
+ m_privdoc.insert(s,nl.at(i).toElement().text().trimmed());
+ }
+}
+
+bool WocTransaction::hasInput(QString v)const
+{
+ for(int i=0;i<m_input.size();i++)
+ if(m_input[i].first==v)return true;
+ return false;
+}
+
+QStringList WocTransaction::inputNames()const
+{
+ QStringList r;
+ for(int i=0;i<m_input.size();i++)
+ r<<m_input[i].first;
+ return r;
+}
+
+QString WocTransaction::inputType(QString v)const
+{
+ for(int i=0;i<m_input.size();i++)
+ if(m_input[i].first==v)return m_input[i].second;
+ return "";
+}
+
+bool WocTransaction::hasOutput(QString v)const
+{
+ for(int i=0;i<m_output.size();i++)
+ if(m_output[i].first==v)return true;
+ return false;
+}
+
+QStringList WocTransaction::outputNames()const
+{
+ QStringList r;
+ for(int i=0;i<m_output.size();i++)
+ r<<m_output[i].first;
+ return r;
+}
+
+QString WocTransaction::outputType(QString v)const
+{
+ for(int i=0;i<m_output.size();i++)
+ if(m_output[i].first==v)return m_output[i].second;
+ return "";
+}
--- /dev/null
+//
+// C++ Interface: processor
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOC_PROCESSOR_TRANS_H
+#define WOC_PROCESSOR_TRANS_H
+
+#include <QList>
+#include <QMap>
+#include <QObject>
+#include <QPair>
+#include <QStringList>
+
+/**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<QString,QString> m_call;
+ QList<QPair<QString,QString> >m_input,m_output;
+ QStringList m_privileges;
+ //docu
+ QStringList m_docstrings;
+ QMap<QString,QString>m_indoc,m_outdoc,m_privdoc;
+};
+
+#endif
--- /dev/null
+//
+// C++ Implementation: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "qtout.h"
+#include "qtclass.h"
+
+#include <QDir>
+#include <QDomElement>
+
+#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 <QCoreApplication>\n\n";
+ QStringList k=cls.propertyNames();
+ for(int i=0;i<k.size();i++)
+ if(cls.propertyIsObject(k[i]))
+ hcd+="#include \""+m_prefix+"O"+cls.propertyPlainType(k[i])+".h\"\n";
+
+ //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 WocQtClass::classEnums(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
+{
+ QStringList k=cls.enumTypes();
+ if(k.size()==0)return;
+ QString hcd=" public:\n";
+ QString scd;
+ for(int i=0;i<k.size();i++){
+ //type
+ hcd+="\tenum "+k[i]+"{";
+ QList<WocEnum>ev=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;j<ev.size();j++){
+ if(j)hcd+=",";
+ hcd+="\n\t\t"+ev[j].name+"="+QString::number(ev[j].val);
+ }
+ hcd+="\n\t};\n";
+ //string converters
+ hcd+="\tstatic "+k[i]+" str2"+k[i]+"(QString,bool*ok=0);\n";
+ hcd+="\tstatic QString "+k[i]+"2str("+k[i]+");\n";
+ scd+=cn+"::"+k[i]+" "+cn+"::str2"+k[i]+"(QString s,bool*ok)\n{\n";
+ scd+="\ts=s.toLower();if(ok)*ok=true;\n";
+ for(int j=0;j<ev.size();j++){
+ scd+="\tif(s==\""+ev[j].name.toLower()+"\")return "+ev[j].name+";\n";
+ }
+ scd+="\tif(ok)*ok=false;\n\treturn "+ev[0].name+";\n}\n";
+ scd+="QString "+cn+"::"+k[i]+"2str("+k[i]+" e)\n{\n";
+ for(int j=0;j<ev.size();j++){
+ scd+="\tif(e=="+ev[j].name+")return \""+ev[j].name+"\";\n";
+ }
+ scd+="\treturn \"\";\n}\n";
+ //localized string converters
+ hcd+="\tstatic "+k[i]+" locstr2"+k[i]+"(QString,bool*ok=0);\n";
+ hcd+="\tstatic QString "+k[i]+"2locstr("+k[i]+");\n";
+ scd+=cn+"::"+k[i]+" "+cn+"::locstr2"+k[i]+"(QString s,bool*ok)\n{\n";
+ scd+="\ts=s.toLower();if(ok)*ok=true;\n";
+ for(int j=0;j<ev.size();j++){
+ scd+="\tif(s==QCoreApplication::translate(\""+cn+"\",\""+ev[j].name+"\").toLower())return "+ev[j].name+";\n";
+ }
+ scd+="\tif(ok)*ok=false;\n\treturn "+ev[0].name+";\n}\n";
+ scd+="QString "+cn+"::"+k[i]+"2locstr("+k[i]+" e)\n{\n";
+ for(int j=0;j<ev.size();j++){
+ scd+="\tif(e=="+ev[j].name+")return QCoreApplication::translate(\""+cn+"\",\""+ev[j].name+"\");\n";
+ }
+ scd+="\treturn \"\";\n}\n";
+ }
+ hdr.write(hcd.toAscii());
+ src.write(scd.toAscii());
+}
+
+void WocQtClass::classProperties(const WocClass&cls,MFile&hdr,MFile&)
+{
+ QStringList k=cls.propertyNames();
+ if(k.size()==0)return;
+ QString hcd,scd;
+ //declare members
+ hcd=" protected:\n";
+ for(int i=0;i<k.size();i++){
+ hcd+="\t"+qttype(cls,k[i])+" mp_"+k[i]+";\n";
+ }
+ //declare getters
+ hcd+=" public:\n";
+ for(int i=0;i<k.size();i++){
+ hcd+="\tvirtual "+qttype(cls,k[i])+" "+k[i]+"()const{return mp_"+k[i]+";}\n";
+ }
+
+ //declare setters
+ for(int i=0;i<k.size();i++){
+ hcd+="\tvirtual void set"+k[i]+"("+qttype(cls,k[i])+" s){mp_"+k[i]+"=s;}\n";
+ if(cls.propertyIsList(k[i])){
+ hcd+="\tvirtual void clear"+k[i]+"(){mp_"+k[i]+".clear();}\n";
+ hcd+="\tvirtual void add"+k[i]+"("+qttype(cls,k[i],false)+" a){mp_"+k[i]+".append(a);}\n";
+ }
+ }
+ //write
+ hdr.write(hcd.toAscii());
+}
+
+void WocQtClass::classDeserializer(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
+{
+ QString hcd,scd;
+ hcd=" public:\n";
+ //this is needed to allow WObjects to be Nullable and some other operations...
+ hcd+="\t"+cn+"(){}\n";
+
+ //implement copiers
+ QStringList k=cls.propertyNames();
+ hcd+="\t"+cn+"(const "+cn+"&);\n";
+ scd+=cn+"::"+cn+"(const "+cn+"&o)\n\t:WObject()\n{\n";
+ for(int i=0;i<k.size();i++)
+ scd+="\tmp_"+k[i]+"=o.mp_"+k[i]+";\n";
+ scd+="}\n";
+ hcd+="\t"+cn+"& operator=(const "+cn+"&);\n";
+ scd+=cn+"& "+cn+"::operator=(const "+cn+"&o)\n{\n";
+ for(int i=0;i<k.size();i++)
+ scd+="\tmp_"+k[i]+"=o.mp_"+k[i]+";\n";
+ scd+="\treturn *this;\n}\n";
+
+ //implement deserializer (as constructor)
+ hcd+="\t"+cn+"(const QDomElement&);\n";
+ scd+=cn+"::"+cn+"(const QDomElement&root)\n\t:WObject()\n{\n";
+ scd+="\tQList<QDomElement> nl;\n";
+ for(int i=0;i<k.size();i++){
+ if(cls.propertyIsList(k[i])){
+ scd+="\tnl=elementsByTagName(root,\""+k[i]+"\");\n";
+ scd+="\tfor(int i=0;i<nl.size();i++){\n\t\tQDomElement el=nl.at(i).toElement();\n";
+ scd+="\t\tif(el.isNull())continue;\n";
+ if(cls.propertyIsInt(k[i])){
+ scd+="\t\tbool b;\n\t\tint ct=el.text().toInt(&b);\n";
+ scd+="\t\tif(b)add"+k[i]+"(ct);\n";
+ scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is integer list, but non-integer was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
+ }else
+ if(cls.propertyIsBool(k[i])){
+ scd+="\t\tadd"+k[i]+"(el.text()==\"yes\");\n";
+ }else
+ if(cls.propertyIsString(k[i])){
+ scd+="\t\tadd"+k[i]+"(el.text());\n";
+ }else
+ if(cls.propertyIsBlob(k[i])){
+ scd+="\t\tadd"+k[i]+"(QByteArray::fromBase64(el.text().toAscii()));\n";
+ }else
+ if(cls.propertyIsEnum(k[i])){
+ scd+="\t\tbool b;\n";
+ QString pt=cls.propertyPlainType(k[i]);
+ scd+="\t\t"+pt+" ct=str2"+pt+"(root.attribute(\""+k[i]+"\"),&b);\n";
+ scd+="\t\tif(b)add"+k[i]+"(ct);\n";
+ scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is enum list, invalid value was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
+ }else
+ if(cls.propertyIsObject(k[i])){
+ scd+="\t\tadd"+k[i]+"("+m_prefix+"O"+cls.propertyPlainType(k[i])+"(el));\n";
+ }else{
+ scd+="#error \"Internal Generator error.\"\n";
+ qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
+ emit errorFound();
+ return;
+ }
+ scd+="\t}\n";
+ }else{
+ //non-list types
+ //attribute stored types
+ if(cls.propertyIsAttribute(k[i])){
+ scd+="\tif(root.hasAttribute(\""+k[i]+"\")){\n";
+ if(cls.propertyIsInt(k[i])){
+ scd+="\t\tbool b;\n\t\tint ct=root.attribute(\""+k[i]+"\").toInt(&b);\n";
+ scd+="\t\tif(b)set"+k[i]+"(ct);\n";
+ scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is integer, but non-integer was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
+ }else
+ if(cls.propertyIsBool(k[i])){
+ scd+="\t\tset"+k[i]+"(root.attribute(\""+k[i]+"\")==\"yes\");\n";
+ }else
+ if(cls.propertyIsString(k[i])){
+ scd+="\t\tset"+k[i]+"(root.attribute(\""+k[i]+"\"));\n";
+ }else
+ if(cls.propertyIsEnum(k[i])){
+ scd+="\t\tbool b;\n";
+ QString pt=cls.propertyPlainType(k[i]);
+ scd+="\t\t"+pt+" ct=str2"+pt+"(root.attribute(\""+k[i]+"\"),&b);\n";
+ scd+="\t\tif(b)set"+k[i]+"(ct);\n";
+ scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is enum, invalid value was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
+ }else{
+ scd+="#error \"Internal Generator error.\"\n";
+ qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
+ emit errorFound();
+ return;
+ }
+ scd+="\t}\n";
+ }else{
+ //element stored types...
+ scd+="\tnl=elementsByTagName(root,\""+k[i]+"\");\n";
+ scd+="\tif(nl.size()>0){\n";
+ if(cls.propertyIsString(k[i])){
+ scd+="\t\tset"+k[i]+"(nl.at(0).toElement().text());\n";
+ }else
+ if(cls.propertyIsBlob(k[i])){
+ scd+="\t\tset"+k[i]+"(QByteArray::fromBase64(nl.at(0).toElement().text().toAscii()));\n";
+ }else
+ if(cls.propertyIsObject(k[i])){
+ scd+="\t\tset"+k[i]+"("+m_prefix+"O"+cls.propertyPlainType(k[i])+"(nl.at(0).toElement()));\n";
+ }else{
+ scd+="#error \"Internal Generator error.\"\n";
+ qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
+ emit errorFound();
+ return;
+ }
+ scd+="\t}\n";
+ }
+ }
+ }
+ scd+="}\n";
+
+ //write it...
+ hdr.write(hcd.toAscii());
+ src.write(scd.toAscii());
+}
+
+void WocQtClass::classSerializers(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
+{
+ QString hcd=" public:\n";
+ QString scd;
+ hcd+="\tQString toString();\n";
+ scd+="QString "+cn+"::toString()\n{\n";
+ scd+="\tQDomDocument doc;\n\tdoc.appendChild(toXml(doc));\n";
+ scd+="\treturn doc.toString();\n}\n";
+ hcd+="\tQDomElement toXml(QDomDocument&,QString name=\""+cls.name()+"\");\n";
+ scd+="QDomElement "+cn+"::toXml(QDomDocument&doc,QString name)\n{\n";
+ scd+="\tQDomElement r=doc.createElement(name);\n";
+ QStringList p=cls.propertyNames();
+ for(int j=0;j<p.size();j++){
+ QStringList pv=p[j].split("/",QString::SkipEmptyParts);
+ if(pv.size()<1){
+ qDebug("Error: encountered empty property while creating serializer for class %s.",cls.name().toAscii().data());
+ emit errorFound();
+ return;
+ }
+ QString prop=pv[0];
+ QString var;
+ if(pv.size()>1)var=pv[1];
+ //is it a list
+ if(cls.propertyIsList(prop)){
+ scd+="\tfor(int i=0;i<mp_"+prop+".size();i++){\n";
+ if(cls.propertyIsObject(prop))
+ scd+="\t\tr.appendChild(mp_"+prop+"[i].toXml"+var+"(doc,\""+prop+"\"));\n";
+ else
+ if(cls.propertyIsEnum(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode("+cls.propertyPlainType(prop)+"2str(mp_"+prop+"[i])));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else
+ if(cls.propertyIsString(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+"[i]));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else
+ if(cls.propertyIsBool(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+"[i]?\"yes\":\"no\"));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else
+ if(cls.propertyIsBlob(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+"[i].toBase64()));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else
+ if(cls.propertyIsInt(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode(QString::number(mp_"+prop+"[i])));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else{
+ qDebug("Error: cannot generate serializer for class %s property %s.",cls.name().toAscii().data(),prop.toAscii().data());
+ emit errorFound();
+ return;
+ }
+ scd+="\t}\n";
+ }else{
+ //non lists
+ scd+="\tif(!mp_"+prop+".isNull()){\n";
+ if(cls.propertyIsAttribute(prop)){
+ if(cls.propertyIsBool(prop))
+ scd+="\t\tr.setAttribute(\""+prop+"\",mp_"+prop+".value()?\"yes\":\"no\");\n";
+ else
+ scd+="\t\tr.setAttribute(\""+prop+"\",mp_"+prop+".value());\n";
+ }else{
+ if(cls.propertyIsObject(prop)){
+ scd+="\t\tr.appendChild(mp_"+prop+".value().toXml"+var+"(doc,\""+prop+"\"));\n";
+ }else
+ if(cls.propertyIsString(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+".value()));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else
+ if(cls.propertyIsBlob(prop)){
+ scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
+ scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+".value().toBase64()));\n";
+ scd+="\t\tr.appendChild(el);\n";
+ }else{
+ qDebug("Error: cannot generate serializer for class %s property %s.",cls.name().toAscii().data(),prop.toAscii().data());
+ emit errorFound();
+ return;
+ }
+ }
+ scd+="\t}\n";
+ }
+ }
+ scd+="\treturn r;\n}\n";
+ hdr.write(hcd.toAscii());
+ src.write(scd.toAscii());
+}
--- /dev/null
+//
+// C++ Interface: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QObject>
+
+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
--- /dev/null
+//
+// C++ Implementation: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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 <QDomElement>\n"
+ "#include <QDomDocument>\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
--- /dev/null
+//
+// C++ Implementation: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "qtout.h"
+#include "qtctrans.h"
+
+#include <QDir>
+#include <QDomElement>
+
+#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 <QCoreApplication>\n";
+ for(int i=0;i<in.size();i++){
+ QString tp=qtobjtype(trn,in[i],WocQtOut::In);
+ if(tp!="")hcd+="#include <"+tp+".h>\n";
+ }
+ for(int i=0;i<out.size();i++){
+ QString tp=qtobjtype(trn,out[i],WocQtOut::Out);
+ if(tp!="")hcd+="#include <"+tp+".h>\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;i<in.size();i++){
+ hcd+="\t"+qttype(trn,in[i],WocQtOut::In)+"in_"+in[i]+";\n";
+ if(i){inlist+=",";clist+=",";}
+ inlist+="const "+qttype(trn,in[i],WocQtOut::In)+"&a"+in[i];
+ clist+="a"+in[i];
+ }
+ for(int i=0;i<out.size();i++)
+ hcd+="\t"+qttype(trn,out[i],WocQtOut::Out)+"out_"+out[i]+";\n";
+ hdr.write(hcd.toAscii());
+
+ //query method decl
+ hdr.write(QByteArray("\tvoid netquery();\n"));
+
+ //global interface code
+ QString sif=" "+cn+" query"+trn.name()+"("+inlist+")\n\t";
+ sif+="{return "+cn+"::query("+clist+(clist!=""?",":"")+"name());}\n";
+ m_iface.write(sif.toAscii());
+
+ //create constructors
+ if(inlist!="")inlist+=",";
+ inlist+="QString iface";
+ if(clist!="")clist+=",";
+ clist+="iface";
+ QString defparm="=\""+WocProcessor::instance()->projectName()+"\"";
+ //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;i<in.size();i++){
+ scd+="\tin_"+in[i]+"=a"+in[i]+";\n";
+ }
+ scd+="}\n\n";
+ //decl copy constructor
+ hcd+="\t"+cn+"(const "+cn+"&);\n";
+ //copy constructor implementation
+ scd+=cn+"::"+cn+"(const "+cn+"&t)\n\t:"+m_transbase+"(t)\n{\n";
+ for(int i=0;i<in.size();i++){
+ scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
+ }
+ scd+="}\n\n";
+ //decl copy operator
+ hcd+="\t"+cn+"& operator=(const "+cn+"&);\n";
+ //copy operator implemented
+ scd+=cn+"& "+cn+"::operator=(const "+cn+"&t)\n{\n";
+ scd+="\t"+m_transbase+"::operator=(t);\n";
+ for(int i=0;i<in.size();i++){
+ scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
+ }
+ for(int i=0;i<out.size();i++){
+ scd+="\tout_"+out[i]+"=t.out_"+out[i]+";\n";
+ }
+ scd+="\treturn *this;\n}\n\n";
+
+ //query method implemented
+ scd+="void "+cn+"::netquery()\n{\n";
+ scd+="\tWTLog log(this,\""+trn.name()+"\");\n";
+ scd+="\tQDomDocument doc;QDomElement root=doc.createElement(\"WobRequest-"+trn.name()+"\");\n";
+ scd+="\tQDomElement tmp;\n";
+ scd+="\tWInterface *iface=WInterface::instance(m_iface);\n";
+ scd+="\tif(iface==0){m_errtype=\"_iface\";m_errstr=\"interface not found\";m_stage=Error;log.setError(m_errstr);return;}\n";
+ //encode input
+ scd+=trnInput(trn);
+ scd+="\tdoc.appendChild(root);\n";
+ //query
+ scd+="\tQByteArray rba=executeQuery(\""+trn.name()+"\",doc.toByteArray());\n";
+ //decode output
+ scd+=trnOutput(trn);
+ scd+="}\n";
+ hdr.write(hcd.toAscii());
+ src.write(scd.toAscii());
+
+
+ //create getters
+ hcd="";
+ for(int i=0;i<out.size();i++){
+ QString tp=qttype(trn,out[i],WocQtOut::Out);
+ hcd+="\t"+tp+" get"+out[i]+"(){return out_"+out[i]+";}\n";
+ }
+ //create queries
+ scd="";
+ hcd+="\tstatic "+cn+" query("+inlist+defparm+");\n";
+ scd+=cn+" "+cn+"::query("+inlist+")\n{\n";
+ scd+="\t"+cn;
+ if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;";
+ scd+="\tr.netquery();\n\treturn r;\n}\n";
+
+ //lead out
+ hdr.write(hcd.toAscii());
+ src.write(scd.toAscii());
+ hdr.write(QByteArray("\n};\n"));
+ hdr.write(QByteArray(HDREND).replace("%",cn.toAscii()));
+ src.write(QByteArray(SRCEND).replace("%",cn.toAscii()));
+}
+
+QString WocQtClientTransaction::trnInput(const WocTransaction&trn)
+{
+ QString code="\t/*start of input encoding*/\n";
+ QStringList sl=trn.inputNames();
+ for(int i=0;i<sl.size();i++){
+ QString t=trn.inputType(sl[i]);
+ if(trn.isAttributeType(t)){
+ code+="\troot.setAttribute(\""+sl[i]+"\",in_"+sl[i];
+ if(trn.isBoolType(t))
+ code+="?\"yes\":\"no\"";
+ code+=");\n";
+ }else{
+ if(trn.isListType(t)){
+ QString pt=trn.plainType(t);
+ code+="\tfor(int i=0;i<in_"+sl[i]+".size();i++){\n";
+ if(trn.isObjectType(t)){
+ code+="\t\ttmp=in_"+sl[i]+"[i].toXml(doc,\""+sl[i]+"\");\n";
+ }else{
+ code+="\t\ttmp=doc.createElement(\""+sl[i]+"\");\n";
+ code+="\t\ttmp.appendChild(doc.createTextNode(";
+ if(trn.isIntType(t))
+ code+="QString::number(in_"+sl[i]+"[i])";
+ else
+ if(trn.isBoolType(t))
+ code+="in_"+sl[i]+"[i]?\"yes\":\"no\"";
+ else
+ if(trn.isBlobType(t))
+ code+="in_"+sl[i]+".toBase64()";
+ else
+ code+="in_"+sl[i]+"[i]";
+ code+="));\n";
+ }
+ code+="\t\troot.appendChild(tmp);\n";
+ code+="\t}\n";
+ }else{
+ if(trn.isObjectType(t)){
+ code+="\troot.appendChild(in_"+sl[i]+".toXml(doc,\""+sl[i]+"\"));\n";
+ }else{
+ code+="\ttmp=doc.createElement(\""+sl[i]+"\");\n";
+ code+="\ttmp.appendChild(doc.createTextNode(";
+ if(trn.isIntType(t))
+ code+="QString::number(in_"+sl[i]+")";
+ else
+ if(trn.isBlobType(t))
+ code+="in_"+sl[i]+".toBase64()";
+ else
+ code+="in_"+sl[i];
+ code+="));\n\troot.appendChild(tmp);\n";
+ }
+ }
+ }
+ }
+ code+="\t/*end of input encoding*/\n";
+ return code;
+}
+
+QString WocQtClientTransaction::trnOutput(const WocTransaction&trn)
+{
+ QStringList sl=trn.outputNames();
+ QString code="\t/*start of output decoding*/\n";
+ //basic XML parsing
+ code+="\tif(rba.isEmpty())return;\n";
+ code+="\tdoc=QDomDocument();\n";
+ code+="\tQString emsg;int eln,ecl;\n";
+ code+="\tif(!doc.setContent(rba,&emsg,&eln,&ecl)){\n";
+ code+="\t\tm_stage=Error;m_errtype=\"_iface\";m_errstr=QString(QCoreApplication::translate(\"WobTransaction\",\"XML result parser error line %1 col %2: %3\")).arg(eln).arg(ecl).arg(emsg);\n\t\tlog.setError(m_errstr);\n\t\treturn;\n\t}\n";
+ code+="\troot=doc.documentElement();\n";
+ //decide where to go, error handling
+ code+="\tif(m_wobstatus!=\"ok\"){\n\t\tm_stage=Error;m_errtype=\"_server\";m_errstr=\"unknown server error\";\n";
+ code+="\t\tQString terr=root.text().trimmed();\n";
+ code+="\t\tif(terr==\"\"){\n\t\t\tlog.setError(m_errstr);\n\t\t\treturn;\n\t\t}\n";
+ code+="\t\tm_errtype=root.attribute(\"type\",\"_server\");\n";
+ code+="\t\tm_errstr=terr;\n\t\tlog.setError(m_errstr);\n\t\treturn;\n\t}\n";
+ code+="\tQList<QDomElement> nl;\n";
+ //parse parameters
+ for(int i=0;i<sl.size();i++){
+ QString t=trn.outputType(sl[i]);
+ if(trn.isAttributeType(t)){
+ code+="\tout_"+sl[i]+"=root.attribute(\""+sl[i]+"\")";
+ if(trn.isIntType(t))code+=".toInt()";else
+ if(trn.isBoolType(t))code+="==\"yes\"";
+ code+=";\n";
+ }else{
+ code+="\tnl=elementsByTagName(root,\""+sl[i]+"\");\n";
+ if(trn.isListType(t)){
+ code+="\tfor(int i=0;i<nl.size();i++){\n";
+ if(trn.isObjectType(t)){
+ code+="\t\ttry{out_"+sl[i]+".append("+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(i).toElement()));}catch(WException e){m_stage=Error;m_errtype=e.component();m_errstr=e.error();log.setError(m_errstr);}\n";
+ }else if(trn.isIntType(t)){
+ code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text().toInt());\n";
+ }else if(trn.isBoolType(t)){
+ code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text()==\"yes\");\n";
+ }else if(trn.isBlobType(t)){
+ code+="\t\tout_"+sl[i]+".append(QByteArray::fromBase64(nl.at(i).toElement().text().toAscii()));\n";
+ }else{//can only be string
+ code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text());\n";
+ }
+ code+="\t}\n";
+ }else{
+ code+="\tif(nl.size()>0){\n";
+ if(trn.isObjectType(t)){
+ code+="\t\ttry{out_"+sl[i]+"="+qtobjtype(trn,sl[i],WocQtOut::Out)+"(nl.at(0).toElement());}catch(WException e){m_stage=Error;m_errtype=e.component();m_errstr=e.error();log.setError(m_errstr);}\n";
+ }else if(trn.isBlobType(t)){
+ code+="\t\tout_"+sl[i]+"=QByteArray::fromBase64(nl.at(0).toElement().text().toAscii());\n";
+ }else{//can only be string
+ code+="\t\tout_"+sl[i]+"=nl.at(0).toElement().text();\n";
+ }
+ code+="\t}\n";
+ }
+ }
+ }
+ code+="\t/*end of output*/\n";
+ return code;
+}
+
+void WocQtClientTransaction::trnList()
+{
+ QString code;
+ //header
+ code+=" enum Right {\n NoRight";
+ QStringList r=WocProcessor::instance()->transactionNames();
+ QStringList p=WocProcessor::instance()->privilegeNames();
+ QStringList pp=p;
+ for(int i=0;i<r.size();i++)
+ code+=",\n R"+r[i];
+ for(int i=0;i<p.size();i++)
+ code+=",\n P"+pp[i].replace(':',"_");
+ code+="\n };\n";
+ code+=" static QString rightToString(Right);\n";
+ code+=" static QString rightToLocalString(Right);\n";
+ code+=" static Right stringToRight(QString);\n";
+ code+=" static QStringList allKnownRightsString();\n";
+ code+=" static QList<Right> allKnownRights();\n";
+ m_iface.write(code.toAscii());
+
+ code="QString "+m_prefix+"Interface::rightToString(Right r)\n{\n\tswitch(r){\n";
+ for(int i=0;i<r.size();i++)
+ code+="\t\tcase R"+r[i]+":return \""+r[i]+"\";\n";
+ for(int i=0;i<p.size();i++)
+ code+="\t\tcase P"+pp[i]+":return \""+p[i]+"\";\n";
+ code+="\t\tdefault:return \"\";\n\t}\n}\n";
+ code+="QString "+m_prefix+"Interface::rightToLocalString(Right r)\n{\n\tswitch(r){\n";
+ for(int i=0;i<r.size();i++)
+ code+="\t\tcase R"+r[i]+":return tr(\""+r[i]+"\");\n";
+ for(int i=0;i<p.size();i++)
+ code+="\t\tcase P"+pp[i]+":return tr(\""+p[i]+"\");\n";
+ code+="\t\tdefault:return \"\";\n\t}\n}\n";
+ code+=m_prefix+"Interface::Right "+m_prefix+"Interface::stringToRight(QString s)\n{\n";
+ for(int i=0;i<r.size();i++)
+ code+="\tif(s==\""+r[i]+"\")return R"+r[i]+";else\n";
+ for(int i=0;i<p.size();i++)
+ code+="\tif(s==\""+p[i]+"\")return P"+pp[i]+";else\n";
+ code+="\treturn NoRight;\n}\n";
+ code+="QList<"+m_prefix+"Interface::Right> "+m_prefix+"Interface::allKnownRights()\n{\n";
+ code+="\tQList<Right> ret;ret";
+ for(int i=0;i<r.size();i++)
+ code+="<<R"+r[i];
+ for(int i=0;i<p.size();i++)
+ code+="<<P"+pp[i];
+ code+=";\n\treturn ret;\n}\n";
+ code+="QStringList "+m_prefix+"Interface::allKnownRightsString()\n{\n";
+ code+="\tQStringList ret;ret";
+ for(int i=0;i<r.size();i++)
+ code+="<<\""+r[i]+"\"";
+ for(int i=0;i<p.size();i++)
+ code+="<<\""+p[i]+"\"";
+ code+=";\n\treturn ret;\n}\n";
+ m_ifacecpp.write(code.toAscii());
+}
--- /dev/null
+//
+// C++ Interface: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
--- /dev/null
+//
+// C++ Implementation: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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&){}
--- /dev/null
+//
+// C++ Interface: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
//
#include "qtout.h"
+#include "qtctrans.h"
+#include "qtstrans.h"
+#include "qtclass.h"
+#include "qtdb.h"
#include <QDir>
#include <QDomElement>
-//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 <QDomElement>\n"
- "#include <QDomDocument>\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");
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);
}
}
-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 <QCoreApplication>\n\n";
- QStringList k=cls.propertyNames();
- for(int i=0;i<k.size();i++)
- if(cls.propertyIsObject(k[i]))
- hcd+="#include \""+m_prefix+"O"+cls.propertyPlainType(k[i])+".h\"\n";
+ if(qtable)qtable->newTable(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;i<k.size();i++){
- //type
- hcd+="\tenum "+k[i]+"{";
- QList<WocEnum>ev=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;j<ev.size();j++){
- if(j)hcd+=",";
- hcd+="\n\t\t"+ev[j].name+"="+QString::number(ev[j].val);
- }
- hcd+="\n\t};\n";
- //string converters
- hcd+="\tstatic "+k[i]+" str2"+k[i]+"(QString,bool*ok=0);\n";
- hcd+="\tstatic QString "+k[i]+"2str("+k[i]+");\n";
- scd+=cn+"::"+k[i]+" "+cn+"::str2"+k[i]+"(QString s,bool*ok)\n{\n";
- scd+="\ts=s.toLower();if(ok)*ok=true;\n";
- for(int j=0;j<ev.size();j++){
- scd+="\tif(s==\""+ev[j].name.toLower()+"\")return "+ev[j].name+";\n";
- }
- scd+="\tif(ok)*ok=false;\n\treturn "+ev[0].name+";\n}\n";
- scd+="QString "+cn+"::"+k[i]+"2str("+k[i]+" e)\n{\n";
- for(int j=0;j<ev.size();j++){
- scd+="\tif(e=="+ev[j].name+")return \""+ev[j].name+"\";\n";
- }
- scd+="\treturn \"\";\n}\n";
- //localized string converters
- hcd+="\tstatic "+k[i]+" locstr2"+k[i]+"(QString,bool*ok=0);\n";
- hcd+="\tstatic QString "+k[i]+"2locstr("+k[i]+");\n";
- scd+=cn+"::"+k[i]+" "+cn+"::locstr2"+k[i]+"(QString s,bool*ok)\n{\n";
- scd+="\ts=s.toLower();if(ok)*ok=true;\n";
- for(int j=0;j<ev.size();j++){
- scd+="\tif(s==QCoreApplication::translate(\""+cn+"\",\""+ev[j].name+"\").toLower())return "+ev[j].name+";\n";
- }
- scd+="\tif(ok)*ok=false;\n\treturn "+ev[0].name+";\n}\n";
- scd+="QString "+cn+"::"+k[i]+"2locstr("+k[i]+" e)\n{\n";
- for(int j=0;j<ev.size();j++){
- scd+="\tif(e=="+ev[j].name+")return QCoreApplication::translate(\""+cn+"\",\""+ev[j].name+"\");\n";
- }
- scd+="\treturn \"\";\n}\n";
- }
- hdr.write(hcd.toAscii());
- src.write(scd.toAscii());
+ if(qtrans)qtrans->newTransaction(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;i<k.size();i++){
- hcd+="\t"+qttype(cls,k[i])+" mp_"+k[i]+";\n";
- }
- //declare getters
- hcd+=" public:\n";
- for(int i=0;i<k.size();i++){
- hcd+="\tvirtual "+qttype(cls,k[i])+" "+k[i]+"()const{return mp_"+k[i]+";}\n";
- }
-
- //declare setters
- for(int i=0;i<k.size();i++){
- hcd+="\tvirtual void set"+k[i]+"("+qttype(cls,k[i])+" s){mp_"+k[i]+"=s;}\n";
- if(cls.propertyIsList(k[i])){
- hcd+="\tvirtual void clear"+k[i]+"(){mp_"+k[i]+".clear();}\n";
- hcd+="\tvirtual void add"+k[i]+"("+qttype(cls,k[i],false)+" a){mp_"+k[i]+".append(a);}\n";
- }
- }
- //write
- hdr.write(hcd.toAscii());
+ QString code="HEADERS+="+m_subdir+"/"+bn+".h\nSOURCES+="+m_subdir+"/"+bn+".cpp\n";
+ m_pri.write(code.toAscii());
+ m_hdr.write(QByteArray("#include \"%.h\"\n").replace('%',bn.toAscii()));
}
-QString WocQtClientOut::qttype(const WocClass&cls,QString p,bool dolist)
+QString WocQtOut::qttype(const WocClass&cls,QString p,bool dolist)
{
QString r;
if(cls.propertyIsList(p)&&dolist)r="QList<";
return r;
}
-void WocQtClientOut::classDeserializer(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
-{
- QString hcd,scd;
- hcd=" public:\n";
- //this is needed to allow WObjects to be Nullable and some other operations...
- hcd+="\t"+cn+"(){}\n";
-
- //implement copiers
- QStringList k=cls.propertyNames();
- hcd+="\t"+cn+"(const "+cn+"&);\n";
- scd+=cn+"::"+cn+"(const "+cn+"&o)\n\t:WObject()\n{\n";
- for(int i=0;i<k.size();i++)
- scd+="\tmp_"+k[i]+"=o.mp_"+k[i]+";\n";
- scd+="}\n";
- hcd+="\t"+cn+"& operator=(const "+cn+"&);\n";
- scd+=cn+"& "+cn+"::operator=(const "+cn+"&o)\n{\n";
- for(int i=0;i<k.size();i++)
- scd+="\tmp_"+k[i]+"=o.mp_"+k[i]+";\n";
- scd+="\treturn *this;\n}\n";
-
- //implement deserializer (as constructor)
- hcd+="\t"+cn+"(const QDomElement&);\n";
- scd+=cn+"::"+cn+"(const QDomElement&root)\n\t:WObject()\n{\n";
- scd+="\tQList<QDomElement> nl;\n";
- for(int i=0;i<k.size();i++){
- if(cls.propertyIsList(k[i])){
- scd+="\tnl=elementsByTagName(root,\""+k[i]+"\");\n";
- scd+="\tfor(int i=0;i<nl.size();i++){\n\t\tQDomElement el=nl.at(i).toElement();\n";
- scd+="\t\tif(el.isNull())continue;\n";
- if(cls.propertyIsInt(k[i])){
- scd+="\t\tbool b;\n\t\tint ct=el.text().toInt(&b);\n";
- scd+="\t\tif(b)add"+k[i]+"(ct);\n";
- scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is integer list, but non-integer was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
- }else
- if(cls.propertyIsBool(k[i])){
- scd+="\t\tadd"+k[i]+"(el.text()==\"yes\");\n";
- }else
- if(cls.propertyIsString(k[i])){
- scd+="\t\tadd"+k[i]+"(el.text());\n";
- }else
- if(cls.propertyIsBlob(k[i])){
- scd+="\t\tadd"+k[i]+"(QByteArray::fromBase64(el.text().toAscii()));\n";
- }else
- if(cls.propertyIsEnum(k[i])){
- scd+="\t\tbool b;\n";
- QString pt=cls.propertyPlainType(k[i]);
- scd+="\t\t"+pt+" ct=str2"+pt+"(root.attribute(\""+k[i]+"\"),&b);\n";
- scd+="\t\tif(b)add"+k[i]+"(ct);\n";
- scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is enum list, invalid value was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
- }else
- if(cls.propertyIsObject(k[i])){
- scd+="\t\tadd"+k[i]+"("+m_prefix+"O"+cls.propertyPlainType(k[i])+"(el));\n";
- }else{
- scd+="#error \"Internal Generator error.\"\n";
- qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
- emit errorFound();
- return;
- }
- scd+="\t}\n";
- }else{
- //non-list types
- //attribute stored types
- if(cls.propertyIsAttribute(k[i])){
- scd+="\tif(root.hasAttribute(\""+k[i]+"\")){\n";
- if(cls.propertyIsInt(k[i])){
- scd+="\t\tbool b;\n\t\tint ct=root.attribute(\""+k[i]+"\").toInt(&b);\n";
- scd+="\t\tif(b)set"+k[i]+"(ct);\n";
- scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is integer, but non-integer was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
- }else
- if(cls.propertyIsBool(k[i])){
- scd+="\t\tset"+k[i]+"(root.attribute(\""+k[i]+"\")==\"yes\");\n";
- }else
- if(cls.propertyIsString(k[i])){
- scd+="\t\tset"+k[i]+"(root.attribute(\""+k[i]+"\"));\n";
- }else
- if(cls.propertyIsEnum(k[i])){
- scd+="\t\tbool b;\n";
- QString pt=cls.propertyPlainType(k[i]);
- scd+="\t\t"+pt+" ct=str2"+pt+"(root.attribute(\""+k[i]+"\"),&b);\n";
- scd+="\t\tif(b)set"+k[i]+"(ct);\n";
- scd+="\t\telse throw WDeserializerException(QCoreApplication::translate(\"WobTransaction\",\"Class '%1' property '%2' is enum, invalid value was found.\").arg(\""+cn+"\").arg(\""+k[i]+"\"));\n";
- }else{
- scd+="#error \"Internal Generator error.\"\n";
- qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
- emit errorFound();
- return;
- }
- scd+="\t}\n";
- }else{
- //element stored types...
- scd+="\tnl=elementsByTagName(root,\""+k[i]+"\");\n";
- scd+="\tif(nl.size()>0){\n";
- if(cls.propertyIsString(k[i])){
- scd+="\t\tset"+k[i]+"(nl.at(0).toElement().text());\n";
- }else
- if(cls.propertyIsBlob(k[i])){
- scd+="\t\tset"+k[i]+"(QByteArray::fromBase64(nl.at(0).toElement().text().toAscii()));\n";
- }else
- if(cls.propertyIsObject(k[i])){
- scd+="\t\tset"+k[i]+"("+m_prefix+"O"+cls.propertyPlainType(k[i])+"(nl.at(0).toElement()));\n";
- }else{
- scd+="#error \"Internal Generator error.\"\n";
- qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
- emit errorFound();
- return;
- }
- scd+="\t}\n";
- }
- }
- }
- scd+="}\n";
-
- //write it...
- hdr.write(hcd.toAscii());
- src.write(scd.toAscii());
-}
-
-void WocQtClientOut::classSerializers(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
-{
- QString hcd=" public:\n";
- QString scd;
- hcd+="\tQString toString();\n";
- scd+="QString "+cn+"::toString()\n{\n";
- scd+="\tQDomDocument doc;\n\tdoc.appendChild(toXml(doc));\n";
- scd+="\treturn doc.toString();\n}\n";
- hcd+="\tQDomElement toXml(QDomDocument&,QString name=\""+cls.name()+"\");\n";
- scd+="QDomElement "+cn+"::toXml(QDomDocument&doc,QString name)\n{\n";
- scd+="\tQDomElement r=doc.createElement(name);\n";
- QStringList p=cls.propertyNames();
- for(int j=0;j<p.size();j++){
- QStringList pv=p[j].split("/",QString::SkipEmptyParts);
- if(pv.size()<1){
- qDebug("Error: encountered empty property while creating serializer for class %s.",cls.name().toAscii().data());
- emit errorFound();
- return;
- }
- QString prop=pv[0];
- QString var;
- if(pv.size()>1)var=pv[1];
- //is it a list
- if(cls.propertyIsList(prop)){
- scd+="\tfor(int i=0;i<mp_"+prop+".size();i++){\n";
- if(cls.propertyIsObject(prop))
- scd+="\t\tr.appendChild(mp_"+prop+"[i].toXml"+var+"(doc,\""+prop+"\"));\n";
- else
- if(cls.propertyIsEnum(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode("+cls.propertyPlainType(prop)+"2str(mp_"+prop+"[i])));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else
- if(cls.propertyIsString(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+"[i]));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else
- if(cls.propertyIsBool(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+"[i]?\"yes\":\"no\"));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else
- if(cls.propertyIsBlob(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+"[i].toBase64()));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else
- if(cls.propertyIsInt(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode(QString::number(mp_"+prop+"[i])));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else{
- qDebug("Error: cannot generate serializer for class %s property %s.",cls.name().toAscii().data(),prop.toAscii().data());
- emit errorFound();
- return;
- }
- scd+="\t}\n";
- }else{
- //non lists
- scd+="\tif(!mp_"+prop+".isNull()){\n";
- if(cls.propertyIsAttribute(prop)){
- if(cls.propertyIsBool(prop))
- scd+="\t\tr.setAttribute(\""+prop+"\",mp_"+prop+".value()?\"yes\":\"no\");\n";
- else
- scd+="\t\tr.setAttribute(\""+prop+"\",mp_"+prop+".value());\n";
- }else{
- if(cls.propertyIsObject(prop)){
- scd+="\t\tr.appendChild(mp_"+prop+".value().toXml"+var+"(doc,\""+prop+"\"));\n";
- }else
- if(cls.propertyIsString(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+".value()));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else
- if(cls.propertyIsBlob(prop)){
- scd+="\t\tQDomElement el=doc.createElement(\""+prop+"\");\n";
- scd+="\t\tel.appendChild(doc.createTextNode(mp_"+prop+".value().toBase64()));\n";
- scd+="\t\tr.appendChild(el);\n";
- }else{
- qDebug("Error: cannot generate serializer for class %s property %s.",cls.name().toAscii().data(),prop.toAscii().data());
- emit errorFound();
- return;
- }
- }
- scd+="\t}\n";
- }
- }
- scd+="\treturn r;\n}\n";
- hdr.write(hcd.toAscii());
- src.write(scd.toAscii());
-}
-
-void WocQtClientOut::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 <QCoreApplication>\n";
- for(int i=0;i<in.size();i++){
- QString tp=qtobjtype(trn,in[i],In);
- if(tp!="")hcd+="#include <"+tp+".h>\n";
- }
- for(int i=0;i<out.size();i++){
- QString tp=qtobjtype(trn,out[i],Out);
- if(tp!="")hcd+="#include <"+tp+".h>\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;i<in.size();i++){
- hcd+="\t"+qttype(trn,in[i],In)+"in_"+in[i]+";\n";
- if(i){inlist+=",";clist+=",";}
- inlist+="const "+qttype(trn,in[i],In)+"&a"+in[i];
- clist+="a"+in[i];
- }
- for(int i=0;i<out.size();i++)
- hcd+="\t"+qttype(trn,out[i],Out)+"out_"+out[i]+";\n";
- hdr.write(hcd.toAscii());
-
- //query method decl
- hdr.write(QByteArray("\tvoid netquery();\n"));
-
- //global interface code
- QString sif=" "+cn+" query"+trn.name()+"("+inlist+")\n\t";
- sif+="{return "+cn+"::query("+clist+(clist!=""?",":"")+"name());}\n";
- m_iface.write(sif.toAscii());
-
- //create constructors
- if(inlist!="")inlist+=",";
- inlist+="QString iface";
- if(clist!="")clist+=",";
- clist+="iface";
- QString defparm="=\""+WocProcessor::instance()->projectName()+"\"";
- //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;i<in.size();i++){
- scd+="\tin_"+in[i]+"=a"+in[i]+";\n";
- }
- scd+="}\n\n";
- //decl copy constructor
- hcd+="\t"+cn+"(const "+cn+"&);\n";
- //copy constructor implementation
- scd+=cn+"::"+cn+"(const "+cn+"&t)\n\t:"+m_transbase+"(t)\n{\n";
- for(int i=0;i<in.size();i++){
- scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
- }
- scd+="}\n\n";
- //decl copy operator
- hcd+="\t"+cn+"& operator=(const "+cn+"&);\n";
- //copy operator implemented
- scd+=cn+"& "+cn+"::operator=(const "+cn+"&t)\n{\n";
- scd+="\t"+m_transbase+"::operator=(t);\n";
- for(int i=0;i<in.size();i++){
- scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
- }
- for(int i=0;i<out.size();i++){
- scd+="\tout_"+out[i]+"=t.out_"+out[i]+";\n";
- }
- scd+="\treturn *this;\n}\n\n";
-
- //query method implemented
- scd+="void "+cn+"::netquery()\n{\n";
- scd+="\tWTLog log(this,\""+trn.name()+"\");\n";
- scd+="\tQDomDocument doc;QDomElement root=doc.createElement(\"WobRequest-"+trn.name()+"\");\n";
- scd+="\tQDomElement tmp;\n";
- scd+="\tWInterface *iface=WInterface::instance(m_iface);\n";
- scd+="\tif(iface==0){m_errtype=\"_iface\";m_errstr=\"interface not found\";m_stage=Error;log.setError(m_errstr);return;}\n";
- //encode input
- scd+=trnInput(trn);
- scd+="\tdoc.appendChild(root);\n";
- //query
- scd+="\tQByteArray rba=executeQuery(\""+trn.name()+"\",doc.toByteArray());\n";
- //decode output
- scd+=trnOutput(trn);
- scd+="}\n";
- hdr.write(hcd.toAscii());
- src.write(scd.toAscii());
-
-
- //create getters
- hcd="";
- for(int i=0;i<out.size();i++){
- QString tp=qttype(trn,out[i],Out);
- hcd+="\t"+tp+" get"+out[i]+"(){return out_"+out[i]+";}\n";
- }
- //create queries
- scd="";
- hcd+="\tstatic "+cn+" query("+inlist+defparm+");\n";
- scd+=cn+" "+cn+"::query("+inlist+")\n{\n";
- scd+="\t"+cn;
- if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;";
- scd+="\tr.netquery();\n\treturn r;\n}\n";
-
- //lead out
- hdr.write(hcd.toAscii());
- src.write(scd.toAscii());
- hdr.write(QByteArray("\n};\n"));
- hdr.write(QByteArray(HDREND).replace("%",cn.toAscii()));
- src.write(QByteArray(SRCEND).replace("%",cn.toAscii()));
-}
-
-QString WocQtClientOut::trnInput(const WocTransaction&trn)
-{
- QString code="\t/*start of input encoding*/\n";
- QStringList sl=trn.inputNames();
- for(int i=0;i<sl.size();i++){
- QString t=trn.inputType(sl[i]);
- if(trn.isAttributeType(t)){
- code+="\troot.setAttribute(\""+sl[i]+"\",in_"+sl[i];
- if(trn.isBoolType(t))
- code+="?\"yes\":\"no\"";
- code+=");\n";
- }else{
- if(trn.isListType(t)){
- QString pt=trn.plainType(t);
- code+="\tfor(int i=0;i<in_"+sl[i]+".size();i++){\n";
- if(trn.isObjectType(t)){
- code+="\t\ttmp=in_"+sl[i]+"[i].toXml(doc,\""+sl[i]+"\");\n";
- }else{
- code+="\t\ttmp=doc.createElement(\""+sl[i]+"\");\n";
- code+="\t\ttmp.appendChild(doc.createTextNode(";
- if(trn.isIntType(t))
- code+="QString::number(in_"+sl[i]+"[i])";
- else
- if(trn.isBoolType(t))
- code+="in_"+sl[i]+"[i]?\"yes\":\"no\"";
- else
- if(trn.isBlobType(t))
- code+="in_"+sl[i]+".toBase64()";
- else
- code+="in_"+sl[i]+"[i]";
- code+="));\n";
- }
- code+="\t\troot.appendChild(tmp);\n";
- code+="\t}\n";
- }else{
- if(trn.isObjectType(t)){
- code+="\troot.appendChild(in_"+sl[i]+".toXml(doc,\""+sl[i]+"\"));\n";
- }else{
- code+="\ttmp=doc.createElement(\""+sl[i]+"\");\n";
- code+="\ttmp.appendChild(doc.createTextNode(";
- if(trn.isIntType(t))
- code+="QString::number(in_"+sl[i]+")";
- else
- if(trn.isBlobType(t))
- code+="in_"+sl[i]+".toBase64()";
- else
- code+="in_"+sl[i];
- code+="));\n\troot.appendChild(tmp);\n";
- }
- }
- }
- }
- code+="\t/*end of input encoding*/\n";
- return code;
-}
-
-QString WocQtClientOut::trnOutput(const WocTransaction&trn)
-{
- QStringList sl=trn.outputNames();
- QString code="\t/*start of output decoding*/\n";
- //basic XML parsing
- code+="\tif(rba.isEmpty())return;\n";
- code+="\tdoc=QDomDocument();\n";
- code+="\tQString emsg;int eln,ecl;\n";
- code+="\tif(!doc.setContent(rba,&emsg,&eln,&ecl)){\n";
- code+="\t\tm_stage=Error;m_errtype=\"_iface\";m_errstr=QString(QCoreApplication::translate(\"WobTransaction\",\"XML result parser error line %1 col %2: %3\")).arg(eln).arg(ecl).arg(emsg);\n\t\tlog.setError(m_errstr);\n\t\treturn;\n\t}\n";
- code+="\troot=doc.documentElement();\n";
- //decide where to go, error handling
- code+="\tif(m_wobstatus!=\"ok\"){\n\t\tm_stage=Error;m_errtype=\"_server\";m_errstr=\"unknown server error\";\n";
- code+="\t\tQString terr=root.text().trimmed();\n";
- code+="\t\tif(terr==\"\"){\n\t\t\tlog.setError(m_errstr);\n\t\t\treturn;\n\t\t}\n";
- code+="\t\tm_errtype=root.attribute(\"type\",\"_server\");\n";
- code+="\t\tm_errstr=terr;\n\t\tlog.setError(m_errstr);\n\t\treturn;\n\t}\n";
- code+="\tQList<QDomElement> nl;\n";
- //parse parameters
- for(int i=0;i<sl.size();i++){
- QString t=trn.outputType(sl[i]);
- if(trn.isAttributeType(t)){
- code+="\tout_"+sl[i]+"=root.attribute(\""+sl[i]+"\")";
- if(trn.isIntType(t))code+=".toInt()";else
- if(trn.isBoolType(t))code+="==\"yes\"";
- code+=";\n";
- }else{
- code+="\tnl=elementsByTagName(root,\""+sl[i]+"\");\n";
- if(trn.isListType(t)){
- code+="\tfor(int i=0;i<nl.size();i++){\n";
- if(trn.isObjectType(t)){
- code+="\t\ttry{out_"+sl[i]+".append("+qtobjtype(trn,sl[i],Out)+"(nl.at(i).toElement()));}catch(WException e){m_stage=Error;m_errtype=e.component();m_errstr=e.error();log.setError(m_errstr);}\n";
- }else if(trn.isIntType(t)){
- code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text().toInt());\n";
- }else if(trn.isBoolType(t)){
- code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text()==\"yes\");\n";
- }else if(trn.isBlobType(t)){
- code+="\t\tout_"+sl[i]+".append(QByteArray::fromBase64(nl.at(i).toElement().text().toAscii()));\n";
- }else{//can only be string
- code+="\t\tout_"+sl[i]+".append(nl.at(i).toElement().text());\n";
- }
- code+="\t}\n";
- }else{
- code+="\tif(nl.size()>0){\n";
- if(trn.isObjectType(t)){
- code+="\t\ttry{out_"+sl[i]+"="+qtobjtype(trn,sl[i],Out)+"(nl.at(0).toElement());}catch(WException e){m_stage=Error;m_errtype=e.component();m_errstr=e.error();log.setError(m_errstr);}\n";
- }else if(trn.isBlobType(t)){
- code+="\t\tout_"+sl[i]+"=QByteArray::fromBase64(nl.at(0).toElement().text().toAscii());\n";
- }else{//can only be string
- code+="\t\tout_"+sl[i]+"=nl.at(0).toElement().text();\n";
- }
- code+="\t}\n";
- }
- }
- }
- code+="\t/*end of output*/\n";
- return code;
-}
-
-void WocQtClientOut::trnList()
-{
- QString code;
- //header
- code+=" enum Right {\n NoRight";
- QStringList r=WocProcessor::instance()->transactionNames();
- QStringList p=WocProcessor::instance()->privilegeNames();
- QStringList pp=p;
- for(int i=0;i<r.size();i++)
- code+=",\n R"+r[i];
- for(int i=0;i<p.size();i++)
- code+=",\n P"+pp[i].replace(':',"_");
- code+="\n };\n";
- code+=" static QString rightToString(Right);\n";
- code+=" static QString rightToLocalString(Right);\n";
- code+=" static Right stringToRight(QString);\n";
- code+=" static QStringList allKnownRightsString();\n";
- code+=" static QList<Right> allKnownRights();\n";
- m_iface.write(code.toAscii());
-
- code="QString "+m_prefix+"Interface::rightToString(Right r)\n{\n\tswitch(r){\n";
- for(int i=0;i<r.size();i++)
- code+="\t\tcase R"+r[i]+":return \""+r[i]+"\";\n";
- for(int i=0;i<p.size();i++)
- code+="\t\tcase P"+pp[i]+":return \""+p[i]+"\";\n";
- code+="\t\tdefault:return \"\";\n\t}\n}\n";
- code+="QString "+m_prefix+"Interface::rightToLocalString(Right r)\n{\n\tswitch(r){\n";
- for(int i=0;i<r.size();i++)
- code+="\t\tcase R"+r[i]+":return tr(\""+r[i]+"\");\n";
- for(int i=0;i<p.size();i++)
- code+="\t\tcase P"+pp[i]+":return tr(\""+p[i]+"\");\n";
- code+="\t\tdefault:return \"\";\n\t}\n}\n";
- code+=m_prefix+"Interface::Right "+m_prefix+"Interface::stringToRight(QString s)\n{\n";
- for(int i=0;i<r.size();i++)
- code+="\tif(s==\""+r[i]+"\")return R"+r[i]+";else\n";
- for(int i=0;i<p.size();i++)
- code+="\tif(s==\""+p[i]+"\")return P"+pp[i]+";else\n";
- code+="\treturn NoRight;\n}\n";
- code+="QList<"+m_prefix+"Interface::Right> "+m_prefix+"Interface::allKnownRights()\n{\n";
- code+="\tQList<Right> ret;ret";
- for(int i=0;i<r.size();i++)
- code+="<<R"+r[i];
- for(int i=0;i<p.size();i++)
- code+="<<P"+pp[i];
- code+=";\n\treturn ret;\n}\n";
- code+="QStringList "+m_prefix+"Interface::allKnownRightsString()\n{\n";
- code+="\tQStringList ret;ret";
- for(int i=0;i<r.size();i++)
- code+="<<\""+r[i]+"\"";
- for(int i=0;i<p.size();i++)
- code+="<<\""+p[i]+"\"";
- code+=";\n\treturn ret;\n}\n";
- m_ifacecpp.write(code.toAscii());
-}
-
-QString WocQtClientOut::qttype(const WocTransaction&trn,QString v,InOut io)
+QString WocQtOut::qttype(const WocTransaction&trn,QString v,InOut io)
{
QString tp=io==In?trn.inputType(v):trn.outputType(v);
QString r,e;
if(tp.startsWith("List:")){
- r="QList<";e=">";
- tp=tp.mid(5);
+ r="QList<";e=">";
+ tp=tp.mid(5);
}else
- if(io==Out){
- r="Nullable<";
- e=">";
- }
+ if(io==Out){
+ r="Nullable<";
+ e=">";
+ }
if(tp=="astring" || tp=="string")r+="QString";else
if(tp=="int"||tp=="int32"||tp=="int64")r+="qint64";else
if(tp=="blob")r+="QByteArray";else
if(tp=="bool")r+="bool";else
if(tp==""){
- qDebug("Warning: the final type of property %s is empty!",v.toAscii().data());
- r+="void";
+ qDebug("Warning: the final type of property %s is empty!",v.toAscii().data());
+ r+="void";
}else r+=m_prefix+"O"+tp.split("/",QString::SkipEmptyParts).at(0);
r+=e;r+=" ";
return r;
}
-QString WocQtClientOut::qtobjtype(const WocTransaction&trn,QString v,InOut io)
+QString WocQtOut::qtobjtype(const WocTransaction&trn,QString v,InOut io)
{
QString tp=io==In?trn.inputType(v):trn.outputType(v);
if(tp.startsWith("List:"))
- tp=tp.mid(5);
+ tp=tp.mid(5);
if(tp=="astring" || tp=="string" || tp=="int" || tp=="int32" || tp=="int64" || tp=="bool" || tp=="blob")
- return "";
+ return "";
else
- return m_prefix+"O"+tp;
+ return m_prefix+"O"+tp;
}
-void WocQtClientOut::addFile(QString bn)
+WocQtClientOut::WocQtClientOut(QDomElement&el)
+ :WocQtOut(el)
{
- QString code="HEADERS+="+m_subdir+"/"+bn+".h\nSOURCES+="+m_subdir+"/"+bn+".cpp\n";
- m_pri.write(code.toAscii());
- m_hdr.write(QByteArray("#include \"%.h\"\n").replace('%',bn.toAscii()));
-}
\ No newline at end of file
+ qclass=new WocQtClass(this);
+ qtrans=new WocQtClientTransaction(this);
+}
+
+WocQtTransaction::WocQtTransaction(WocQtOut*p)
+ :m_parent(p)
+{
+ connect(this,SIGNAL(errorFound()),p,SIGNAL(errorFound()));
+}
class QDomElement;
-class WocQtClientOut:public WocOutput
+class WocQtOut;
+
+class WocQtTransaction:public QObject
{
+ Q_OBJECT
public:
- WocQtClientOut(QDomElement&);
- ~WocQtClientOut();
+ WocQtTransaction(WocQtOut*);
+ virtual void newTransaction(const WocTransaction&)=0;
+ virtual void finalize()=0;
+ signals:
+ void errorFound();
+ protected:
+ WocQtOut*m_parent;
+};
+
+class WocQtClass;
+class WocQtTable;
+
+class WocQtOut:public WocOutput
+{
+ public:
+ WocQtOut(QDomElement&);
+ ~WocQtOut();
protected:
virtual void finalize();
virtual void newClass(const WocClass&);
virtual void newTable(const WocTable&);
virtual void newTransaction(const WocTransaction&);
- private:
+
+ friend class WocQtClass;
+ friend class WocQtClientTransaction;
+ friend class WocQtServerTransaction;
+ friend class WocQtTransaction;
+ friend class WocQtTable;
+
QString m_basedir,m_subdir,m_prefix,m_transbase;
MFile m_pri,m_iface,m_ifacecpp,m_hdr;
bool m_clean;
- /**helper: adds a file to the project file*/
- void addFile(QString basename);
- /**helper: generate enums for classes*/
- void classEnums(const WocClass&,MFile&,MFile&,QString);
- /**helper: generate properties*/
- void classProperties(const WocClass&,MFile&,MFile&);
- /**helper: generate constructors/deserializer/copiers*/
- void classDeserializer(const WocClass&,MFile&,MFile&,QString);
- /**helper: generate serializers*/
- void classSerializers(const WocClass&,MFile&,MFile&,QString);
/**helper: generate a proper Qt type for a property*/
QString qttype(const WocClass&,QString,bool dolist=true);
-
enum InOut{In,Out};
/**helper: generate a proper QT type for a transaction variable*/
QString qttype(const WocTransaction&,QString,InOut);
/**helper: generate a proper QT type for a transaction variable, WO* only */
QString qtobjtype(const WocTransaction&,QString,InOut);
+ /**helper: adds a file to the project file*/
+ void addFile(QString basename);
- /**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();
+ WocQtClass*qclass;
+ WocQtTable*qtable;
+ WocQtTransaction*qtrans;
+};
+
+class WocQtClientOut:public WocQtOut
+{
+ public:
+ WocQtClientOut(QDomElement&);
};
#endif
--- /dev/null
+//
+// C++ Implementation: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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&){}
--- /dev/null
+//
+// C++ Interface: qtout
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (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
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