Caf::Pdm: Added better Error messages and Recovery when encountering unknown field names and class types

p4#: 21001
This commit is contained in:
Jacob Støren
2013-03-20 13:56:17 +01:00
parent d5b056b078
commit ad8cbfa651
2 changed files with 83 additions and 21 deletions

View File

@@ -19,6 +19,7 @@
#include "cafPdmObject.h"
#include <vector>
#include <iostream>
#include "cafPdmUiFieldEditorHandle.h"
namespace caf
@@ -226,26 +227,66 @@ template<typename DataType >
void caf::PdmField<DataType*>::readFieldData(QXmlStreamReader& xmlStream)
{
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
if (!xmlStream.isStartElement()) return; // Todo: Error handling
QString className = xmlStream.name().toString();
if (m_fieldValue.isNull())
if (!xmlStream.isStartElement())
{
m_fieldValue.setRawPtr(caf::PdmObjectFactory::instance()->create(className));
if (m_fieldValue.notNull())
{
m_fieldValue.rawPtr()->addParentField(this);
}
return; // This happens when the field is "shortcut" empty (written like: <ElementName/>)
}
if (m_fieldValue.isNull()) return; // Warning: Unknown className read
QString className = xmlStream.name().toString();
PdmObject* obj = NULL;
if (xmlStream.name() != m_fieldValue.rawPtr()->classKeyword()) return; // Error: Field contains different class type than on file
// Create an object if needed
if (m_fieldValue.isNull())
{
obj = caf::PdmObjectFactory::instance()->create(className);
m_fieldValue.rawPtr()->readFields(xmlStream);
if (obj == NULL)
{
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << this->keyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
else
{
if (dynamic_cast<DataType *>(obj) == NULL)
{
assert(false); // Inconsistency in the factory. It creates objects of wrong type from the ClassKeyword
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
m_fieldValue.setRawPtr(obj);
obj->addParentField(this);
}
}
else
{
obj = m_fieldValue.rawPtr();
}
if (className != obj->classKeyword())
{
// Error: Field contains different class type than on file
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << this->keyword().toLatin1().data() << std::endl;
std::cout << " Expected class name: " << obj->classKeyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
// Everything seems ok, so read the contents of the object:
obj->readFields(xmlStream);
// Make stream point to endElement of this field
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
@@ -540,8 +581,17 @@ template<typename DataType>
{
// Warning: Unknown className read
// Skip to corresponding end element
xmlStream.skipCurrentElement();
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << this->keyword().toLatin1().data() << std::endl;
// Skip to EndElement of the object
xmlStream.skipCurrentElement();
// Jump off the end element, and head for next start element (or the final EndElement of the field)
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
@@ -549,18 +599,24 @@ template<typename DataType>
if (currentObject == NULL)
{
// Warning: Inconsistency in factory !! Assert ?
// Skip to corresponding end element
assert(false); // There is an inconsistency in the factory. It creates objects of type not matching the ClassKeyword
// Skip to EndElement of the object
xmlStream.skipCurrentElement();
// Jump off the end element, and head for next start element (or the final EndElement of the field)
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
currentObject->readFields(xmlStream);
this->push_back(currentObject);
// Skip comments and for some reason: Characters. The last bit should not be correct,
// but Qt reports a character token between EndElement and StartElement
// Jump off the end element, and head for next start element (or the final EndElement of the field)
// Qt reports a character token between EndElements and StartElements so skip it
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();

View File

@@ -30,10 +30,10 @@ namespace caf
//--------------------------------------------------------------------------------------------------
/// Reads all the fields into this PdmObject
/// Assumes xmlStream points to the start element token of the containing object.
/// Assumes xmlStream points to the start element token of the PdmObject for which to read fields.
/// ( and not first token of object content)
/// This makes attribute based field storage possible.
/// Leaves the xmlStream pointing to the EndElement corresponding to the start element.
/// Leaves the xmlStream pointing to the EndElement of the PdmObject.
//--------------------------------------------------------------------------------------------------
void PdmObject::readFields (QXmlStreamReader& xmlStream )
{
@@ -48,6 +48,11 @@ void PdmObject::readFields (QXmlStreamReader& xmlStream )
case QXmlStreamReader::StartElement:
{
QString name = xmlStream.name().toString();
if (name == QString("SimpleObjPtrField"))
{
int a;
a = 2 + 7;
}
PdmFieldHandle* currentField = findField(name);
if (currentField)
{
@@ -76,6 +81,7 @@ void PdmObject::readFields (QXmlStreamReader& xmlStream )
case QXmlStreamReader::EndElement:
{
// End of object.
QString name = xmlStream.name().toString(); // For debugging
isObjectFinished = true;
}
break;