Logo Search packages:      
Sourcecode: kmess version File versions

soapmessage.cpp

/***************************************************************************
                          soapmessage.cpp  -  description
                             -------------------
    begin                : Sun Jul 24 2005
    copyright            : (C) 2005 by Diederik van der Boor
    email                : vdboor --at-- codingdomain.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "soapmessage.h"
#include "xmlfunctions.h"
#include "../../kmessdebug.h"

#include <kdebug.h>
#include <qtextstream.h>

#ifdef KMESSDEBUG_SOAPMESSAGE
  #define KMESSDEBUG_SOAPMESSAGE_GENERAL
#endif



// The soap message constructor
SoapMessage::SoapMessage()
: errorCode_(0)
{
}



// The constructor for action SoapMessages
SoapMessage::SoapMessage(const QString &message)
: errorCode_(0)
{
  parseMessage(message);
}



// The destructor
SoapMessage::~SoapMessage()
{

}



// Add a field to the message
void SoapMessage::addField(const QString& field, const QString& value)
{
  fields_ << field;
  values_ << value;
}



// Change a field, or add it
void SoapMessage::setField(const QString& field, const QString& value)
{
  int index = fields_.findIndex(field);
  if(index == -1)
  {
    addField(field, value);
  }
  else
  {
    values_[index]= value;
  }
}



// Return the message action
const QString& SoapMessage::getAction() const
{
  return action_;
}



// Return the message action namespace prefix
const QString& SoapMessage::getActionPrefix() const
{
  return actionPrefix_;
}



// Return the message action namespace
const QString& SoapMessage::getActionNamespace() const
{
  return actionNs_;
}



// Return the error code
int SoapMessage::getErrorCode() const
{
  return errorCode_;
}



// Return the error description
const QString& SoapMessage::getErrorDescription() const
{
  return errorDescription_;
}



// Return the entire message as string
QString SoapMessage::getMessage() const
{
  // Create the data message
  QString soapMessage = "<s:Envelope"
                        " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
                        " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""
                        "><s:Body>";

  // Add the body tag
  if(actionPrefix_.isEmpty())
  {
    soapMessage += "<" + action_;
    if(! actionNs_.isEmpty())
    {
      soapMessage += " xmlns=\"" + actionNs_  + "\"";
    }
    soapMessage += ">";
  }
  else
  {
    // Create a <m:Tag xmlns:m="fdfd"> tag
    soapMessage += "<" + actionPrefix_ + ":" + action_;
    if(! actionNs_.isEmpty())
    {
      soapMessage += " xmlns:" + actionPrefix_ + "=\"" + actionNs_  + "\"";
    }
    soapMessage += ">";
  }

  // If we received a tree of result nodes, include that
  if(! responseBody_.isNull())
  {
    QString str;
    QTextStream ts( &str, IO_WriteOnly );
    ts << responseBody_;
    soapMessage += str;
  }
  else
  {
    // Otherwise, add the parsed field/value pairs

    // Add the fields and values
    for ( uint i = 0; i < fields_.count(); i++ )
    {
      soapMessage += "<" + fields_[i] + ">" + values_[i] + "</" + fields_[i] + ">";
    }
  }

  // Add the body closing tag
  if(actionPrefix_.isEmpty())
  {
    soapMessage += "</" + action_ + ">";
  }
  else
  {
    soapMessage += "</" + actionPrefix_ + ":" + action_ + ">";
  }

  // Add the remaining tags
  soapMessage += "</s:Body></s:Envelope>";

  // Return the message
  return soapMessage;
}



// The total number of fields
uint SoapMessage::getNoFields() const
{
  return fields_.count();
}



// Get a value given a field
const QString& SoapMessage::getValue(const QString& field ) const
{
  int index = fields_.findIndex( field );

  // Warn if not found
  if(index == -1)
  {
    kdWarning() << "SoapMessage: This message does not have a field named '" << field << "'." << endl;
    return QString::null;
  }

  return values_[index];
}



// Return the response xml tree
const QDomNode& SoapMessage::getResponseBody() const
{
  return responseBody_;
}



// Test whether a given field exists in the message header
bool SoapMessage::hasField(const QString& field) const
{
  return (fields_.findIndex( field ) == -1);
}



// Return whether this was an error response
bool SoapMessage::isErrorMessage() const
{
  return (errorCode_ != 0);
}



// Parse the incoming message
void SoapMessage::parseMessage(const QString &message)
{
  QDomDocument xml;

  // Parse the XML
  QString errorMessage;
  bool    error = ! xml.setContent(message, true, &errorMessage);

  // Handle errors first
  if(error)
  {
    kdWarning() << "SoapMessage::parseMessage - XML Parsing failed: '" << errorMessage << "'." << endl;
    // Create a dummy the error message
    errorCode_        = 1;
    errorDescription_ = errorMessage;
    return;
  }

  // Get the body child node
  QDomNode resultNode     = XmlFunctions::getNode(xml, "/Envelope/Body").firstChild();
  QString  resultNodeName = resultNode.toElement().nodeName();

  if(resultNode.isNull())
  {
    kdWarning() << "SoapMessage::parseMessage - XML Parsing failed: result node is null." << endl;
    // Create a dummy the error message
    errorCode_        = 1;
    errorDescription_ = "result node is null";
    return;
  }

  // See if it's a soap error message
  if(resultNodeName == "Fault")
  {
    QString faultString = XmlFunctions::getNodeValue(resultNode, "/faultstring");
    errorCode_          = XmlFunctions::getNodeValue(resultNode, "/detail/" + faultString + "/errorCode").toInt();
    errorDescription_   = XmlFunctions::getNodeValue(resultNode, "/detail/" + faultString + "/errorDescription");
    return;
  }

  // TODO: test this parsing code
  action_       = resultNodeName;
  actionPrefix_ = resultNode.prefix();
  actionNs_     = resultNode.namespaceURI();

  // Try to parse the result node
  if(resultNodeName.endsWith("Response"))
  {
    responseBody_ = resultNode.firstChild();
  }
  else
  {
    // Parse all parameters
    // It's possible to pass the entire QDomNode object to the gotActionResponse()
    // function, but this is somewhat nicer, and reduces code boat in the subclasses
    QDomNodeList children = resultNode.childNodes();
    for(uint i = 0; i < children.count(); i++)
    {
      fields_.append( children.item(i).nodeName()         );
      values_.append( children.item(i).toElement().text() );
    }
  }
}



// Set the message type
void SoapMessage::setAction(const QString &action, const QString &prefix, const QString &xmlns)
{
  action_       = action;
  actionPrefix_ = prefix;
  actionNs_     = xmlns;
}




Generated by  Doxygen 1.6.0   Back to index