refactored woc to prepare for new targets
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 26 Jul 2010 20:54:38 +0000 (20:54 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 26 Jul 2010 20:54:38 +0000 (20:54 +0000)
git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@573 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

31 files changed:
woc/phpclass.cpp [new file with mode: 0644]
woc/phpclass.h [new file with mode: 0644]
woc/phpconst.h [new file with mode: 0644]
woc/phpctrans.cpp [new file with mode: 0644]
woc/phpctrans.h [new file with mode: 0644]
woc/phpdb.cpp [new file with mode: 0644]
woc/phpdb.h [new file with mode: 0644]
woc/phpout.cpp
woc/phpout.h
woc/phpstrans.cpp [new file with mode: 0644]
woc/phpstrans.h [new file with mode: 0644]
woc/procclass.cpp [new file with mode: 0644]
woc/procclass.h [new file with mode: 0644]
woc/processor.cpp
woc/processor.h
woc/proctable.cpp [new file with mode: 0644]
woc/proctable.h [new file with mode: 0644]
woc/proctrans.cpp [new file with mode: 0644]
woc/proctrans.h [new file with mode: 0644]
woc/qtclass.cpp [new file with mode: 0644]
woc/qtclass.h [new file with mode: 0644]
woc/qtconst.h [new file with mode: 0644]
woc/qtctrans.cpp [new file with mode: 0644]
woc/qtctrans.h [new file with mode: 0644]
woc/qtdb.cpp [new file with mode: 0644]
woc/qtdb.h [new file with mode: 0644]
woc/qtout.cpp
woc/qtout.h
woc/qtstrans.cpp [new file with mode: 0644]
woc/qtstrans.h [new file with mode: 0644]
woc/woc.pro

diff --git a/woc/phpclass.cpp b/woc/phpclass.cpp
new file mode 100644 (file)
index 0000000..1019988
--- /dev/null
@@ -0,0 +1,531 @@
+//
+// 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";
+}
diff --git a/woc/phpclass.h b/woc/phpclass.h
new file mode 100644 (file)
index 0000000..fc67a26
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// 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
diff --git a/woc/phpconst.h b/woc/phpconst.h
new file mode 100644 (file)
index 0000000..718dac7
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// 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
diff --git a/woc/phpctrans.cpp b/woc/phpctrans.cpp
new file mode 100644 (file)
index 0000000..3719a5e
--- /dev/null
@@ -0,0 +1,419 @@
+//
+// 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;
+}
diff --git a/woc/phpctrans.h b/woc/phpctrans.h
new file mode 100644 (file)
index 0000000..546144e
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// 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
diff --git a/woc/phpdb.cpp b/woc/phpdb.cpp
new file mode 100644 (file)
index 0000000..e99e938
--- /dev/null
@@ -0,0 +1,221 @@
+//
+// 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());
+}
diff --git a/woc/phpdb.h b/woc/phpdb.h
new file mode 100644 (file)
index 0000000..5c9193d
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// 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
index 211bc0a..c204e26 100644 (file)
 //
 
 #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");
@@ -50,1094 +59,45 @@ WocPHPServerOut::WocPHPServerOut(const QDomElement&el)
        }
        m_loader.write(PHPSTART);
        m_loader.write(QString("$d=dirname(__FILE__);\n").toAscii());
-       //create schema file
-       m_schema.setFileName(m_basedir+"/"+m_subdir+"/schema"+m_fileext);
-       if(!m_schema.open(QIODevice::ReadWrite|QIODevice::Truncate)){
-               qDebug("Error: PHP Server Generator - cannot create DB schema file.");
-               emit errorFound();
-               return;
-       }
-       m_schema.write(PHPSTART);
-       m_schema.write(SCHEMASTART);
-       m_schema.write(("\tself::$sversion=\""+WocProcessor::instance()->dbVersion()+"\";\n").toAscii());
-       addLoad("WobSchema","schema");
-       //create Transaction file
-       m_transact.setFileName(m_basedir+"/"+m_subdir+"/transaction"+m_fileext);
-       if(!m_transact.open(QIODevice::ReadWrite|QIODevice::Truncate)){
-               qDebug("Error: PHP Server Generator - cannot create transaction processor file.");
-               emit errorFound();
-               return;
-       }
-       m_transact.write(PHPSTART);
-       m_transact.write(TRANSACTCLASS);
-       transInfo();
-       m_transact.write(TRANSACTSTART);
-       addLoad("WobTransaction","transaction");
 }
 
