Add method to convert QgsFieldDomain to OGR field domain

This commit is contained in:
Nyall Dawson 2022-01-28 14:43:50 +10:00
parent 44844bc736
commit 7db84789f8
3 changed files with 191 additions and 0 deletions

View File

@ -2123,4 +2123,108 @@ std::unique_ptr< QgsFieldDomain > QgsOgrUtils::convertFieldDomain( OGRFieldDomai
}
return res;
}
OGRFieldDomainH QgsOgrUtils::convertFieldDomain( const QgsFieldDomain *domain )
{
if ( !domain )
return nullptr;
OGRFieldType domainFieldType = OFTInteger;
OGRFieldSubType domainFieldSubType = OFSTNone;
variantTypeToOgrFieldType( domain->fieldType(), domainFieldType, domainFieldSubType );
OGRFieldDomainH res = nullptr;
switch ( domain->type() )
{
case Qgis::FieldDomainType::Coded:
{
std::vector< OGRCodedValue > enumeration;
const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
enumeration.reserve( values.size() );
for ( const QgsCodedValue &value : values )
{
OGRCodedValue codedValue;
codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
enumeration.push_back( codedValue );
}
OGRCodedValue last;
last.pszCode = nullptr;
last.pszValue = nullptr;
enumeration.push_back( last );
res = OGR_CodedFldDomain_Create(
domain->name().toUtf8().constData(),
domain->description().toUtf8().constData(),
domainFieldType,
domainFieldSubType,
enumeration.data()
);
for ( const OGRCodedValue &value : std::as_const( enumeration ) )
{
CPLFree( value.pszCode );
CPLFree( value.pszValue );
}
break;
}
case Qgis::FieldDomainType::Range:
{
std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum() );
std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum() );
res = OGR_RangeFldDomain_Create(
domain->name().toUtf8().constData(),
domain->description().toUtf8().constData(),
domainFieldType,
domainFieldSubType,
min.get(),
qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
max.get(),
qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
);
break;
}
case Qgis::FieldDomainType::Glob:
{
res = OGR_GlobFldDomain_Create(
domain->name().toUtf8().constData(),
domain->description().toUtf8().constData(),
domainFieldType,
domainFieldSubType,
qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
);
break;
}
}
switch ( domain->mergePolicy() )
{
case Qgis::FieldDomainMergePolicy::DefaultValue:
OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
break;
case Qgis::FieldDomainMergePolicy::GeometryWeighted:
OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
break;
case Qgis::FieldDomainMergePolicy::Sum:
OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
break;
}
switch ( domain->splitPolicy() )
{
case Qgis::FieldDomainSplitPolicy::DefaultValue:
OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
break;
case Qgis::FieldDomainSplitPolicy::GeometryRatio:
OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
break;
case Qgis::FieldDomainSplitPolicy::Duplicate:
OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
break;
}
return res;
}
#endif

View File

@ -407,6 +407,15 @@ class CORE_EXPORT QgsOgrUtils
* \since QGIS 3.26
*/
static std::unique_ptr< QgsFieldDomain > convertFieldDomain( OGRFieldDomainH domain );
/**
* Converts a QGIS field domain definition to an OGR field domain equivalent.
*
* \note Requires GDAL >= 3.3
* \note Not available in Python bindings
* \since QGIS 3.26
*/
static OGRFieldDomainH convertFieldDomain( const QgsFieldDomain *domain );
#endif
#endif
};

View File

