/*************************************************************************** * Copyright (C) 2004 - 2005 by Raphael Langerhorst * * raphael-langerhorst@gmx.at * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to * * the following conditions: * * * * The above copyright notice and this permission notice shall be * * included in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.* * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * ***************************************************************************/ #include "GCoreXmlSerializer.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace GCS; using namespace GBE; namespace GWE { GCoreXmlSerializer::GCoreXmlSerializer(const GCS::GWorldData* world_data, QObject *parent, const char *name) : QObject(parent,name), WorldData(world_data) { } /*! \fn GWE::GCoreXmlSerializer::~GCoreXmlSerializer() */ GCoreXmlSerializer::~GCoreXmlSerializer() { } /*! \fn GWE::GCoreXmlSerializer::createAgent(QDomElement data) */ GCS::GAgent* GCoreXmlSerializer::createAgent(QDomElement data) { //@todo for 0.6 release: temporary function till we get an agent factory to create the appropriate subagent QString name = data.namedItem("name").toElement().text(); if (name.isEmpty()) { qWarning("Agent name is empty!"); } /* GAttractAgent GDynamicGeneratorAgent GMoveAgent GRadiatingAgent */ if (name == "GBE::GAttractAgent") { return new GAttractAgent(); } else if (name == "GBE::GDynamicGeneratorAgent") { return new GDynamicGeneratorAgent(); } else if (name == "GBE::GEnergyFormAgent") { return new GEnergyFormAgent(); } else if (name == "GBE::GMoveAgent") { return new GMoveAgent(); } else if (name == "GBE::GRadiatingAgent") { return new GRadiatingAgent(); } else { qWarning(QString("Couldn't determine appropriate agent for given agent name: %1").arg(name)); return NULL; } } /*! \fn GWE::GCoreXmlSerializer::createAgent(QDomElement data) */ QPtrList* GCoreXmlSerializer::createAgents(QDomElement data) { if (data.isNull()) return NULL; QPtrList* agents = new QPtrList; QDomNode agentNode = data.firstChild(); while( !agentNode.isNull() ) { if(agentNode.isElement()) { agents->append(createAgent(agentNode.toElement())); } agentNode = agentNode.nextSibling(); } return agents; } /*! \fn GWE::GCoreXmlSerializer::createElementData(QDomElement data) */ QDomDocument* GCoreXmlSerializer::createElementData(QDomElement data) { if (data.isNull()) { qWarning("Element Data to deserialize is NULL! Returning NULL."); return NULL; } // else // { // qDebug("deserializing element data:"); // qDebug(data.ownerDocument().toString()); // } QDomDocument* NewDocument = new QDomDocument(); QDomNode child = data.firstChild(); while (!child.isNull()) { if (child.isElement()) NewDocument->appendChild(NewDocument->importNode(child,true)); child = child.nextSibling(); } // if (!NewDocument->isNull()) // { // qDebug("deserialized element data:"); // qDebug(NewDocument->toString()); // } return NewDocument; // @todo remove, GElementData is now a QDomDocument // GCS::GElementData* elementData = new GCS::GElementData(); // elementData->setDomDocument(*NewDocument); // return elementData; } /*! \fn GWE::GCoreXmlSerializer::createElement(QDomElement data) */ GCS::GElement* GCoreXmlSerializer::createElement(QDomElement data) { if (data.isNull()) return NULL; QPtrList* Agents = createAgents(data.namedItem("Agents").toElement()); if (Agents==NULL) { return NULL; } GCS::GObject * object = createObject(data.namedItem("Object").toElement()); if (object==NULL) { delete Agents; return NULL; } GCS::GElement * element = new GCS::GElement(object); if (element==NULL) { delete Agents; delete object; return NULL; } GCS::GAgent *Agent; for ( Agent = Agents->first(); Agent; Agent = Agents->next() ) { element->addAgent(Agent); } return element; } GCS::GElementID GCoreXmlSerializer::createElementID(QDomElement data, bool* ok) { if (ok!=NULL) *ok=true; if (data.isNull()) { if (ok!=NULL) *ok=false; return GCS::GElementID(0); } else return GCS::GElementID(data.text().toULong()); } /*! \fn GWE::GCoreXmlSerializer::createEnergy(QDomElement data) */ GCS::GEnergy* GCoreXmlSerializer::createEnergy(QDomElement data) { if (data.isNull()) return NULL; bool ok=false; double level = data.namedItem("Level").toElement().text().toDouble(&ok); if (!ok) return NULL; double amount = data.namedItem("Amount").toElement().text().toDouble(&ok); if (!ok) return NULL; double sigma = data.namedItem("Sigma").toElement().text().toDouble(&ok); if (!ok) return NULL; return new GCS::GEnergy(level,amount,sigma); } /*! \fn GWE::GCoreXmlSerializer::createForm(QDomElement data) */ GCS::GForm* GCoreXmlSerializer::createForm(QDomElement data) { QDomElement DomPosition = data.namedItem("Position").toElement(); QDomElement DomRotation = data.namedItem("Rotation").toElement(); QDomElement DomEllipsoid = data.namedItem("Ellipsoid").toElement(); if (DomPosition.isNull() || DomRotation.isNull() || DomEllipsoid.isNull()) return NULL; bool ok; //More efficient than making an extra function call to createVector3??? GCS::GVector3 position(this->createVector3(DomPosition,&ok)); if (!ok) return NULL; GCS::GVector3 rotation(this->createVector3(DomRotation,&ok)); if (!ok) return NULL; GCS::GVector3 ellipsoid(this->createVector3(DomEllipsoid,&ok)); if (!ok) return NULL; return new GCS::GForm( position, rotation, ellipsoid); } /*! \fn GWE::GCoreXmlSerializer::createVector3(QDomElement data) */ GCS::GVector3 GCoreXmlSerializer::createVector3(QDomElement data, bool* ok) { if (ok!=NULL) *ok=true; bool ok_private=false; double x = data.namedItem("x").toElement().text().toDouble(&ok_private); if (!ok_private) { if (ok!=NULL) *ok=false; } double y = data.namedItem("y").toElement().text().toDouble(&ok_private); if (!ok_private) { if (ok!=NULL) *ok=false; } double z = data.namedItem("z").toElement().text().toDouble(&ok_private); if (!ok_private) { if (ok!=NULL) *ok=false; } return GCS::GVector3(x,y,z); } /*! \fn GWE::GCoreXmlSerializer::createObject(QDomElement data) */ GCS::GObject* GCoreXmlSerializer::createObject(QDomElement data) { GCS::GEnergy * energy = createEnergy(data.namedItem("Energy").toElement()); if (energy==NULL) return NULL; GCS::GForm * form = createForm(data.namedItem("Form").toElement()); if (form==NULL) { delete energy; return NULL; } bool ok=false; GCS::GElementID parent = createElementID(data.namedItem("Parent").toElement(),&ok); if (!ok) { delete energy; delete form; return NULL; } GCS::GElementID ID = createElementID(data.namedItem("ID").toElement(),&ok); if (!ok) { delete energy; delete form; return NULL; } GCS::GElementID connection = createElementID(data.namedItem("Connection").toElement(),&ok); if (!ok) { delete energy; delete form; return NULL; } QDomDocument * mydata = createElementData(data.namedItem("Data").toElement()); if (mydata == NULL) { delete energy; delete form; return NULL; } GCS::GObject* object = new GCS::GObject(energy,form,parent,ID,connection,mydata,WorldData); if (object == NULL) { delete energy; delete form; delete mydata; return NULL; } return object; } GCS::GMatrix44 GCoreXmlSerializer::createMatrix44(QDomElement data, bool* ok) { if (ok!=NULL) *ok=true; bool ok_private=false; double m[4][4]; for (int i = 0; i<4; i++) { for (int j = 0; j<4; j++) { m[i][j] = data.namedItem(QString("m%1%2").arg(QString::number(i+1)).arg(QString::number(j+1))).toElement().text().toDouble(&ok_private); if (!ok_private) { if (ok!=NULL) *ok=false; } } } return GCS::GMatrix44(m[0][0],m[0][1],m[0][2],m[0][3], m[1][0],m[1][1],m[1][2],m[1][3], m[2][0],m[2][1],m[2][2],m[2][3], m[3][0],m[3][1],m[3][2],m[3][3]); } GCS::GElementInfluence GCoreXmlSerializer::createElementInfluence(QDomElement data, bool* ok) { if (ok!=NULL) *ok=true; GCS::GEnergy* e = this->createEnergy(data.namedItem("Energy").toElement()); GCS::GEnergy energy; if (e==NULL) { if (ok!=NULL) *ok=false; } else { energy.set(*e); } delete e; e=NULL; GCS::GElementID id = this->createElementID(data.namedItem("Source").toElement(),ok); return GCS::GElementInfluence(id,energy); } GCS::GElementID GCoreXmlSerializer::getInfluenceTarget(QDomElement data, bool* ok) { return GCS::GElementID(data.attribute("target","0").toULong(ok)); } /*! \fn GWE::GCoreXmlSerializer::serializeAgent(GCS::GAgent* agent, QString TagName, QDomDocument* document) */ QDomElement GCoreXmlSerializer::serializeAgent(const GCS::GAgent* agent, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); QDomElement Name = document->createElement( "name" ); root.appendChild( Name ); Name.appendChild( document->createTextNode( agent->className() ) ); return root; } /*! \fn GWE::GCoreXmlSerializer::serializeElementData(GCS::GElementData* data) */ QDomElement GCoreXmlSerializer::serializeElementData(const QDomDocument* data, QString TagName, QDomDocument* document) { if (data->isNull()) { qWarning("Element Data to serialize is NULL!"); } Q_CHECK_PTR(data); QDomElement e = document->createElement(TagName); document->appendChild(e); QDomNode child = data->firstChild(); while (!child.isNull()) { if (child.isElement()) e.appendChild(document->importNode(child,true)); child = child.nextSibling(); } // if (!data->isNull()) // { // qDebug("original element data:"); // qDebug(data->toString()); // qDebug("serialized element data:"); // qDebug(document->toString()); // } return e; } /*! \fn GWE::GCoreXmlSerializer::serializeElement(GCS::GElement* element) */ QDomElement GCoreXmlSerializer::serializeElement(const GCS::GElement* element, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); root.appendChild(serializeObject(element->getObject(),QString("Object"),document)); root.appendChild(serializeAgents(element->getAgents(),QString("Agents"),document)); root.setAttribute(QString("ParkTime"),element->getParkTime().toString()); return root; } QDomElement GCoreXmlSerializer::serializeElementID(const GCS::GElementID& element_id, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); root.appendChild(document->createTextNode(QString::number(element_id.getID()))); return root; } /*! \fn GWE::GCoreXmlSerializer::serializeEnergy(GCS::GEnergy* energy) */ QDomElement GCoreXmlSerializer::serializeEnergy(const GCS::GEnergy* energy, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); QString LevelString; QString AmountString; QString SigmaString; LevelString.setNum(energy->level()); AmountString.setNum(energy->amount()); SigmaString.setNum(energy->sigma()); QDomElement Level = document->createElement( "Level" ); root.appendChild( Level ); Level.appendChild( document->createTextNode( LevelString ) ); QDomElement Amount = document->createElement( "Amount" ); root.appendChild( Amount ); Amount.appendChild( document->createTextNode( AmountString ) ); QDomElement Sigma = document->createElement( "Sigma" ); root.appendChild( Sigma ); Sigma.appendChild( document->createTextNode( SigmaString ) ); return root; } /*! \fn GWE::GCoreXmlSerializer::serializeForm(GCS::GForm* form) */ QDomElement GCoreXmlSerializer::serializeForm(const GCS::GForm* form, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); root.appendChild( serializeVector3(&(form->Position),QString("Position"),document)); root.appendChild( serializeVector3(&(form->Rotation),QString("Rotation"),document)); root.appendChild( serializeVector3(&(form->Ellipsoid),QString("Ellipsoid"),document)); return root; } /*! \fn GWE::GCoreXmlSerializer::serializeVector3(GCS::GVector3* vector3) */ QDomElement GCoreXmlSerializer::serializeVector3(const GCS::GVector3* vector3, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); QString XString; QString YString; QString ZString; XString.setNum(vector3->x); YString.setNum(vector3->y); ZString.setNum(vector3->z); QDomElement X = document->createElement( "x" ); root.appendChild( X ); X.appendChild( document->createTextNode( XString ) ); QDomElement Y = document->createElement( "y" ); root.appendChild( Y ); Y.appendChild( document->createTextNode( YString ) ); QDomElement Z = document->createElement( "z" ); root.appendChild( Z ); Z.appendChild( document->createTextNode( ZString ) ); return root; } QDomElement GCoreXmlSerializer::serializeObject(const GCS::GObject* object, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); root.appendChild(serializeEnergy(object->getEnergy(),QString("Energy"),document)); root.appendChild(serializeForm(object->getForm(),QString("Form"),document)); root.appendChild(serializeElementID(object->getParent(),QString("Parent"),document)); root.appendChild(serializeElementID(object->getID(),QString("ID"),document)); root.appendChild(serializeElementID(object->getConnection(),QString("Connection"),document)); root.appendChild(serializeElementData(object->getElementData(),QString("Data"),document)); return root; } QDomElement GCoreXmlSerializer::serializeAgents(QValueList Agents, QString TagName, QDomDocument* document) { QDomElement root = document->createElement( TagName ); document->appendChild( root ); QValueList::iterator it; for ( it = Agents.begin(); it != Agents.end(); ++it ) { root.appendChild(serializeAgent(*it,QString("Agent"),document)); } return root; } QDomElement GCoreXmlSerializer::serializeMatrix44(const GCS::GMatrix44& matrix, QString TagName, QDomDocument* document) { //@todo implement QDomElement root = document->createElement(TagName); document->appendChild(root); for (int i=0; i<4; i++) { for (int j=0; j<4; j++) { QDomElement e = document->createElement(QString("m")+QString::number(i+1)+QString::number(j+1)); root.appendChild(e); e.appendChild(document->createTextNode(QString::number(matrix.m[i][j]))); } } return root; } QDomElement GCoreXmlSerializer::serializeElementInfluence(const GCS::GElementInfluence& influence, const GCS::GElementID& target_element, QString TagName, QDomDocument* document) { //@todo implement // IMPORTANT: the target_element should be modelled as an "attribute" of the root DOM element; // the GElementInfluence class does not hold any target IDs, thus we need to provide // this additional info to be able to reconstruct the target at other servers (in createElementInfluence()) QDomElement root = document->createElement(TagName); document->appendChild(root); root.setAttribute("target",QString::number(target_element.getID())); root.appendChild(this->serializeElementID(influence.source(),"Source",document)); root.appendChild(this->serializeEnergy(&influence.Energy,"Energy",document)); return root; } }