#include "streamSerializerXML.h"
#include "metadataXML.h"
#include "metadataXMLPluginStrings.h"
#include <sstream>
#include <string>
#include <map>
#include <stdlib.h>
#include <string.h>
#include <maya/MString.h>
#include <maya/MStringResource.h>
#include <maya/adskDataIndex.h>
#include <maya/adskDataStream.h>
#include <maya/adskDataStructure.h>
#include <maya/adskDataStreamSerializer.h>
#include <assert.h>
#include <libxml/globals.h>
#include <libxml/xmlreader.h>
#include <libxml/parser.h>
using namespace adsk::Data::XML;
StreamSerializerXML::StreamSerializerXML()
{
}
StreamSerializerXML::~StreamSerializerXML ()
{
}
StreamSerializerXML::read(
std::istream& cSrc,
std::string& errors ) const
{
unsigned int errorCount = 0;
errors = "";
xmlDocPtr doc = NULL;
LIBXML_TEST_VERSION
cSrc.seekg (0, std::ios::end);
int size = (int) cSrc.tellg();
char* memblock = new char [size];
cSrc.seekg (0, std::ios::beg);
cSrc.read (memblock, size);
doc = xmlReadMemory(memblock, size, NULL, NULL, 0);
xmlNode* rootEl = Util::findNamedNode( xmlDocGetRootElement(doc), xmlTagStream );
newStream = parseDOM( doc, *rootEl, errorCount, errors );
delete[] memblock;
xmlFreeDoc(doc);
if( errorCount > 0 )
{
delete newStream;
newStream = NULL;
}
return newStream;
}
StreamSerializerXML::parseDOM(
xmlDocPtr doc,
xmlNode& streamNode,
unsigned int& errorCount,
std::string& errors ) const
{
if( 0 != strcmp( (const char*)streamNode.name, xmlTagStream ) )
{
return NULL;
}
xmlNode* nameNode = Util::findNamedNode( streamNode.children, xmlTagStreamName );
const char* streamName = nameNode ? (const char*) Util::findText( doc, nameNode ) : NULL;
if( ! streamName )
{
REPORT_ERROR_AT_LINE(kStreamXMLStreamNameMissing, streamNode.line);
return newStream;
}
xmlNode* structureNode = Util::findNamedNode( streamNode.children, xmlTagStreamStructure );
if( !structureNode )
{
REPORT_ERROR_AT_LINE1(kStreamXMLStructureNotFound, structureName, streamNode.line)
return NULL;
}
else
{
structureName = (const char*) Util::findText( doc, structureNode );
}
if( ! structure )
{
if( structureName.
length() > 0 )
{
REPORT_ERROR_AT_LINE1(kStreamXMLStructureNotFound, structureName, streamNode.line)
}
else
{
REPORT_ERROR_AT_LINE(kStreamXMLStructureMissing, streamNode.line);
}
return newStream;
}
xmlNode* indexTypeNode = Util::findNamedNode( streamNode.children, xmlTagStreamIndexType );
const char* indexTypeName = indexTypeNode ? (const char*)Util::findText(doc, indexTypeNode) : NULL;
if( indexTypeName )
{
std::string indexTypeStr( indexTypeName );
{
MString invalidIndexType( indexTypeName );
REPORT_ERROR_AT_LINE1(kStreamXMLIndexTypeInvalid, invalidIndexType, streamNode.line);
delete newStream;
return NULL;
}
}
if( ! indexCreator )
{
MString invalidIndexType( indexTypeName );
REPORT_ERROR_AT_LINE1(kStreamXMLIndexTypeInvalid, invalidIndexType, streamNode.line);
delete newStream;
return NULL;
}
if( streamNode.children && newStream )
{
for( xmlNode* dataNode = streamNode.children;
dataNode; dataNode = dataNode->next )
{
if( (dataNode->type != XML_ELEMENT_NODE)
|| (0 != strcmp( (const char*)dataNode->name, xmlTagStreamData) ) )
{
continue;
}
bool foundIndex = false;
std::map<std::string,int> tagDimensions;
for( xmlNode* valueNode = dataNode->children;
valueNode; valueNode = valueNode->next )
{
if( valueNode->type != XML_ELEMENT_NODE )
{
continue;
}
if( 0 == strcmp( (const char*)valueNode->name, xmlTagStreamDataIndex ) )
{
dataIndex = indexCreator( (const char*)Util::findText( doc, valueNode ) );
foundIndex = true;
}
else
{
std::string valueName( (const char*)valueNode->name );
if( newValue.setPositionByMemberName( (const char*)valueNode->name ) )
{
std::string handleValue;
const char* textValue = (const char*)Util::findText( doc, valueNode );
if( textValue )
{
handleValue = textValue;
}
if( tagDimensions.find(valueName) == tagDimensions.end() )
{
tagDimensions[valueName] = 0;
}
else
{
tagDimensions[valueName]++;
}
unsigned int parseErrors = newValue.fromStr( handleValue, tagDimensions[valueName], errors );
if( parseErrors > 0 )
{
MString invalidValue( handleValue.c_str() );
MString invalidMember( (
const char*) valueNode->name );
REPORT_ERROR_AT_LINE2(kStreamXMLMemberValueInvalid, invalidValue, invalidMember, dataNode->line);
errorCount += parseErrors;
}
}
else
{
MString invalidMember( (
const char*) valueNode->name );
REPORT_ERROR_AT_LINE1(kStreamXMLMemberNameInvalid, invalidMember, dataNode->line);
errorCount--;
}
}
}
if( foundIndex )
{
if( ! newStream->
setElement( dataIndex, newValue ) )
{
REPORT_ERROR_AT_LINE(kStreamXMLSetValueFailed, dataNode->line);
errorCount--;
}
}
else
{
REPORT_ERROR_AT_LINE(kStreamXMLMissingIndex, dataNode->line);
}
}
}
return newStream;
}
int
StreamSerializerXML::write(
std::ostream& cDst,
std::string& errors ) const
{
errors = "";
cDst << xmlTagStreamIndent << "<"
<< xmlTagStream << ">" << std::endl;
cDst << xmlTagStreamDataIndent << "<"
<< xmlTagStreamName <<
">" << dataToWrite.
name() <<
"</" << xmlTagStreamName <<
">" << std::endl;
cDst << xmlTagStreamDataIndent << "<"
<< xmlTagStreamStructure <<
">" << dataToWrite.
structure().
name() <<
"</" << xmlTagStreamStructure <<
">" << std::endl;
cDst << xmlTagStreamDataIndent << "<"
<< xmlTagStreamIndexType <<
">" << dataToWrite.
indexType() <<
"</" << xmlTagStreamIndexType <<
">" << std::endl;
sIter != dataToWrite.
cend(); ++sIter )
{
cDst << xmlTagStreamDataIndent << "<" << xmlTagStreamData << ">" << std::endl;
cDst << xmlTagStreamDataValueIndent << "<" << xmlTagStreamDataIndex << ">"
<< theIndex.
asString() <<
"</" << xmlTagStreamDataIndex <<
">" << std::endl;
{
for( unsigned int dim=0; dim<structIt->length(); ++dim )
{
cDst << xmlTagStreamDataValueIndent << "<"
<< structIt->name()
<< ">"
<< "</" << structIt->name() << ">" << std::endl;
}
}
cDst << xmlTagStreamDataIndent << "</" << xmlTagStreamData << ">" << std::endl;
}
cDst << xmlTagStreamIndent << "</" << xmlTagStream << ">" << std::endl;
return 0;
}
void
StreamSerializerXML::getFormatDescription(
std::ostream& info ) const
{
}