Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Server] Define QgsWms::QgsRenderer::dimensionFilter method
  • Loading branch information
rldhont committed Sep 13, 2019
1 parent 1e4df22 commit ea0c174
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 160 deletions.
330 changes: 170 additions & 160 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -2749,200 +2749,210 @@ namespace QgsWms
filteredLayer->setSubsetString( newSubsetString );
}
}
// WMS Dimension filters
const QList<QgsVectorLayerServerProperties::WmsDimensionInfo> wmsDims = filteredLayer->serverProperties()->wmsDimensions();
if ( !wmsDims.isEmpty() )

expList.append( dimensionFilter( filteredLayer ) );

// Join and apply expressions provided by OGC filter and Dimensions
QString exp;
if ( expList.size() == 1 )
{
QMap<QString, QString> dimParamValues = mContext.parameters().dimensionValues();
for ( const QgsVectorLayerServerProperties::WmsDimensionInfo &dim : wmsDims )
exp = expList[0];
}
else if ( expList.size() > 1 )
{
exp = QStringLiteral( "( %1 )" ).arg( expList.join( QStringLiteral( " ) AND ( " ) ) );
}
if ( !exp.isEmpty() )
{
std::unique_ptr<QgsExpression> expression( new QgsExpression( exp ) );
if ( expression )
{
// Check field index
int fieldIndex = filteredLayer->fields().indexOf( dim.fieldName );
if ( fieldIndex == -1 )
mFeatureFilter.setFilter( filteredLayer, *expression );
}
}
}
}

QStringList QgsRenderer::dimensionFilter( QgsVectorLayer *layer ) const
{
QStringList expList;
// WMS Dimension filters
const QList<QgsVectorLayerServerProperties::WmsDimensionInfo> wmsDims = layer->serverProperties()->wmsDimensions();
if ( wmsDims.isEmpty() )
{
return expList;
}

QMap<QString, QString> dimParamValues = mContext.parameters().dimensionValues();
for ( const QgsVectorLayerServerProperties::WmsDimensionInfo &dim : wmsDims )
{
// Check field index
int fieldIndex = layer->fields().indexOf( dim.fieldName );
if ( fieldIndex == -1 )
{
continue;
}
// Check end field index
int endFieldIndex = -1;
if ( !dim.endFieldName.isEmpty() )
{
endFieldIndex = layer->fields().indexOf( dim.endFieldName );
if ( endFieldIndex == -1 )
{
continue;
}
}
// Apply dimension filtering
if ( !dimParamValues.contains( dim.name.toUpper() ) )
{
// Default value based on type configured by user
QVariant defValue;
if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::AllValues )
{
continue; // no filter by default for this dimension
}
else if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::ReferenceValue )
{
defValue = dim.referenceValue;
}
else
{
// get unique values
QSet<QVariant> uniqueValues = layer->uniqueValues( fieldIndex );
if ( endFieldIndex != -1 )
{
continue;
uniqueValues.unite( layer->uniqueValues( endFieldIndex ) );
}
// Check end field index
int endFieldIndex = -1;
if ( !dim.endFieldName.isEmpty() )
// sort unique values
QList<QVariant> values = uniqueValues.toList();
std::sort( values.begin(), values.end() );
if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::MinValue )
{
endFieldIndex = filteredLayer->fields().indexOf( dim.endFieldName );
if ( endFieldIndex == -1 )
{
continue;
}
defValue = values.first();
}
else if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::MaxValue )
{
defValue = values.last();
}
}
// build expression
if ( endFieldIndex == -1 )
{
expList << QgsExpression::createFieldEqualityExpression( dim.fieldName, defValue );
}
else
{
QStringList expElems;
expElems << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( defValue )
<< QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( defValue );
expList << expElems.join( ' ' );
}
}
else
{
// Get field to convert value provided in parameters
QgsField dimField = layer->fields().at( fieldIndex );
// Value provided in parameters
QString dimParamValue = dimParamValues[dim.name.toUpper()];
// The expression list for this dimension
QStringList dimExplist;
// Multiple values are separated by ,
QStringList dimValues = dimParamValue.split( ',' );
for ( int i = 0; i < dimValues.size(); ++i )
{
QString dimValue = dimValues[i];
// Trim value if necessary
if ( dimValue.size() > 1 )
{
dimValue = dimValue.trimmed();
}
// Apply dimension filtering
if ( !dimParamValues.contains( dim.name.toUpper() ) )
// Range value is separated by / for example 0/1
if ( dimValue.contains( '/' ) )
{
// Default value based on type configured by user
QVariant defValue;
if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::AllValues )
QStringList rangeValues = dimValue.split( '/' );
// Check range value size
if ( rangeValues.size() != 2 )
{
continue; // no filter by default for this dimension
continue; // throw an error
}
else if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::ReferenceValue )
// Get range values
QVariant rangeMin = QVariant( rangeValues[0] );
QVariant rangeMax = QVariant( rangeValues[1] );
// Convert and check range values
if ( !dimField.convertCompatible( rangeMin ) )
{
defValue = dim.referenceValue;
continue; // throw an error
}
else
if ( !dimField.convertCompatible( rangeMax ) )
{
// get unique values
QSet<QVariant> uniqueValues = filteredLayer->uniqueValues( fieldIndex );
if ( endFieldIndex != -1 )
{
uniqueValues.unite( filteredLayer->uniqueValues( endFieldIndex ) );
}
// sort unique values
QList<QVariant> values = uniqueValues.toList();
std::sort( values.begin(), values.end() );
if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::MinValue )
{
defValue = values.first();
}
else if ( dim.defaultDisplayType == QgsVectorLayerServerProperties::WmsDimensionInfo::MaxValue )
{
defValue = values.last();
}
continue; // throw an error
}
// build expression
// Build expression for this range
QStringList expElems;
if ( endFieldIndex == -1 )
{
expList << QgsExpression::createFieldEqualityExpression( dim.fieldName, defValue );
// The field values are between min and max range
expElems << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
<< QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax );
}
else
{
QStringList expElems;
expElems << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( defValue )
<< QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( defValue );
expList << expElems.join( ' ' );
// The start field or the end field are lesser than min range
// or the start field or the end field are greater than min range
expElems << QStringLiteral( "(" ) << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
<< QStringLiteral( "OR" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
<< QStringLiteral( ") AND (" ) << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax )
<< QStringLiteral( "OR" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax )
<< QStringLiteral( ")" );
}
dimExplist << expElems.join( ' ' );
}
else
{
// Get field to convert value provided in parameters
QgsField dimField = filteredLayer->fields().at( fieldIndex );
// Value provided in parameters
QString dimParamValue = dimParamValues[dim.name.toUpper()];
// The expression list for this dimension
QStringList dimExplist;
// Multiple values are separated by ,
QStringList dimValues = dimParamValue.split( ',' );
for ( int i = 0; i < dimValues.size(); ++i )
QVariant dimVariant = QVariant( dimValue );
if ( !dimField.convertCompatible( dimVariant ) )
{
QString dimValue = dimValues[i];
// Trim value if necessary
if ( dimValue.size() > 1 )
{
dimValue = dimValue.trimmed();
}
// Range value is separated by / for example 0/1
if ( dimValue.contains( '/' ) )
{
QStringList rangeValues = dimValue.split( '/' );
// Check range value size
if ( rangeValues.size() != 2 )
{
continue; // throw an error
}
// Get range values
QVariant rangeMin = QVariant( rangeValues[0] );
QVariant rangeMax = QVariant( rangeValues[1] );
// Convert and check range values
if ( !dimField.convertCompatible( rangeMin ) )
{
continue; // throw an error
}
if ( !dimField.convertCompatible( rangeMax ) )
{
continue; // throw an error
}
// Build expression for this range
QStringList expElems;
if ( endFieldIndex == -1 )
{
// The field values are between min and max range
expElems << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
<< QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax );
}
else
{
// The start field or the end field are lesser than min range
// or the start field or the end field are greater than min range
expElems << QStringLiteral( "(" ) << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
<< QStringLiteral( "OR" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
<< QStringLiteral( ") AND (" ) << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax )
<< QStringLiteral( "OR" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax )
<< QStringLiteral( ")" );
}
dimExplist << expElems.join( ' ' );
}
else
{
QVariant dimVariant = QVariant( dimValue );
if ( !dimField.convertCompatible( dimVariant ) )
{
continue; // throw an error
}
// Build expression for this value
if ( endFieldIndex == -1 )
{
// Field is equal to
dimExplist << QgsExpression::createFieldEqualityExpression( dim.fieldName, dimVariant );
}
else
{
// The start field is lesser or equal to
// and the end field is greater or equal to
QStringList expElems;
expElems << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( dimVariant )
<< QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( dimVariant );
dimExplist << expElems.join( ' ' );
}
}
continue; // throw an error
}
// Build the expression for this dimension
if ( dimExplist.size() == 1 )
// Build expression for this value
if ( endFieldIndex == -1 )
{
expList << dimExplist;
// Field is equal to
dimExplist << QgsExpression::createFieldEqualityExpression( dim.fieldName, dimVariant );
}
else if ( dimExplist.size() > 1 )
else
{
expList << QStringLiteral( "( %1 )" ).arg( dimExplist.join( QStringLiteral( " ) OR ( " ) ) );
// The start field is lesser or equal to
// and the end field is greater or equal to
QStringList expElems;
expElems << QgsExpression::quotedColumnRef( dim.fieldName )
<< QStringLiteral( "<=" ) << QgsExpression::quotedValue( dimVariant )
<< QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
<< QStringLiteral( ">=" ) << QgsExpression::quotedValue( dimVariant );
dimExplist << expElems.join( ' ' );
}
}
}
}