@ -75,6 +75,7 @@ class TestQgsOgrUtils: public QObject
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
void testConvertFieldDomain();
void testConvertToFieldDomain();
#endif
private:
@ -1053,6 +1054,83 @@ void TestQgsOgrUtils::testConvertFieldDomain()
QCOMPARE( globDomain->fieldType(), QVariant::String );
OGR_FldDomain_Destroy( domain );
}
void TestQgsOgrUtils::testConvertToFieldDomain()
{
// test converting QgsFieldDomain to OGR field domain
QgsGlobFieldDomain globDomain( QStringLiteral( "name" ), QStringLiteral( "desc" ), QVariant::String, QStringLiteral( "*a*" ) );
OGRFieldDomainH domain = QgsOgrUtils::convertFieldDomain( &globDomain );
std::unique_ptr< QgsFieldDomain > res = QgsOgrUtils::convertFieldDomain( domain );
QCOMPARE( res->name(), QStringLiteral( "name" ) );
QCOMPARE( res->description(), QStringLiteral( "desc" ) );
QCOMPARE( res->splitPolicy(), Qgis::FieldDomainSplitPolicy::DefaultValue );
QCOMPARE( res->mergePolicy(), Qgis::FieldDomainMergePolicy::DefaultValue );
QCOMPARE( dynamic_cast< QgsGlobFieldDomain * >( res.get() )->glob(), QStringLiteral( "*a*" ) );
OGR_FldDomain_Destroy( domain );
globDomain.setSplitPolicy( Qgis::FieldDomainSplitPolicy::Duplicate );
globDomain.setMergePolicy( Qgis::FieldDomainMergePolicy::Sum );
domain = QgsOgrUtils::convertFieldDomain( &globDomain );
res = QgsOgrUtils::convertFieldDomain( domain );
OGR_FldDomain_Destroy( domain );
QCOMPARE( res->splitPolicy(), Qgis::FieldDomainSplitPolicy::Duplicate );
QCOMPARE( res->mergePolicy(), Qgis::FieldDomainMergePolicy::Sum );
globDomain.setSplitPolicy( Qgis::FieldDomainSplitPolicy::GeometryRatio );
globDomain.setMergePolicy( Qgis::FieldDomainMergePolicy::GeometryWeighted );
domain = QgsOgrUtils::convertFieldDomain( &globDomain );
res = QgsOgrUtils::convertFieldDomain( domain );
OGR_FldDomain_Destroy( domain );
QCOMPARE( res->splitPolicy(), Qgis::FieldDomainSplitPolicy::GeometryRatio );
QCOMPARE( res->mergePolicy(), Qgis::FieldDomainMergePolicy::GeometryWeighted );
// range
QgsRangeFieldDomain rangeDomain( QStringLiteral( "name" ), QStringLiteral( "desc" ), QVariant::Int,
1, true, 5, false );
domain = QgsOgrUtils::convertFieldDomain( &rangeDomain );
res = QgsOgrUtils::convertFieldDomain( domain );
OGR_FldDomain_Destroy( domain );
QCOMPARE( res->name(), QStringLiteral( "name" ) );
QCOMPARE( res->description(), QStringLiteral( "desc" ) );
QCOMPARE( dynamic_cast< QgsRangeFieldDomain * >( res.get() )->minimum(), QVariant( 1 ) );
QVERIFY( dynamic_cast< QgsRangeFieldDomain * >( res.get() )->minimumIsInclusive() );
QCOMPARE( dynamic_cast< QgsRangeFieldDomain * >( res.get() )->maximum(), QVariant( 5 ) );
QVERIFY( !dynamic_cast< QgsRangeFieldDomain * >( res.get() )->maximumIsInclusive() );
rangeDomain.setFieldType( QVariant::Double );
rangeDomain.setMinimum( 5.5 );
rangeDomain.setMaximum( 12.1 );
rangeDomain.setMinimumIsInclusive( false );
rangeDomain.setMaximumIsInclusive( true );
domain = QgsOgrUtils::convertFieldDomain( &rangeDomain );
res = QgsOgrUtils::convertFieldDomain( domain );
OGR_FldDomain_Destroy( domain );
QCOMPARE( dynamic_cast< QgsRangeFieldDomain * >( res.get() )->minimum(), QVariant( 5.5 ) );
QVERIFY( !dynamic_cast< QgsRangeFieldDomain * >( res.get() )->minimumIsInclusive() );
QCOMPARE( dynamic_cast< QgsRangeFieldDomain * >( res.get() )->maximum(), QVariant( 12.1 ) );
QVERIFY( dynamic_cast< QgsRangeFieldDomain * >( res.get() )->maximumIsInclusive() );
// coded
QgsCodedFieldDomain codedDomain( QStringLiteral( "name" ), QStringLiteral( "desc" ), QVariant::String,
{
QgsCodedValue( "aa", "aaaa" ),
QgsCodedValue( "bb", "bbbb" ),
} );
domain = QgsOgrUtils::convertFieldDomain( &codedDomain );
res = QgsOgrUtils::convertFieldDomain( domain );
OGR_FldDomain_Destroy( domain );
QCOMPARE( res->name(), QStringLiteral( "name" ) );
QCOMPARE( res->description(), QStringLiteral( "desc" ) );
QList< QgsCodedValue > resValues = dynamic_cast< QgsCodedFieldDomain * >( res.get() )->values();
QCOMPARE( resValues.size(), 2 );
QCOMPARE( resValues.at( 0 ).code(), QVariant( "aa" ) );
QCOMPARE( resValues.at( 0 ).value(), QStringLiteral( "aaaa" ) );
QCOMPARE( resValues.at( 1 ).code(), QVariant( "bb" ) );
QCOMPARE( resValues.at( 1 ).value(), QStringLiteral( "bbbb" ) );
}
#endif
QGSTEST_MAIN( TestQgsOgrUtils )