}
//implement properties
+ k=cls.propertyNames();
+ for(int i=0;i<k.size();i++){
+ code+="\nprotected $prop_"+k[i]+";\n";
+ //generate validator
+ code+="static public function validate"+k[i]+"($value){\n";
+ if(cls.propertyIsEnum(k[i])){
+ QList<QPair<QString,int> >ev=cls.enumValues(cls.propertyPlainType(k[i]));
+ 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].second)+")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].first+"\")return true;\n";
+ }
+ code+="\t\treturn false;\n\t}\n";
+ }else
+ if(cls.propertyIsInt(k[i]))
+ code+="\treturn is_numeric($value);\n";
+ else
+ if(cls.propertyIsString(k[i]))
+ code+="\treturn true;\n";//TODO: special handling for astring
+ else
+ if(cls.propertyIsObject(k[i]))
+ code+="\treturn is_a($value,\"WO"+cls.propertyPlainType(k[i])+"\");\n";
+ else{
+ qDebug("Warning: unable to generate validator for class %s property %s: unknown type.",cls.name().toAscii().data(),k[i].toAscii().data());
+ code+="\treturn false;\n";
+ }
+ code+="}\n";
+ //generic getter
+ code+="public function get_"+k[i]+"(){return $this->prop_"+k[i]+";}\n";
+ if(cls.propertyIsList(k[i])){
+ //lists...
+ //getters
+ if(cls.propertyIsString(k[i]))code+="public function getstrlist_"+k[i]+"(){return $this->prop_"+k[i]+";}\n";
+ else
+ if(cls.propertyIsInt(k[i])){
+ code+="public function getstrlist_"+k[i]+"(){\n";
+ code+="\t$ret=array();\n\tforeach($this->prop_"+k[i]+" as $p)$ret[]=\"\".$p;\n";
+ code+="\treturn $ret;\n}\n";
+ }else
+ if(cls.propertyIsEnum(k[i])){
+ code+="public function getstrlist_"+k[i]+"(){\n";
+ code+="\t$ret=array();\n";
+ code+="\tforeach($this->prop_"+k[i]+" as $p)switch($p){\n";
+ QList<QPair<QString,int> > ev=cls.enumValues(cls.propertyPlainType(k[i]));
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tcase "+QString::number(ev[j].second)+":$ret[]=\""+ev[j].first+"\";break;\n";
+ }
+ code+="\t\tdefault:$ret[]=null;break;\n\t}\n\treturn $ret;\n}\n";
+ }
+ //setters
+ code+="public function clear_"+k[i]+"(){$this->prop_"+k[i]+"=array();}\n";
+ QString acode;//body of add_ function, see below
+ code+="public function set_"+k[i]+"(array $values){\n";
+ if(cls.propertyIsEnum(k[i])){
+ QList<QPair<QString,int> >ev=cls.enumValues(cls.propertyPlainType(k[i]));
+ 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].second)+"){\n";
+ code+="\t\t\t\t$prop[]="+QString::number(ev[j].second)+";\n";
+ code+="\t\t\t}else\n";
+ acode+="\t\tif($value=="+QString::number(ev[j].second)+"){\n";
+ acode+="\t\t\t$this->prop_"+k[i]+"[]="+QString::number(ev[j].second)+";\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].first+"\"){\n";
+ code+="\t\t\t\t$prop[]="+QString::number(ev[j].second)+";\n";
+ code+="\n\t\t\t}else\n";
+ acode+="\t\tif($value==\""+ev[j].first+"\"){\n";
+ acode+="\t\t\t$this->prop_"+k[i]+"[]="+QString::number(ev[j].second)+";\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_"+k[i]+"=$prop;\n";
+ code+="\treturn true;\n";
+ acode+="\t\treturn false;\n\t}\n";
+ }else
+ if(cls.propertyIsInt(k[i])){
+ 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_"+k[i]+"=$prop;\n\treturn true;\n";
+ acode+="\tif(is_numeric($value)){\n";
+ acode+="\t\t$this->prop_"+k[i]+"=0+$value;\n\t\treturn true;\n\t}else return false;\n";
+ }else
+ if(cls.propertyIsString(k[i])){
+ code+="\t$prop=array();\n\tforeach($values as $value)$prop[]=\"\".$value;\n";
+ code+="\t$this->prop_"+k[i]+"=$prop;\n\treturn true;\n";
+ //TODO: special handling for astring
+ acode+="\t$this->prop_"+k[i]+"[]=\"\".$value;\n\treturn true;\n";
+ }else
+ if(cls.propertyIsObject(k[i])){
+ code+="\t$prop=array();\n\tforeach($values as $value)\n";
+ code+="\t\tif(is_a($value,\"WO"+cls.propertyPlainType(k[i])+"\"))\n";
+ code+="\t\t\t$prop[]=$value;\n";
+ code+="\t\telse return false;\n";
+ code+="\t$this->prop_"+k[i]+"=$prop;\n";
+ code+="\treturn true;\n";
+ acode+="\tif(is_a($value,\"WO"+cls.propertyPlainType(k[i])+"\")){\n";
+ acode+="\t\t$this->prop_"+k[i]+"[]=$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(),k[i].toAscii().data());
+ code+="\treturn false;\n";
+ }
+ code+="}\n";
+ code+="public function add_"+k[i]+"($value){\n"+acode+"}\n";
+ }else{
+ //non-lists...
+ //getters
+ if(cls.propertyIsString(k[i]))code+="public function getstr_"+k[i]+"(){return $this->prop_"+k[i]+";}\n";
+ else
+ if(cls.propertyIsInt(k[i]))code+="public function getstr_"+k[i]+"(){return \"\".$this->prop_"+k[i]+";}\n";
+ else
+ if(cls.propertyIsEnum(k[i])){
+ code+="public function getstr_"+k[i]+"(){\n\tswitch($this->prop_"+k[i]+"){\n";
+ QList<QPair<QString,int> > ev=cls.enumValues(cls.propertyPlainType(k[i]));
+ for(int j=0;j<ev.size();j++){
+ code+="\t\tcase "+QString::number(ev[j].second)+":return \""+ev[j].first+"\";\n";
+ }
+ code+="\t\tdefault:return null;\n\t}\n}\n";
+ }
+ //setter
+ code+="public function set_"+k[i]+"($value){\n";
+ if(cls.propertyIsEnum(k[i])){
+ QList<QPair<QString,int> >ev=cls.enumValues(cls.propertyPlainType(k[i]));
+ 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].second)+"){\n";
+ code+="\t\t\t$this->prop_"+k[i]+"="+QString::number(ev[j].second)+";\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].first+"\"){\n";
+ code+="\t\t\t$this->prop_"+k[i]+"="+QString::number(ev[j].second)+";\n";
+ code+="\t\t\treturn true;\n\t\t}\n";
+ }
+ code+="\t\treturn false;\n\t}\n";
+ }else
+ if(cls.propertyIsInt(k[i]))
+ code+="\tif(is_numeric($value)){\n\t\t$this->prop_"+k[i]+"=0+$value;\n\t\treturn true;\n\t}else return false;\n";
+ else
+ if(cls.propertyIsString(k[i]))
+ code+="\t$this->prop_"+k[i]+"=\"\".$value;\n\treturn true;\n";
+ //TODO: special handling for astring
+ else
+ if(cls.propertyIsObject(k[i])){
+ code+="\tif(is_a($value,\"WO"+cls.propertyPlainType(k[i])+"\")){\n";
+ code+="\t\t$this->prop_"+k[i]+"=$value;\n";
+ code+="\t\treturn true;\n";
+ }else{
+ qDebug("Warning: unable to generate setter for class %s property %s: unknown type.",cls.name().toAscii().data(),k[i].toAscii().data());
+ code+="\treturn false;\n";
+ }
+ code+="}\n";
+ }
+ }
- //implement mappings
+ //TODO: implement mappings
//implement serializers
k=cls.serializers();
for(int i=0;i<k.size();i++){
//toString function (wraps toXml)
- code+="\nfunction toString"+k[i]+"(){\n\t$xml=new DomDocument;\n";
+ code+="\npublic function toString"+k[i]+"(){\n\t$xml=new DomDocument;\n";
code+="\t$xml->appendChild($this->toXml"+k[i]+"($xml));\n\treturn $xml->saveXml();\n}\n";
//toXml function:
- code+="function toXml"+k[i]+"($xml){\n";
- code+="\t$root=$xml->createElement(\""+cls.name()+k[i]+"\");\n";
+ code+="public function toXml"+k[i]+"($xml){\n";
+ code+="\t$root=$xml->createElement(\""+cls.name()+"\");\n";
+ code+="\t$root->setAttribute(\"serialization-mode\",\""+k[i]+"\");\n";
//add properties
QStringList p=cls.serializerProperties(k[i]);
for(int j=0;j<p.size();j++)
}
//implement de-serializer
- code+="\nstatic function fromString($txt){\n\t$xml=new DomDocument;\n";
+ code+="\nstatic public function fromString($txt){\n\t$xml=new DomDocument;\n";
code+="\tif(!$xml->loadXml(trim($txt)))";
code+="\n\t\tthrow WobXmlException(\"Unable to deserialize object of type "+cn+".\");";
code+="\n\treturn self::fromXml($xml,$xml->documentElement);\n}\n";
- code+="static function fromXml($xml,$elem){\n\t$data=array();\n";
+ code+="static public function fromXml($xml,$elem){\n\t$data=array();\n";
k=cls.propertyNames();
for(int i=0;i<k.size();i++){
//TODO: scan properties
tf.close();
}
-QString WocPHPServerOut::propertyToXml(const WocClass&,QString){return "";}
+QString WocPHPServerOut::propertyToXml(const WocClass&cls,QString pt)
+{
+ QStringList sl=pt.split("/",QString::SkipEmptyParts);
+ if(sl.size()<1)return "";
+ QString prop=sl[0].trimmed();
+ QString var;
+ if(sl.size()>1)var=sl[1].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"+var+"($xml));\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;
+ }
+ }
+ //is it an attribute?
+ if(cls.propertyIsAttribute(prop))
+ return "\t$root->setAttribute(\""+prop+"\",$this->getstr_"+prop+"());\n";
+ //is it an element?
+ if(cls.propertyIsElement(prop))
+ return "\t$root->appendChild($xml->createElement(\""+prop+"\",xq($this->getstr_"+prop+"())));\n";
+ //is it a class?
+ if(cls.propertyIsObject(prop))
+ return "\t$root->appendChild($this->get_"+prop+"()->toXml"+var+"($xml));\n";
+ //anything else?
+ qDebug("Warning: end of WocPHPServerOut::propertyToXml - this code should not be reachable.");
+ return "//internal generator error!\n";
+}
void WocPHPServerOut::newTransaction(const WocTransaction&)
{
class QDomElement;
+/**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)*/
QString baseClass()const{return m_base;}
+ /**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{return propertyPlainType(p)=="int";}
+ /**returns whether the property type is string*/
+ bool propertyIsString(QString p)const{QString pt=propertyPlainType(p);return pt=="string"||pt=="astring";}
+
+ /**returns whether the class is abstract (needs to be customized); it is automatically abstract if any property is abstract*/
bool isAbstract()const;
+ /**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<QPair<QString,int> > enumValues(QString t)const{return m_enumvals[t];}
+ /**returns the names of all serializer methods of this class*/
QStringList serializers()const{return m_serial.keys();}
+ /**returns true if the given serializer is defined*/
bool hasSerializer(QString s)const{return m_serial.contains(s);}
+ /**returns which properties are encoded by this serializer*/
QStringList serializerProperties(QString s)const{return m_serial[s];}
+ /**returns true if the given mapping exists*/
bool hasMapping(QString m)const{return m_maps.contains(m);}
private:
+ //valid: parsing the WOLF succeeded
+ //abstract: the class is declared abstract (isAbstract may return true even if this is false)
bool m_valid,m_abstract;
+ //name: class name
+ //base: name of parent class
QString m_name,m_base;
+ //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")
QMap<QString,QList<QPair<QString,QString> > >m_maps;
+ //enum types: "type-name" => List of ("constant-name",int-constant-value)
QMap<QString,QList<QPair<QString,int> > >m_enumvals;
+ //serializers: "name" => List of properties (syntax Objects: "propertyname/Serializer"
QMap<QString,QStringList> m_serial;
+
+ //helper: contains predefined types sorted by serialization type
+ static const QStringList attrtypes,elemtypes;
};
class WocTable