summaryrefslogtreecommitdiff
path: root/cpp/src/IceXML/StreamI.cpp
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2002-01-23 16:40:37 +0000
committerMatthew Newhook <matthew@zeroc.com>2002-01-23 16:40:37 +0000
commitcbddb4bb5eb52699fe267f75032b44c68e2532eb (patch)
treeab01c420bc5f6c1a9b6fe39817e3717386a44e7e /cpp/src/IceXML/StreamI.cpp
parentInitial commit of generic marshaling. (diff)
downloadice-cbddb4bb5eb52699fe267f75032b44c68e2532eb.tar.bz2
ice-cbddb4bb5eb52699fe267f75032b44c68e2532eb.tar.xz
ice-cbddb4bb5eb52699fe267f75032b44c68e2532eb.zip
added missing files. Renamed XMLStream to StreamI. Renamed XMLOutput to
Output.
Diffstat (limited to 'cpp/src/IceXML/StreamI.cpp')
-rw-r--r--cpp/src/IceXML/StreamI.cpp1362
1 files changed, 1362 insertions, 0 deletions
diff --git a/cpp/src/IceXML/StreamI.cpp b/cpp/src/IceXML/StreamI.cpp
new file mode 100644
index 00000000000..82f30514ca7
--- /dev/null
+++ b/cpp/src/IceXML/StreamI.cpp
@@ -0,0 +1,1362 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/Object.h>
+#include <Ice/Communicator.h>
+#include <Ice/Logger.h>
+#include <Ice/LocalException.h>
+#include <Ice/ObjectFactory.h>
+
+#include <IceXML/StreamI.h>
+
+//
+// For input streaming
+//
+#include <framework/MemBufInputSource.hpp>
+#include <util/PlatformUtils.hpp>
+#include <util/XMLString.hpp>
+#include <util/XMLUniDefs.hpp>
+#include <framework/XMLFormatter.hpp>
+#include <util/TranscodingException.hpp>
+
+#include <dom/DOM_DOMException.hpp>
+#include <parsers/DOMParser.hpp>
+
+#include <dom/DOM_Node.hpp>
+#include <dom/DOM_NamedNodeMap.hpp>
+
+#include <sax/ErrorHandler.hpp>
+#include <sax/SAXParseException.hpp>
+#include <dom/DOMString.hpp>
+
+using namespace std;
+using namespace IceXML;
+
+//
+// Utilities to make the usage of xerces easier.
+//
+static string
+toString(const DOMString& s)
+{
+ char* t = s.transcode();
+ string r(t);
+ delete[] t;
+ return r;
+}
+
+static string
+toString(const XMLCh* s)
+{
+ char* t = XMLString::transcode(s);
+ string r(t);
+ delete[] t;
+ return r;
+}
+
+//
+// Error handling class for xerces.
+//
+class DOMTreeErrorReporter : public ErrorHandler
+{
+public:
+
+ DOMTreeErrorReporter(const ::Ice::LoggerPtr logger) :
+ _logger(logger),
+ _sawErrors(false)
+ {
+ }
+
+ virtual void
+ warning(const SAXParseException& ex)
+ {
+ ostringstream os;
+ os << "xerces: file: \"" << toString(ex.getSystemId())
+ << "\", line:" << ex.getLineNumber()
+ << ", column: " << ex.getColumnNumber()
+ << "\n,essage: " << toString(ex.getMessage()) << endl;
+ _logger->warning(os.str());
+ }
+
+ virtual void
+ error(const SAXParseException& ex)
+ {
+ _sawErrors = true;
+ ostringstream os;
+ os << "xerces: file: \"" << toString(ex.getSystemId())
+ << "\", line: " << ex.getLineNumber()
+ << ", column: " << ex.getColumnNumber()
+ << "\nmessage: " << toString(ex.getMessage()) << endl;
+ _logger->error(os.str());
+ }
+
+ virtual void
+ fatalError(const SAXParseException& ex)
+ {
+ _sawErrors = true;
+ ostringstream os;
+ os << "xerces: file: \"" << toString(ex.getSystemId())
+ << "\", line: " << ex.getLineNumber()
+ << ", column: " << ex.getColumnNumber()
+ << "\nmessage: " << toString(ex.getMessage()) << endl;
+ _logger->error(os.str());
+ }
+
+ virtual void
+ resetErrors()
+ {
+ }
+
+ bool
+ getSawErrors() const
+ {
+ return _sawErrors;
+ }
+
+private:
+
+ ::Ice::LoggerPtr _logger;
+ bool _sawErrors;
+};
+
+namespace IceXML
+{
+
+//
+// This is used to reduce the external dependencies on the xerces
+// headers.
+//
+struct StreamInputImpl
+{
+ StreamInputImpl() :
+ source(0),
+ parser(0),
+ errReporter(0)
+ {
+ }
+ ~StreamInputImpl()
+ {
+ delete parser;
+ delete errReporter;
+ delete source;
+ }
+
+ InputSource* source;
+ DOMParser* parser;
+ DOMTreeErrorReporter* errReporter;
+ DOM_Node current;
+
+ list<DOM_Node> nodeStack;
+
+ map<string, ::Ice::ObjectPtr> readObjects;
+};
+
+} // End namespace IceXML
+
+//
+// A constant string which is used as the name of collection elements.
+//
+const string IceXML::StreamI::seqElementName("e");
+
+IceXML::StreamI::StreamI(const ::Ice::CommunicatorPtr& communicator, std::ostream& os) :
+ _communicator(communicator),
+ _input(0),
+ _os(os),
+ _nextId(0)
+{
+ ::Ice::LoggerPtr logger = communicator->getLogger();
+ //
+ // Initialize the XML4C2 system. TODO: This really needs to be
+ // dealt with as global system state.
+ //
+ try
+ {
+ XMLPlatformUtils::Initialize();
+ }
+ catch (const XMLException& ex)
+ {
+ string err = "xerces: initialize failed: ";
+ err += toString(ex.getMessage());
+ logger->error(err);
+ throw ::Ice::SystemException(__FILE__, __LINE__);
+ }
+}
+
+
+IceXML::StreamI::StreamI(const ::Ice::CommunicatorPtr& communicator, std::istream& is) :
+ _communicator(communicator),
+ _nextId(0)
+{
+ ::Ice::LoggerPtr logger = communicator->getLogger();
+
+ //
+ // Initialize the XML4C2 system. TODO: This really needs to be
+ // dealt with as global system state.
+ //
+ try
+ {
+ XMLPlatformUtils::Initialize();
+ }
+ catch (const XMLException& ex)
+ {
+ string err = "xerces: initialize failed: ";
+ err += toString(ex.getMessage());
+ logger->error(err);
+ throw ::Ice::SystemException(__FILE__, __LINE__);
+ }
+
+ //
+ // Read the contents of the stream into memory.
+ //
+ while (!is.eof())
+ {
+ char buf[1000];
+ is.read(buf, sizeof(buf));
+ _content.append(buf, is.gcount());
+ }
+
+ _input = new StreamInputImpl();
+ _input->source = new MemBufInputSource((const XMLByte*)_content.data(), _content.size(), "inputsource");
+
+ //
+ // Create our parser, then attach an error handler to the parser.
+ // The parser will call back to methods of the ErrorHandler if it
+ // discovers errors during the course of parsing the XML
+ // document.
+ //
+ _input->parser = new DOMParser;
+ _input->parser->setValidationScheme(DOMParser::Val_Auto);
+ _input->parser->setDoNamespaces(true);
+ _input->parser->setDoSchema(true);
+ //_input->parser->setValidationSchemaFullChecking(true);
+
+ _input->errReporter = new DOMTreeErrorReporter(logger);
+ _input->parser->setErrorHandler(_input->errReporter);
+ _input->parser->setCreateEntityReferenceNodes(false);
+ _input->parser->setToCreateXMLDeclTypeNode(true);
+
+ // TODO:
+ // parser->setEntityResolver
+
+ //
+ // Parse the XML file, catching any XML exceptions that might propogate
+ // out of it.
+ //
+ bool errorsOccured = false;
+ try
+ {
+ _input->parser->parse(*_input->source);
+ int errorCount = _input->parser->getErrorCount();
+ if (errorCount > 0)
+ {
+ errorsOccured = true;
+ }
+ }
+ catch (const XMLException& ex)
+ {
+ ostringstream os;
+ os << "xerces: parsing error: " << toString(ex.getMessage());
+ logger->error(os.str());
+ errorsOccured = true;
+ }
+ catch (const DOM_DOMException& ex)
+ {
+ ostringstream os;
+ os << "xerces: DOM parsing error: " << toString(ex.msg);
+ logger->error(os.str());
+ errorsOccured = true;
+ }
+
+ if (errorsOccured)
+ {
+ delete _input;
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ //
+ // The first child of the document is the root node - ignore
+ // that. Move to the top-level node in the document content.
+ //
+ _input->current = _input->parser->getDocument().getFirstChild();
+ _input->current = _input->current.getFirstChild();
+}
+
+IceXML::StreamI::~StreamI()
+{
+ delete _input;
+
+ //
+ // And call the termination method (TODO: is this correct -
+ // reference count?)
+ //
+ XMLPlatformUtils::Terminate();
+}
+
+void
+IceXML::StreamI::startWriteDictionary(const string& name, ::Ice::Int size)
+{
+ ostringstream os;
+ os << name << " length=\"" << size << "\"";
+ startWrite(os.str());
+}
+
+void
+IceXML::StreamI::endWriteDictionary()
+{
+ endWrite();
+}
+
+void
+IceXML::StreamI::startWriteDictionaryElement()
+{
+ startWrite(seqElementName);
+}
+
+void
+IceXML::StreamI::endWriteDictionaryElement()
+{
+ endWrite();
+}
+
+void
+IceXML::StreamI::startReadDictionary(const string& name, ::Ice::Int& size)
+{
+ startRead(name);
+ size = readLength();
+ _input->current = _input->current.getFirstChild();
+}
+
+void
+IceXML::StreamI::endReadDictionary()
+{
+ endRead();
+}
+
+void
+IceXML::StreamI::startReadDictionaryElement()
+{
+ startRead(seqElementName);
+}
+
+void
+IceXML::StreamI::endReadDictionaryElement()
+{
+ endRead();
+}
+
+void
+IceXML::StreamI::startWriteSequence(const string& name, ::Ice::Int size)
+{
+ ostringstream os;
+ os << name << " length=\"" << size << "\"";
+ startWrite(os.str());
+}
+
+void
+IceXML::StreamI::endWriteSequence()
+{
+ endWrite();
+}
+
+void
+IceXML::StreamI::startWriteSequenceElement()
+{
+ startWrite(seqElementName);
+}
+
+void
+IceXML::StreamI::endWriteSequenceElement()
+{
+ endWrite();
+}
+
+void
+IceXML::StreamI::startReadSequence(const string& name, ::Ice::Int& size)
+{
+ startRead(name);
+ size = readLength();
+ _input->current = _input->current.getFirstChild();
+}
+
+void
+IceXML::StreamI::endReadSequence()
+{
+ endRead();
+}
+
+void
+IceXML::StreamI::startReadSequenceElement()
+{
+ startRead(seqElementName);
+}
+
+void
+IceXML::StreamI::endReadSequenceElement()
+{
+ endRead();
+}
+
+void
+IceXML::StreamI::startWriteStruct(const string& name)
+{
+ startWrite(name);
+}
+
+void
+IceXML::StreamI::endWriteStruct()
+{
+ endWrite();
+}
+
+void
+IceXML::StreamI::startReadStruct(const string& name)
+{
+ startRead(name);
+ _input->current = _input->current.getFirstChild();
+}
+
+void
+IceXML::StreamI::endReadStruct()
+{
+ endRead();
+}
+
+void
+IceXML::StreamI::startWriteException(const string& name)
+{
+ startWrite(name);
+}
+
+void
+IceXML::StreamI::endWriteException()
+{
+ endWrite();
+}
+
+void
+IceXML::StreamI::startReadException(const string& name)
+{
+ startRead(name);
+ _input->current = _input->current.getFirstChild();
+}
+
+void
+IceXML::StreamI::endReadException()
+{
+ endRead();
+}
+
+void
+IceXML::StreamI::writeEnum(const string& name, const ::Ice::StringSeq& table, ::Ice::Int ordinal)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << table[ordinal] << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::readEnum(const string& name, const ::Ice::StringSeq& table, ::Ice::Int& ordinal)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string value = toString(child.getNodeValue());
+ ::Ice::StringSeq::const_iterator p = find(table.begin(), table.end(), value);
+ if (p == table.end())
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+ ordinal = p - table.begin();
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeByte(const string& name, ::Ice::Byte value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+
+ // The schema encoding for xs:byte is a value from -127 to 128.
+ _os << nl << "<" << name << ">" << (int)value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeByteSeq(const string& name, const ::Ice::ByteSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::ByteSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << (int)*p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readByte(const string& name, ::Ice::Byte& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ ::Ice::Int i = atoi(s.c_str());
+ if (i < -127 || i > 128)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+ value = (::Ice::Byte)i;
+
+ endRead();
+}
+
+//
+// None of the read*Seq methods are very efficient. It's possible to
+// write them as follows in a much more efficient manner - but it's
+// not as maintainable.
+//
+// startRead(name);
+// ::Ice::Int size = readLength();
+// value.resize(size);
+// value_type::iterator p = value.begin();
+// DOM_NodeList children = _input->current.getChildNodes();
+//
+// int nchildren = children.getLength();
+// for (int i = 0; i < nchildren; ++i)
+// {
+// DOM_Node child = children.item(i);
+// while (child.getNodeType() != DOM_Node::ELEMENT_NODE)
+// {
+// child = child.getNextSibling();
+// }
+// string name = toString(child.getNodeName());
+// if (name != seqElementName)
+// {
+// throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+// }
+//
+// child = child.getFirstChild();
+// if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+// {
+// throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+// }
+//
+// string s = toString(child.getNodeValue());
+// *p++ = ???;
+// }
+//
+// endRead();
+//
+//
+//
+
+void
+IceXML::StreamI::readByteSeq(const string& name, ::Ice::ByteSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readByte(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeBool(const string& name, bool value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << (value ? "true" : "false") << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeBoolSeq(const string& name, const ::Ice::BoolSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::BoolSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << ((*p) ? "true" : "false") << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readBool(const string& name, bool& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ value = (s == "true") ? true : false;
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readBoolSeq(const string& name, ::Ice::BoolSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ bool v;
+ readBool(seqElementName, v);
+ value[i] = v;
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeShort(const string& name, ::Ice::Short value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeShortSeq(const string& name, const ::Ice::ShortSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::ShortSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << *p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readShort(const string& name, ::Ice::Short& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ value = atoi(s.c_str());
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readShortSeq(const string& name, ::Ice::ShortSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readShort(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeInt(const string& name, ::Ice::Int value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeIntSeq(const string& name, const ::Ice::IntSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::IntSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << *p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readInt(const string& name, ::Ice::Int& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ value = atoi(s.c_str());
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readIntSeq(const string& name, ::Ice::IntSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readInt(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeLong(const string& name, ::Ice::Long value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeLongSeq(const string& name, const ::Ice::LongSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::LongSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << *p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readLong(const string& name, ::Ice::Long& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ value = atol(s.c_str());
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readLongSeq(const string& name, ::Ice::LongSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readLong(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeFloat(const string& name, ::Ice::Float value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeFloatSeq(const string& name, const ::Ice::FloatSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::FloatSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << *p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readFloat(const string& name, ::Ice::Float& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ value = atof(s.c_str());
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readFloatSeq(const string& name, ::Ice::FloatSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readFloat(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeDouble(const string& name, ::Ice::Double value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeDoubleSeq(const string& name, const ::Ice::DoubleSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::DoubleSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << *p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readDouble(const string& name, ::Ice::Double& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (child.isNull() || child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string s = toString(child.getNodeValue());
+ value = atof(s.c_str());
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readDoubleSeq(const string& name, ::Ice::DoubleSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readDouble(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeString(const string& name, const string& value)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ _os << nl << "<" << name << ">" << value << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::writeStringSeq(const string& name, const ::Ice::StringSeq& seq)
+{
+ startWrite(name);
+ for (::Ice::StringSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
+ {
+ _os << nl << "<e>" << *p << "</e>";
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readString(const string& name, string& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ if (!child.isNull())
+ {
+ if (child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+ value = toString(child.getNodeValue());
+ }
+ else
+ {
+ static const string empty("");
+ value = empty;
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::readStringSeq(const string& name, ::Ice::StringSeq& value)
+{
+ startRead(name);
+
+ ::Ice::Int size = readLength();
+ value.resize(size);
+ if (size > 0)
+ {
+ _input->current = _input->current.getFirstChild();
+ for (int i = 0; i < size; ++i)
+ {
+ readString(seqElementName, value[i]);
+ }
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeProxy(const string& name, const ::Ice::ObjectPrx& proxy)
+{
+ // No attributes
+ assert(name.find_first_of(" \t") == string::npos);
+ string s = _communicator->proxyToString(proxy);
+ _os << nl << "<" << name << ">" << s << "</" << name << ">";
+}
+
+void
+IceXML::StreamI::readProxy(const string& name, ::Ice::ObjectPrx& value)
+{
+ startRead(name);
+
+ DOM_Node child = _input->current.getFirstChild();
+ string s;
+ if (!child.isNull())
+ {
+ if (child.getNodeType() != DOM_Node::TEXT_NODE)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+ s = toString(child.getNodeValue());
+ }
+
+ value = _communicator->stringToProxy(s);
+
+ endRead();
+}
+
+void
+IceXML::StreamI::writeObject(const string& name, const ::Ice::ObjectPtr& obj)
+{
+ //
+ // If at the top level of the document then the object itself must
+ // be written, otherwise write a reference.
+ //
+ bool writeReference = (_elementStack.size() != 0);
+
+ //
+ // If the object doesn't exist in the map add it.
+ //
+ map<Ice::ObjectPtr, ObjectInfo>::iterator p = _objects.find(obj);
+ if (p == _objects.end())
+ {
+ ostringstream os;
+ os << "object" << _nextId++;
+ p = _objects.insert(map<Ice::ObjectPtr, ObjectInfo>::value_type(
+ obj, ObjectInfo(os.str(), !writeReference))).first;
+ }
+
+ if (writeReference)
+ {
+ _os << nl << "<" << name << " href=\"#" << p->second.id << "\"/>";
+ }
+ else
+ {
+ //
+ // Precondition: If the actual object is being written the
+ // written flag should be true.
+ //
+ assert(p->second.written);
+ writeObjectData(name, p->second.id, obj);
+ }
+}
+
+void
+IceXML::StreamI::readObject(const string& name, const string& signatureType, const ::Ice::ObjectFactoryPtr& factory,
+ ::Ice::ObjectPtr& value)
+{
+ startRead(name);
+
+ //
+ // Node attributes. Either id & type will be set, or href.
+ //
+ string id, type, href;
+ readAttributes(id, type, href);
+
+ //
+ // If this object is an href then locate the object. If the object
+ // has been previously read then it will be contained in the
+ // readObjects list. Otherwise, it should be in the object-set at
+ // the top-level of the document.
+ //
+ if (!href.empty())
+ {
+ href = href.substr(1); // Skip the '#'
+
+ map<string, ::Ice::ObjectPtr>::const_iterator p = _input->readObjects.find(href);
+ if (p != _input->readObjects.end())
+ {
+ value = p->second;
+ endRead();
+ return;
+ }
+
+ //
+ // The first child of the document is the root node - ignore
+ // that. Move to the top-level node in the document content.
+ //
+ _input->current = _input->parser->getDocument().getFirstChild();
+ _input->current = _input->current.getFirstChild();
+ while (!_input->current.isNull())
+ {
+ if (_input->current.getNodeType() == DOM_Node::ELEMENT_NODE)
+ {
+ string dummy;
+ readAttributes(id, type, dummy);
+ if (id == href)
+ {
+ break;
+ }
+ }
+ _input->current = _input->current.getNextSibling();
+ }
+ //
+ // If the object isn't found, that's an error.
+ //
+ if (_input->current.isNull())
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+ }
+
+ //
+ // Empty type indicates nil object.
+ //
+ if (type.empty())
+ {
+ value = 0;
+ }
+ else
+ {
+ static const string iceObject("::Ice::Object");
+
+ if (type == iceObject)
+ {
+ value = new ::Ice::Object;
+ }
+ else
+ {
+ //
+ // First, determine if there is an installed factory for this
+ // type. If so use that. If that factory doesn't exist, or it
+ // doesn't create an object of that type then use the supplied
+ // factory provided that the types are the same. If no value
+ // can be created then throw a NoObjectFactoryException.
+ //
+ ::Ice::ObjectFactoryPtr userFactory = _communicator->findObjectFactory(type);
+ if (userFactory)
+ {
+ value = userFactory->create(type);
+ }
+
+ if (!value && type == signatureType)
+ {
+ assert(factory);
+ value = factory->create(type);
+ assert(value);
+ }
+
+ if (!value)
+ {
+ throw ::Ice::NoObjectFactoryException(__FILE__, __LINE__);
+ }
+ }
+
+ //
+ // Add the object to the readObjects map, move to the first
+ // child node & unmarshal the object.
+ //
+ _input->readObjects.insert(map<string, ::Ice::ObjectPtr>::value_type(id, value));
+ _input->current = _input->current.getFirstChild();
+ value->__unmarshal(this);
+ }
+
+ endRead();
+}
+
+void
+IceXML::StreamI::startWrite(const string& element)
+{
+ _os << nl << '<' << element << '>';
+ _os.inc();
+
+ string::size_type pos = element.find_first_of(" \t");
+ if (pos == string::npos)
+ {
+ _elementStack.push(element);
+ }
+ else
+ {
+ _elementStack.push(element.substr(0, pos));
+ }
+}
+
+void
+IceXML::StreamI::endWrite()
+{
+ string element = _elementStack.top();
+ _elementStack.pop();
+
+ _os.dec();
+ _os << nl << "</" << element << '>';
+
+ if (_elementStack.size() == 0)
+ {
+ dumpUnwrittenObjects();
+ }
+}
+
+
+void
+IceXML::StreamI::startRead(const ::std::string& element)
+{
+ while (!_input->current.isNull() && _input->current.getNodeType() != DOM_Node::ELEMENT_NODE)
+ {
+ _input->current = _input->current.getNextSibling();
+ }
+ if (_input->current.isNull())
+ {
+ cout << "element: " << element << endl;
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ string nodeName = toString(_input->current.getNodeName());
+ if (element != nodeName)
+ {
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+ }
+
+ _input->nodeStack.push_back(_input->current);
+}
+
+void
+IceXML::StreamI::endRead()
+{
+ _input->current = _input->nodeStack.back();
+ _input->nodeStack.pop_back();
+ _input->current = _input->current.getNextSibling();
+}
+
+void
+IceXML::StreamI::dumpUnwrittenObjects()
+{
+ //
+ // Precondition: Must be at the top-level.
+ //
+ assert(_elementStack.size() == 0);
+
+ //
+ // It's necessary to run through the set of unwritten objects
+ // repeatedly until all referenced objects have been written
+ // (since referenced objects can themselves reference other
+ // objects).
+ //
+ unsigned int nwritten;
+ do
+ {
+ nwritten = 0;
+ map<Ice::ObjectPtr, ObjectInfo>::iterator p;
+ for (p = _objects.begin(); p != _objects.end(); ++p)
+ {
+ if (!p->second.written)
+ {
+ p->second.written = true;
+ writeObjectData("ice:object", p->second.id, p->first);
+ ++nwritten;
+ }
+ else
+ {
+ ++nwritten;
+ }
+ }
+ }
+ while (_objects.size() != nwritten);
+}
+
+void
+IceXML::StreamI::writeObjectData(const string& name, const string& id, const Ice::ObjectPtr& obj)
+{
+ string xsdType;
+ string typeId;
+
+ if (obj)
+ {
+ //
+ // Convert the type-id to the equivalent schema type
+ // definition name.
+ //
+ typeId = obj->__getClassIds()[0];
+
+ static const string xsdPrefix = "_internal.";
+ static const string xsdSuffix = "Type";
+ xsdType.reserve(typeId.size() + xsdPrefix.size() + xsdSuffix.size());
+ xsdType += xsdPrefix;
+ unsigned int i = 0;
+ if (typeId[0] == ':') // Skip the preceeding "::".
+ {
+ i = 2;
+ }
+ for (; i < typeId.size(); ++i)
+ {
+ if (typeId[i] == ':')
+ {
+ xsdType += '.';
+ ++i;
+ }
+ else
+ {
+ xsdType += typeId[i];
+ }
+ }
+ xsdType += xsdSuffix;
+ }
+ else
+ {
+ xsdType = "";
+ }
+
+ ostringstream os;
+ os << name << " id=\"" << id << "\" type=\"" << typeId << "\""
+ << " xsi:type=\"" << xsdType << "\"";
+ if (!obj)
+ {
+ os << " xsi:nil=\"true\"";
+ }
+
+ startWrite(os.str());
+ if (obj)
+ {
+ obj->__marshal(this);
+ }
+ endWrite();
+}
+
+void
+IceXML::StreamI::readAttributes(::std::string& id, ::std::string& type, ::std::string& href)
+{
+ static const string idStr("id");
+ static const string typeStr("type");
+ static const string hrefStr("href");
+
+ DOM_NamedNodeMap attributes = _input->current.getAttributes();
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount; i++)
+ {
+ DOM_Node attribute = attributes.item(i);
+ string name = toString(attribute.getNodeName());
+ if (name == idStr)
+ {
+ id = toString(attribute.getNodeValue());
+ }
+ else if (name == typeStr)
+ {
+ type = toString(attribute.getNodeValue());
+ }
+ else if (name == hrefStr)
+ {
+ href = toString(attribute.getNodeValue());
+ }
+ }
+}
+
+::Ice::Int
+IceXML::StreamI::readLength()
+{
+ static const string lengthStr("length");
+
+ DOM_NamedNodeMap attributes = _input->current.getAttributes();
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount; i++)
+ {
+ DOM_Node attribute = attributes.item(i);
+ string name = toString(attribute.getNodeName());
+ if (name == lengthStr)
+ {
+ return atoi(toString(attribute.getNodeValue()).c_str());
+ }
+ }
+
+ throw ::Ice::UnmarshalException(__FILE__, __LINE__);
+}