Torque3D Documentation / _generateds / tamlXmlWriter.cpp

tamlXmlWriter.cpp

Engine/source/persistence/taml/xml/tamlXmlWriter.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2013 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "persistence/taml/xml/tamlXmlWriter.h"
 25
 26// Debug Profiling.
 27#include "platform/profiler.h"
 28#include "persistence/taml/fsTinyXml.h"
 29
 30//-----------------------------------------------------------------------------
 31
 32bool TamlXmlWriter::write( FileStream& stream, const TamlWriteNode* pTamlWriteNode )
 33{
 34    // Debug Profiling.
 35    PROFILE_SCOPE(TamlXmlWriter_Write);
 36
 37    // Create document.
 38    fsTiXmlDocument xmlDocument;
 39
 40    // Compile the root element.
 41    TiXmlElement* pRootElement = compileElement( pTamlWriteNode );
 42
 43    // Fetch any TAML Schema file reference.
 44    const char* pTamlSchemaFile = Con::getVariable( TAML_SCHEMA_VARIABLE );
 45
 46    // Do we have a schema file reference?
 47    if ( pTamlSchemaFile != NULL && *pTamlSchemaFile != 0 )
 48    {
 49        // Yes, so add namespace attribute to root.
 50        pRootElement->SetAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
 51
 52        // Expand the file-path reference.
 53        char schemaFilePathBuffer[1024];
 54        Con::expandToolScriptFilename( schemaFilePathBuffer, sizeof(schemaFilePathBuffer), pTamlSchemaFile );
 55
 56        // Fetch the output path for the Taml file.
 57        char outputFileBuffer[1024];
 58        dSprintf( outputFileBuffer, sizeof(outputFileBuffer), "%s", mpTaml->getFilePathBuffer() );
 59        char* pFileStart = dStrrchr( outputFileBuffer, '/' );
 60        if ( pFileStart == NULL )
 61            *outputFileBuffer = 0;
 62        else
 63            *pFileStart = 0;
 64
 65        // Fetch the schema file-path relative to the output file.
 66        StringTableEntry relativeSchemaFilePath = Platform::makeRelativePathName( schemaFilePathBuffer, outputFileBuffer );
 67
 68        // Add schema location attribute to root.
 69        pRootElement->SetAttribute( "xsi:noNamespaceSchemaLocation", relativeSchemaFilePath );
 70    }
 71
 72    // Link the root element.
 73    xmlDocument.LinkEndChild( pRootElement );
 74
 75    // Save document to stream.
 76    return xmlDocument.SaveFile( stream );
 77}
 78
 79//-----------------------------------------------------------------------------
 80
 81TiXmlElement* TamlXmlWriter::compileElement( const TamlWriteNode* pTamlWriteNode )
 82{
 83    // Debug Profiling.
 84    PROFILE_SCOPE(TamlXmlWriter_CompileElement);
 85
 86    // Fetch object.
 87    SimObject* pSimObject = pTamlWriteNode->mpSimObject;
 88
 89    // Fetch element name.
 90    const char* pElementName = pSimObject->getClassName();
 91
 92    // Create element.
 93    TiXmlElement* pElement = new fsTiXmlElement( pElementName );
 94
 95    // Fetch reference Id.
 96    const U32 referenceId = pTamlWriteNode->mRefId;
 97
 98    // Do we have a reference Id?
 99    if ( referenceId != 0 )
100    {
101        // Yes, so set reference Id attribute.
102        pElement->SetAttribute( tamlRefIdName, referenceId );
103    }
104
105    // Do we have a reference to node?
106    else if ( pTamlWriteNode->mRefToNode != NULL )
107    {
108        // Yes, so fetch reference to Id.
109        const U32 referenceToId = pTamlWriteNode->mRefToNode->mRefId;
110
111        // Sanity!
112        AssertFatal( referenceToId != 0, "Taml: Invalid reference to Id." );
113
114        // Set reference to Id attribute.
115        pElement->SetAttribute( tamlRefToIdName, referenceToId );
116
117        // Finish because we're a reference to another object.
118        return pElement;
119    }
120
121    // Fetch object name.
122    const char* pObjectName = pTamlWriteNode->mpObjectName;
123
124    // Do we have a name?
125    if ( pObjectName != NULL )
126    {
127        // Yes, so set name attribute.
128        pElement->SetAttribute( tamlNamedObjectName, pObjectName );
129    }
130
131    // Compile attributes.
132    compileAttributes( pElement, pTamlWriteNode );
133
134    // Fetch children.
135    Vector<TamlWriteNode*>* pChildren = pTamlWriteNode->mChildren;
136
137    // Do we have any children?
138    if ( pChildren )
139    {
140        // Yes, so iterate children.
141        for( Vector<TamlWriteNode*>::iterator itr = pChildren->begin(); itr != pChildren->end(); ++itr )
142        {
143            // Write child element.
144            pElement->LinkEndChild( compileElement( (*itr) ) );
145        }
146    }
147
148    // Compile custom elements.
149    compileCustomElements( pElement, pTamlWriteNode );
150
151    return pElement;
152}
153
154//-----------------------------------------------------------------------------
155
156void TamlXmlWriter::compileAttributes( TiXmlElement* pXmlElement, const TamlWriteNode* pTamlWriteNode )
157{
158    // Debug Profiling.
159    PROFILE_SCOPE(TamlXmlWriter_CompileAttributes);
160
161    // Fetch fields.
162    const Vector<TamlWriteNode::FieldValuePair*>& fields = pTamlWriteNode->mFields;
163
164    // Ignore if no fields.
165    if ( fields.size() == 0 )
166        return;
167
168    // Iterate fields.
169    for( Vector<TamlWriteNode::FieldValuePair*>::const_iterator itr = fields.begin(); itr != fields.end(); ++itr )
170    {
171        // Fetch field/value pair.
172        TamlWriteNode::FieldValuePair* pFieldValue = (*itr);
173
174        // Set field attribute.
175        pXmlElement->SetAttribute( pFieldValue->mName, pFieldValue->mpValue );
176    }
177}
178
179//-----------------------------------------------------------------------------
180
181void TamlXmlWriter::compileCustomElements( TiXmlElement* pXmlElement, const TamlWriteNode* pTamlWriteNode )
182{
183    // Debug Profiling.
184    PROFILE_SCOPE(TamlXmlWriter_CompileCustomElements);
185
186    // Fetch custom nodes.
187    const TamlCustomNodes& customNodes = pTamlWriteNode->mCustomNodes;
188
189    // Fetch custom nodes.
190    const TamlCustomNodeVector& nodes = customNodes.getNodes();
191
192    // Finish if no custom nodes to process.
193    if ( nodes.size() == 0 )
194        return;
195
196    // Iterate custom nodes.
197    for( TamlCustomNodeVector::const_iterator customNodesItr = nodes.begin(); customNodesItr != nodes.end(); ++customNodesItr )
198    {
199        // Fetch the custom node.
200        TamlCustomNode* pCustomNode = *customNodesItr;
201
202        // Format extended element name.
203        char extendedElementNameBuffer[256];
204        dSprintf( extendedElementNameBuffer, sizeof(extendedElementNameBuffer), "%s.%s", pXmlElement->Value(), pCustomNode->getNodeName() );
205        StringTableEntry extendedElementName = StringTable->insert( extendedElementNameBuffer );
206
207        // Create element.
208        TiXmlElement* pExtendedPropertyElement = new fsTiXmlElement( extendedElementName );
209
210        // Fetch node children.
211        const TamlCustomNodeVector& nodeChildren = pCustomNode->getChildren();
212
213        // Iterate children nodes.
214        for( TamlCustomNodeVector::const_iterator childNodeItr = nodeChildren.begin(); childNodeItr != nodeChildren.end(); ++childNodeItr )
215        {
216            // Fetch child node.
217            const TamlCustomNode* pChildNode = *childNodeItr;
218
219            // Compile the custom node.
220            compileCustomNode( pExtendedPropertyElement, pChildNode );
221        }
222
223        // Finish if the node is set to ignore if empty and it is empty.
224        if ( pCustomNode->getIgnoreEmpty() && pExtendedPropertyElement->NoChildren() )
225        {
226            // Yes, so delete the extended element.
227            delete pExtendedPropertyElement;
228            pExtendedPropertyElement = NULL;
229        }
230        else
231        {
232            // No, so add elementt as child.
233            pXmlElement->LinkEndChild( pExtendedPropertyElement );
234        }
235    }
236}
237
238//-----------------------------------------------------------------------------
239
240void TamlXmlWriter::compileCustomNode( TiXmlElement* pXmlElement, const TamlCustomNode* pCustomNode )
241{
242    // Finish if the node is set to ignore if empty and it is empty.
243    if ( pCustomNode->getIgnoreEmpty() && pCustomNode->isEmpty() )
244        return;
245
246    // Is the node a proxy object?
247    if ( pCustomNode->isProxyObject() )
248    {
249        // Yes, so write the proxy object.
250        pXmlElement->LinkEndChild( compileElement( pCustomNode->getProxyWriteNode() ) );
251        return;
252    }
253
254    // Create element.
255    TiXmlElement* pNodeElement = new fsTiXmlElement( pCustomNode->getNodeName() );
256
257    // Is there any node text?
258    if ( !pCustomNode->getNodeTextField().isValueEmpty() )
259    {
260        // Yes, so add a text node.
261        pNodeElement->LinkEndChild( new TiXmlText( pCustomNode->getNodeTextField().getFieldValue() ) );
262    }
263
264    // Fetch fields.
265    const TamlCustomFieldVector& fields = pCustomNode->getFields();
266
267    // Iterate fields.
268    for ( TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr )
269    {
270        // Fetch field.
271        const TamlCustomField* pField = *fieldItr;
272
273        // Set field.
274        pNodeElement->SetAttribute( pField->getFieldName(), pField->getFieldValue() );
275    }
276
277    // Fetch node children.
278    const TamlCustomNodeVector& nodeChildren = pCustomNode->getChildren();
279
280    // Iterate children nodes.
281    for( TamlCustomNodeVector::const_iterator childNodeItr = nodeChildren.begin(); childNodeItr != nodeChildren.end(); ++childNodeItr )
282    {
283        // Fetch child node.
284        const TamlCustomNode* pChildNode = *childNodeItr;
285
286        // Compile the child node.
287        compileCustomNode( pNodeElement, pChildNode );
288    }
289
290    // Finish if the node is set to ignore if empty and it is empty (including fields).
291    if ( pCustomNode->getIgnoreEmpty() && fields.size() == 0 && pNodeElement->NoChildren() )
292    {
293        // Yes, so delete the extended element.
294        delete pNodeElement;
295        pNodeElement = NULL;
296    }
297    else
298    {
299        // Add node element as child.
300        pXmlElement->LinkEndChild( pNodeElement );
301    }
302}
303