Skip to content

Commit

Permalink
Merge pull request #8159 from rldhont/server-wfs-enhance-describeFeat…
Browse files Browse the repository at this point in the history
…ureType-218

[Bugfix][Server] WFS: enhancing the way DescribeFeatureType response is build
  • Loading branch information
rldhont committed Oct 12, 2018
2 parents 942a560 + fde6d93 commit 85fdf4e
Showing 1 changed file with 156 additions and 169 deletions.
325 changes: 156 additions & 169 deletions src/server/qgswfsprojectparser.cpp
Expand Up @@ -22,6 +22,7 @@
#include "qgsvectordataprovider.h"
#include "qgsmapserviceexception.h"
#include "qgsaccesscontrol.h"
#include "qgsmessagelog.h"

QgsWFSProjectParser::QgsWFSProjectParser(
const QString& filePath
Expand Down Expand Up @@ -321,36 +322,18 @@ QSet<QString> QgsWFSProjectParser::wfstDeleteLayers() const

void QgsWFSProjectParser::describeFeatureType( const QString& aTypeName, QDomElement& parentElement, QDomDocument& doc ) const
{
const QList<QDomElement>& projectLayerElements = mProjectParser->projectLayerElements();
if ( projectLayerElements.size() < 1 )
{
return;
}

QStringList wfsLayersId = mProjectParser->wfsLayers();
QStringList typeNameList;
if ( aTypeName != "" )
if ( wfsLayersId.size() < 1 )
{
QStringList typeNameSplit = aTypeName.split( "," );
Q_FOREACH ( const QString &str, typeNameSplit )
{
if ( str.contains( ":" ) )
typeNameList << str.section( ":", 1, 1 );
else
typeNameList << str;
}
return;
}

Q_FOREACH ( const QDomElement &elem, projectLayerElements )
QList<QgsMapLayer*> layerList = mapLayerFromTypeName( aTypeName );
Q_FOREACH ( QgsMapLayer* currentLayer, layerList )
{
QString type = elem.attribute( "type" );
if ( type == "vector" )
QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer );
if ( layer && wfsLayersId.contains( layer->id() ) )
{
QgsMapLayer *mLayer = mProjectParser->createLayerFromElement( elem );
QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( mLayer );
if ( !layer )
continue;

#ifdef HAVE_SERVER_PYTHON_PLUGINS
if ( !mAccessControl->layerReadPermission( layer ) )
{
Expand All @@ -363,164 +346,161 @@ void QgsWFSProjectParser::describeFeatureType( const QString& aTypeName, QDomEle
typeName = layer->shortName();
typeName = typeName.replace( " ", "_" );

if ( wfsLayersId.contains( layer->id() ) && ( aTypeName == "" || typeNameList.contains( typeName ) ) )
//do a select with searchRect and go through all the features
QgsVectorDataProvider* provider = layer->dataProvider();
if ( !provider )
{
//do a select with searchRect and go through all the features
QgsVectorDataProvider* provider = layer->dataProvider();
if ( !provider )
{
continue;
}
continue;
}

//hidden attributes for this layer
const QSet<QString>& layerExcludedAttributes = layer->excludeAttributesWFS();
//hidden attributes for this layer
const QSet<QString>& layerExcludedAttributes = layer->excludeAttributesWFS();

//xsd:element
QDomElement elementElem = doc.createElement( "element"/*xsd:element*/ );
elementElem.setAttribute( "name", typeName );
elementElem.setAttribute( "type", "qgs:" + typeName + "Type" );
elementElem.setAttribute( "substitutionGroup", "gml:_Feature" );
parentElement.appendChild( elementElem );

//xsd:complexType
QDomElement complexTypeElem = doc.createElement( "complexType"/*xsd:complexType*/ );
complexTypeElem.setAttribute( "name", typeName + "Type" );
parentElement.appendChild( complexTypeElem );

//xsd:complexType
QDomElement complexContentElem = doc.createElement( "complexContent"/*xsd:complexContent*/ );
complexTypeElem.appendChild( complexContentElem );

//xsd:extension
QDomElement extensionElem = doc.createElement( "extension"/*xsd:extension*/ );
extensionElem.setAttribute( "base", "gml:AbstractFeatureType" );
complexContentElem.appendChild( extensionElem );

//xsd:sequence
QDomElement sequenceElem = doc.createElement( "sequence"/*xsd:sequence*/ );
extensionElem.appendChild( sequenceElem );
//xsd:element
QDomElement elementElem = doc.createElement( "element"/*xsd:element*/ );
elementElem.setAttribute( "name", typeName );
elementElem.setAttribute( "type", "qgs:" + typeName + "Type" );
elementElem.setAttribute( "substitutionGroup", "gml:_Feature" );
parentElement.appendChild( elementElem );

//xsd:element
if ( layer->hasGeometryType() )
//xsd:complexType
QDomElement complexTypeElem = doc.createElement( "complexType"/*xsd:complexType*/ );
complexTypeElem.setAttribute( "name", typeName + "Type" );
parentElement.appendChild( complexTypeElem );

//xsd:complexType
QDomElement complexContentElem = doc.createElement( "complexContent"/*xsd:complexContent*/ );
complexTypeElem.appendChild( complexContentElem );

//xsd:extension
QDomElement extensionElem = doc.createElement( "extension"/*xsd:extension*/ );
extensionElem.setAttribute( "base", "gml:AbstractFeatureType" );
complexContentElem.appendChild( extensionElem );

//xsd:sequence
QDomElement sequenceElem = doc.createElement( "sequence"/*xsd:sequence*/ );
extensionElem.appendChild( sequenceElem );

//xsd:element
if ( layer->hasGeometryType() )
{
QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ );
geomElem.setAttribute( "name", "geometry" );
if ( provider->name() == "ogr" )
{
QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ );
geomElem.setAttribute( "name", "geometry" );
if ( provider->name() == "ogr" )
{
// because some ogr drivers (e.g. ESRI ShapeFile, GML)
// are not able to determine the geometry type of a layer.
// we set to GeometryType
geomElem.setAttribute( "type", "gml:GeometryPropertyType" );
}
else
// because some ogr drivers (e.g. ESRI ShapeFile, GML)
// are not able to determine the geometry type of a layer.
// we set to GeometryType
geomElem.setAttribute( "type", "gml:GeometryPropertyType" );
}
else
{
QGis::WkbType wkbType = layer->wkbType();
switch ( wkbType )
{
QGis::WkbType wkbType = layer->wkbType();
switch ( wkbType )
{
case QGis::WKBPoint25D:
case QGis::WKBPoint:
geomElem.setAttribute( "type", "gml:PointPropertyType" );
break;
case QGis::WKBLineString25D:
case QGis::WKBLineString:
geomElem.setAttribute( "type", "gml:LineStringPropertyType" );
break;
case QGis::WKBPolygon25D:
case QGis::WKBPolygon:
geomElem.setAttribute( "type", "gml:PolygonPropertyType" );
break;
case QGis::WKBMultiPoint25D:
case QGis::WKBMultiPoint:
geomElem.setAttribute( "type", "gml:MultiPointPropertyType" );
break;
case QGis::WKBMultiLineString25D:
case QGis::WKBMultiLineString:
geomElem.setAttribute( "type", "gml:MultiLineStringPropertyType" );
break;
case QGis::WKBMultiPolygon25D:
case QGis::WKBMultiPolygon:
geomElem.setAttribute( "type", "gml:MultiPolygonPropertyType" );
break;
default:
geomElem.setAttribute( "type", "gml:GeometryPropertyType" );
break;
}
case QGis::WKBPoint25D:
case QGis::WKBPoint:
geomElem.setAttribute( "type", "gml:PointPropertyType" );
break;
case QGis::WKBLineString25D:
case QGis::WKBLineString:
geomElem.setAttribute( "type", "gml:LineStringPropertyType" );
break;
case QGis::WKBPolygon25D:
case QGis::WKBPolygon:
geomElem.setAttribute( "type", "gml:PolygonPropertyType" );
break;
case QGis::WKBMultiPoint25D:
case QGis::WKBMultiPoint:
geomElem.setAttribute( "type", "gml:MultiPointPropertyType" );
break;
case QGis::WKBMultiLineString25D:
case QGis::WKBMultiLineString:
geomElem.setAttribute( "type", "gml:MultiLineStringPropertyType" );
break;
case QGis::WKBMultiPolygon25D:
case QGis::WKBMultiPolygon:
geomElem.setAttribute( "type", "gml:MultiPolygonPropertyType" );
break;
default:
geomElem.setAttribute( "type", "gml:GeometryPropertyType" );
break;
}
geomElem.setAttribute( "minOccurs", "0" );
geomElem.setAttribute( "maxOccurs", "1" );
sequenceElem.appendChild( geomElem );
}
geomElem.setAttribute( "minOccurs", "0" );
geomElem.setAttribute( "maxOccurs", "1" );
sequenceElem.appendChild( geomElem );
}

//const QgsFields& fields = provider->fields();
const QgsFields& fields = layer->pendingFields();
for ( int idx = 0; idx < fields.count(); ++idx )
//const QgsFields& fields = provider->fields();
const QgsFields& fields = layer->pendingFields();
for ( int idx = 0; idx < fields.count(); ++idx )
{
const QgsField field = fields.at( idx );
QString attributeName = field.name();
//skip attribute if excluded from WFS publication
if ( layerExcludedAttributes.contains( attributeName ) )
{
const QgsField field = fields.at( idx );
QString attributeName = field.name();
//skip attribute if excluded from WFS publication
if ( layerExcludedAttributes.contains( attributeName ) )
{
continue;
}
continue;
}

//xsd:element
QDomElement attElem = doc.createElement( "element"/*xsd:element*/ );
attElem.setAttribute( "name", attributeName.replace( " ", "_" ).replace( mCleanTagNameRegExp, "" ) );
QVariant::Type attributeType = field.type();
if ( attributeType == QVariant::Int )
{
attElem.setAttribute( "type", "int" );
}
else if ( attributeType == QVariant::UInt )
{
attElem.setAttribute( "type", "unsignedInt" );
}
else if ( attributeType == QVariant::LongLong )
{
attElem.setAttribute( "type", "long" );
}
else if ( attributeType == QVariant::ULongLong )
{
attElem.setAttribute( "type", "unsignedLong" );
}
else if ( attributeType == QVariant::Double )
{
// if the size is well known, it may be an integer
// else a decimal
// in sqlite the length is unknown but int type can be used
if ( field.length() != 0 && field.precision() == 0 )
attElem.setAttribute( "type", "integer" );
else
attElem.setAttribute( "type", "decimal" );
}
else if ( attributeType == QVariant::Bool )
{
attElem.setAttribute( "type", "boolean" );
}
else if ( attributeType == QVariant::Date )
{
attElem.setAttribute( "type", "date" );
}
else if ( attributeType == QVariant::Time )
{
attElem.setAttribute( "type", "time" );
}
else if ( attributeType == QVariant::DateTime )
{
attElem.setAttribute( "type", "dateTime" );
}
//xsd:element
QDomElement attElem = doc.createElement( "element"/*xsd:element*/ );
attElem.setAttribute( "name", attributeName.replace( " ", "_" ).replace( mCleanTagNameRegExp, "" ) );
QVariant::Type attributeType = field.type();
if ( attributeType == QVariant::Int )
{
attElem.setAttribute( "type", "int" );
}
else if ( attributeType == QVariant::UInt )
{
attElem.setAttribute( "type", "unsignedInt" );
}
else if ( attributeType == QVariant::LongLong )
{
attElem.setAttribute( "type", "long" );
}
else if ( attributeType == QVariant::ULongLong )
{
attElem.setAttribute( "type", "unsignedLong" );
}
else if ( attributeType == QVariant::Double )
{
// if the size is well known, it may be an integer
// else a decimal
// in sqlite the length is unknown but int type can be used
if ( field.length() != 0 && field.precision() == 0 )
attElem.setAttribute( "type", "integer" );
else
{
attElem.setAttribute( "type", "string" );
}
attElem.setAttribute( "type", "decimal" );
}
else if ( attributeType == QVariant::Bool )
{
attElem.setAttribute( "type", "boolean" );
}
else if ( attributeType == QVariant::Date )
{
attElem.setAttribute( "type", "date" );
}
else if ( attributeType == QVariant::Time )
{
attElem.setAttribute( "type", "time" );
}
else if ( attributeType == QVariant::DateTime )
{
attElem.setAttribute( "type", "dateTime" );
}
else
{
attElem.setAttribute( "type", "string" );
}

sequenceElem.appendChild( attElem );
sequenceElem.appendChild( attElem );

QString alias = field.alias();
if ( !alias.isEmpty() )
{
attElem.setAttribute( "alias", alias );
}
QString alias = field.alias();
if ( !alias.isEmpty() )
{
attElem.setAttribute( "alias", alias );
}
}
}
Expand Down Expand Up @@ -575,10 +555,15 @@ QList<QgsMapLayer*> QgsWFSProjectParser::mapLayerFromTypeName( const QString& aT
{
return layerList;
}

QStringList wfsLayersId = wfsLayers();
if ( wfsLayersId.size() < 1 )
{
return layerList;
}

QStringList typeNameList;
if ( aTypeName != "" )
if ( !aTypeName.isEmpty() )
{
QStringList typeNameSplit = aTypeName.split( "," );
Q_FOREACH ( const QString &str, typeNameSplit )
Expand Down Expand Up @@ -613,6 +598,8 @@ QList<QgsMapLayer*> QgsWFSProjectParser::mapLayerFromTypeName( const QString& aT
continue;

layerList.push_back( mLayer );
if ( !aTypeName.isEmpty() && typeNameList.count() == layerList.count() )
break;
}
}
return layerList;
Expand Down

0 comments on commit 85fdf4e

Please sign in to comment.