#8197 AppEnum : Add alias list to support backwards compatibility

This commit is contained in:
Magne Sjaastad 2021-10-27 08:37:31 +02:00
parent c81f6b44db
commit e1dea1d34d
2 changed files with 76 additions and 19 deletions

View File

@ -36,9 +36,12 @@
#pragma once
#include "cafAssert.h"
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <vector>
namespace caf
@ -155,9 +158,9 @@ private:
/// method. It may also set a default value using \m setDefault
//==================================================================================================
static void setUp();
static void addItem( T enumVal, const QString& text, const QString& uiText )
static void addItem( T enumVal, const QString& text, const QString& uiText, const QStringList& aliases = {} )
{
EnumMapper::instance()->addItem( enumVal, text, uiText );
EnumMapper::instance()->addItem( enumVal, text, uiText, aliases );
}
static void setDefault( T defaultEnumValue ) { EnumMapper::instance()->setDefault( defaultEnumValue ); }
@ -174,27 +177,40 @@ private:
class EnumMapper
{
private:
struct Triplet
class EnumData
{
Triplet( T enumVal, const QString& text, QString uiText )
public:
EnumData( T enumVal, const QString& text, const QString& uiText, const QStringList& aliases )
: m_enumVal( enumVal )
, m_text( text )
, m_uiText( uiText )
, m_aliases( aliases )
{
}
T m_enumVal;
QString m_text;
QString m_uiText;
bool isMatching( const QString& text ) const { return ( text == m_text || m_aliases.contains( text ) ); }
T m_enumVal;
QString m_text;
QString m_uiText;
QStringList m_aliases;
};
public:
void addItem( T enumVal, const QString& text, QString uiText )
void addItem( T enumVal, const QString& text, QString uiText, const QStringList& aliases )
{
// Make sure the text is trimmed, as this text is streamed to XML and will be trimmed when read back from
// XML text
// https://github.com/OPM/ResInsight/issues/7829
instance()->m_mapping.push_back( Triplet( enumVal, text.trimmed(), uiText ) );
// Make sure the alias text is unique for enum
for ( const auto& alias : aliases )
{
for ( const auto& enumData : instance()->m_mapping )
{
CAF_ASSERT( !enumData.isMatching( alias ) );
}
}
// Make sure the text is trimmed, as this text is streamed to XML and will be trimmed when read back
// from XML text https://github.com/OPM/ResInsight/issues/7829
instance()->m_mapping.push_back( EnumData( enumVal, text.trimmed(), uiText, aliases ) );
}
static EnumMapper* instance()
@ -244,12 +260,14 @@ private:
bool enumVal( T& value, const QString& text ) const
{
value = defaultValue();
size_t idx;
for ( idx = 0; idx < m_mapping.size(); ++idx )
QString trimmedText = text.trimmed();
for ( size_t idx = 0; idx < m_mapping.size(); ++idx )
{
// Make sure the text parsed from a text stream is trimmed
// https://github.com/OPM/ResInsight/issues/7829
if ( text.trimmed() == m_mapping[idx].m_text )
if ( m_mapping[idx].isMatching( trimmedText ) )
{
value = m_mapping[idx].m_enumVal;
return true;
@ -320,9 +338,9 @@ private:
friend class AppEnum<T>;
std::vector<Triplet> m_mapping;
T m_defaultValue;
bool m_defaultValueIsSet;
std::vector<EnumData> m_mapping;
T m_defaultValue;
bool m_defaultValueIsSet;
};
};

View File

@ -13,6 +13,7 @@
#include "cafPdmXmlObjectHandle.h"
#include "cafPdmXmlObjectHandleMacros.h"
#include <QStringList>
#include <QXmlStreamWriter>
class DemoPdmObject : public caf::PdmObjectHandle, public caf::PdmXmlObjectHandle
@ -39,6 +40,8 @@ public:
m_proxyEnumField.registerSetMethod( this, &DemoPdmObject::setEnumMember );
m_proxyEnumField.registerGetMethod( this, &DemoPdmObject::enumMember );
m_enumMember = T1;
CAF_PDM_XML_InitField( &m_appEnumField, "NativeAppEnum" );
}
~DemoPdmObject() {}
@ -47,6 +50,7 @@ public:
caf::PdmProxyValueField<double> m_proxyDoubleField;
caf::PdmProxyValueField<caf::AppEnum<TestEnumType>> m_proxyEnumField;
caf::PdmDataValueField<caf::AppEnum<TestEnumType>> m_appEnumField;
private:
void setDoubleMember( const double& d )
@ -75,8 +79,12 @@ template <>
void AppEnum<DemoPdmObject::TestEnumType>::setUp()
{
addItem( DemoPdmObject::T1, "T1", "An A letter" );
addItem( DemoPdmObject::T2, "T2", "A B letter" );
addItem( DemoPdmObject::T2, "T2", "A B letter", QStringList( { "T2_a", "T2_b" } ) );
addItem( DemoPdmObject::T3, "T3", "A B letter" );
// Use the following line to test the CAF_ASSERT that should trigger when equal alias texts are defined
// addItem( DemoPdmObject::T3, "T3", "A B letter", QStringList( { "T2_a", "T2_b" } ) );
setDefault( DemoPdmObject::T1 );
}
@ -437,3 +445,34 @@ TEST( BaseTest, TestDataType )
delete s1;
}
#endif
TEST( BaseTest, AppEnumAlias )
{
{
auto* obj2 = new DemoPdmObject;
EXPECT_TRUE( obj2->m_appEnumField() == DemoPdmObject::TestEnumType::T1 );
QString xmlText = "<DemoPdmObject>"
"<BigNumber>0</BigNumber>"
"<AppEnum>T2</AppEnum>"
"<NativeAppEnum>T2_a</NativeAppEnum>"
"</DemoPdmObject>";
obj2->readObjectFromXmlString( xmlText, caf::PdmDefaultObjectFactory::instance() );
EXPECT_TRUE( obj2->m_appEnumField() == DemoPdmObject::TestEnumType::T2 );
}
{
auto* obj2 = new DemoPdmObject;
EXPECT_TRUE( obj2->m_appEnumField() == DemoPdmObject::TestEnumType::T1 );
QString xmlText = "<DemoPdmObject>"
"<BigNumber>0</BigNumber>"
"<AppEnum>T2</AppEnum>"
"<NativeAppEnum>T2_b</NativeAppEnum>"
"</DemoPdmObject>";
obj2->readObjectFromXmlString( xmlText, caf::PdmDefaultObjectFactory::instance() );
EXPECT_TRUE( obj2->m_appEnumField() == DemoPdmObject::TestEnumType::T2 );
}
}