-void WocPHPServerOut::transInfo()
-{
-       WocProcessor*woc=WocProcessor::instance();
-       m_transact.write(QString("  static public function commVersion(){return \""+woc->verComm()+"\";}\n").toAscii());
-       m_transact.write(QString("  static public function needCommVersion(){return \""+woc->verNeedComm()+"\";}\n").toAscii());
-       m_transact.write(QString("  static public function version(){return \""+woc->verHR()+"\";}\n").toAscii());
-       m_transact.write(QString("  static public function svnVersion(){return \""+woc->svnRevision()+"\";}\n\n").toAscii());
-       m_transact.write(QString("  static public function svnRepositoryRoot(){return \""+woc->svnRepositoryRoot()+"\";}\n\n").toAscii());
-       m_transact.write(QString("  static public function svnRepositoryUrl(){return \""+woc->svnRepositoryUrl()+"\";}\n\n").toAscii());
-}
 
-void WocPHPServerOut::transInfo2()
-{
-       WocProcessor*woc=WocProcessor::instance();
-       //transaction names
-       QString code="  static public function transactionNames(){\n\treturn array(";
-       QStringList tns=woc->transactionNames();
-       for(int i=0;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;
-}
index 3c2d9f0..21febb0 100644 (file)
 
 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();
@@ -34,7 +53,13 @@ class WocPHPServerOut:public WocOutput
                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;
@@ -42,50 +67,9 @@ class WocPHPServerOut:public WocOutput
                /**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();}
@@ -96,4 +80,11 @@ class WocPHPServerOut:public WocOutput
                QString trnClassName(const WocTransaction&t){return "WTr"+t.name();}
 };
 
+class WocPHPServerOut:public WocPHPOut
+{
+       public:
+               /**initializes the output object*/
+               WocPHPServerOut(const QDomElement&);
+};
+
 #endif
diff --git a/woc/phpstrans.cpp b/woc/phpstrans.cpp
new file mode 100644 (file)
index 0000000..eafbefe
--- /dev/null
@@ -0,0 +1,419 @@
+//
+// 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;
+}
diff --git a/woc/phpstrans.h b/woc/phpstrans.h
new file mode 100644 (file)
index 0000000..f8816ca
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// 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
diff --git a/woc/procclass.cpp b/woc/procclass.cpp
new file mode 100644 (file)
index 0000000..2170fb3
--- /dev/null
@@ -0,0 +1,324 @@
+//
+// 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 "";
+}
diff --git a/woc/procclass.h b/woc/procclass.h
new file mode 100644 (file)
index 0000000..3bad610
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// 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
index e8184be..bb224c1 100644 (file)
@@ -344,887 +344,3 @@ WocOutput::WocOutput()
 }
 
 WocOutput::~WocOutput(){}
-
-/******************************************************************************
- * WocClass
- ******************************************************************************/
-
-WocClass::WocClass(const QDomElement&cls)
-{
-       //scan basics
-       m_valid=true;
-       m_abstract=str2bool(cls.attribute("abstract","0"));
-       WocProcessor *woc=WocProcessor::instance();
-       QRegExp symok("[a-z_][a-z0-9_]*",Qt::CaseInsensitive);
-       m_name=cls.attribute("name");
-       if(m_name==""){
-               qDebug("Error: unnamed class at line %i column %i.",cls.lineNumber(),cls.columnNumber());
-               m_valid=false;
-               return;
-       }
-       if(woc->hasClass(m_name)){
-               qDebug("Error: double definition of class %s at line %i column %i.",m_name.toAscii().data(),cls.lineNumber(),cls.columnNumber());
-               m_valid=false;
-               return;
-       }
-       if(!symok.exactMatch(m_name)){
-               qDebug("Error: Illegal class name %s.",m_name.toAscii().data());
-               m_valid=false;
-               return;
-       }
-       qDebug("Info: parsing class %s",m_name.toAscii().data());
-       m_sbase=cls.attribute("serverbase","WObject");
-       m_cbase=cls.attribute("clientbase","WObject");
-       //scan properties
-       QList<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 "";
-}
index 2626c08..11ff06b 100644 (file)
@@ -33,326 +33,10 @@ inline bool str2bool(QString s)
        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