// Join and apply expressions provided by OGC filter and Dimensions
QString exp;
if ( expList.size() == 1 )
{
exp = expList[0];
}
else if ( expList.size() > 1 )
{
exp = QStringLiteral( "( %1 )" ).arg( expList.join( QStringLiteral( " ) AND ( " ) ) );
}
if ( !exp.isEmpty() )
{
std::unique_ptr<QgsExpression> expression( new QgsExpression( exp ) );
if ( expression )
// Build the expression for this dimension
if ( dimExplist.size() == 1 )
{
mFeatureFilter.setFilter( filteredLayer, *expression );
expList << dimExplist;
}
else if ( dimExplist.size() > 1 )
{
expList << QStringLiteral( "( %1 )" ).arg( dimExplist.join( QStringLiteral( " ) OR ( " ) ) );
}
}
}
return expList;
}

void QgsRenderer::setLayerSelection( QgsMapLayer *layer, const QStringList &fids ) const
Expand Down
2 changes: 2 additions & 0 deletions src/server/services/wms/qgswmsrenderer.h
Expand Up @@ -149,6 +149,8 @@ namespace QgsWms
// Set layer filter and dimension
void setLayerFilter( QgsMapLayer *layer, const QList<QgsWmsParametersFilter> &filters );

QStringList dimensionFilter( QgsVectorLayer *layer ) const;

// Set layer python filter
void setLayerAccessControlFilter( QgsMapLayer *layer ) const;

Expand Down

0 comments on commit ea0c174

Please sign in to comment.