diff --git a/woc/proctable.cpp b/woc/proctable.cpp
new file mode 100644 (file)
index 0000000..8122163
--- /dev/null
@@ -0,0 +1,444 @@
+//
+// 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;
+}
diff --git a/woc/proctable.h b/woc/proctable.h
new file mode 100644 (file)
index 0000000..8a98a7e
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// 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
diff --git a/woc/proctrans.cpp b/woc/proctrans.cpp
new file mode 100644 (file)
index 0000000..99ef997
--- /dev/null
@@ -0,0 +1,187 @@
+//
+// 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 "";
+}
diff --git a/woc/proctrans.h b/woc/proctrans.h
new file mode 100644 (file)
index 0000000..219e6df
--- /dev/null
@@ -0,0 +1,123 @@
+//
+// 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
diff --git a/woc/qtclass.cpp b/woc/qtclass.cpp
new file mode 100644 (file)
index 0000000..8aff833
--- /dev/null
@@ -0,0 +1,374 @@
+//
+// 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());
+}
diff --git a/woc/qtclass.h b/woc/qtclass.h
new file mode 100644 (file)
index 0000000..4b64942
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// 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
diff --git a/woc/qtconst.h b/woc/qtconst.h
new file mode 100644 (file)
index 0000000..214b216
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// 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
diff --git a/woc/qtctrans.cpp b/woc/qtctrans.cpp
new file mode 100644 (file)
index 0000000..e38b36e
--- /dev/null
@@ -0,0 +1,330 @@
+//
+// 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());
+}
diff --git a/woc/qtctrans.h b/woc/qtctrans.h
new file mode 100644 (file)
index 0000000..7340b49
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// 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
diff --git a/woc/qtdb.cpp b/woc/qtdb.cpp
new file mode 100644 (file)
index 0000000..217945a
--- /dev/null
@@ -0,0 +1,19 @@
+//
+// 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&){}
diff --git a/woc/qtdb.h b/woc/qtdb.h
new file mode 100644 (file)
index 0000000..15c1768
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// 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
index b483d75..b4bf783 100644 (file)
 //
 
 #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");
@@ -96,11 +86,14 @@ WocQtClientOut::WocQtClientOut(QDomElement&el)
        addFile(m_prefix.toAscii()+"Interface");
 }
 
-WocQtClientOut::~WocQtClientOut(){}
+WocQtOut::~WocQtOut(){}
 
-void WocQtClientOut::finalize()
+void WocQtOut::finalize()
 {
-       trnList();
+       if(qclass)qclass->finalize();
+       if(qtable)qtable->finalize();
+       if(qtrans)qtrans->finalize();
+       //finish sources
        m_ifacecpp.write(SRCEND);
        m_ifacecpp.close();
        m_iface.write(QByteArray("};\n")+HDREND);
@@ -121,139 +114,29 @@ void WocQtClientOut::finalize()
        }
 }
 
-void WocQtClientOut::newTable(const WocTable&){/*not needed, Qt client is a few levels higher*/}
-
-void WocQtClientOut::newClass(const WocClass&cls)
+void WocQtOut::newTable(const WocTable&tbl)
 {
-       QString cn=m_prefix+"O"+cls.name();
-       QString cna=cn;
-       if(cls.isAbstract("qt"))cna+="Abstract";
-       addFile(cna);
-       MFile hdr(m_basedir+"/"+m_subdir+"/"+cna+".h");
-       MFile src(m_basedir+"/"+m_subdir+"/"+cna+".cpp");
-       if(!hdr.open(QIODevice::WriteOnly|QIODevice::Truncate) ||
-          !src.open(QIODevice::WriteOnly|QIODevice::Truncate)){
-               qDebug("Error: cannot create class files for class %s.",cn.toAscii().data());
-               emit errorFound();
-               return;
-       }
-       //lead in
-       hdr.write(QByteArray(HDRSTART).replace("%",cna.toAscii()));
-       src.write(QByteArray(SRCSTART).replace("%",cna.toAscii()));
-       
-       QString hcd;
-       QString scd;
-       //includes
-       hcd="#include \""+cls.clientBaseClass()+".h\"\n#include <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<";
@@ -268,555 +151,50 @@ QString WocQtClientOut::qttype(const WocClass&cls,QString p,bool dolist)
        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()));
+}
index 060a000..18f6cb5 100644 (file)
 
 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
diff --git a/woc/qtstrans.cpp b/woc/qtstrans.cpp
new file mode 100644 (file)
index 0000000..8151e3d
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// 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&){}
diff --git a/woc/qtstrans.h b/woc/qtstrans.h
new file mode 100644 (file)
index 0000000..5bfd58d
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// 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
index 0d0a4ad..4877b2c 100644 (file)
@@ -13,16 +13,38 @@ RCC_DIR = .ctmp
 
 SOURCES+= \
        processor.cpp \
+       procclass.cpp \
+       proctrans.cpp \
+       proctable.cpp \
        woc.cpp \
        qtout.cpp \
+       qtclass.cpp \
+       qtdb.cpp \
+       qtctrans.cpp \
+       qtstrans.cpp \
        phpout.cpp \
+       phpclass.cpp \
+       phpctrans.cpp \
+       phpstrans.cpp \
+       phpdb.cpp \
        htmlout.cpp \
        mfile.cpp \
        domquery.cpp
 HEADERS+= \
        processor.h \
+       procclass.h \
+       proctrans.h \
+       proctable.h \
        phpout.h \
+       phpdb.h \
+       phpclass.h \
+       phpctrans.h \
+       phpstrans.h \
        qtout.h \
+       qtclass.h \
+       qtdb.h \
+       qtctrans.h \
+       qtstrans.cpp \
        htmlout.h \
        mfile.h \
        domquery.h