mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-28 00:05:04 -04:00
Merge pull request #4344 from rldhont/server-wfs-configparser
[Server] WFS refactoring and QgsWfsProjectParser removal
This commit is contained in:
commit
cc55ae1932
python/server
src/server
CMakeLists.txtqgsconfigcache.cppqgsconfigcache.hqgsserverprojectutils.cppqgsserverprojectutils.hqgswfsprojectparser.cppqgswfsprojectparser.h
services/wfs
tests
src/python
testdata/qgis_server
@ -32,7 +32,6 @@ class QgsConfigCache: QObject
|
|||||||
~QgsConfigCache();
|
~QgsConfigCache();
|
||||||
|
|
||||||
QgsServerProjectParser* serverConfiguration( const QString& filePath );
|
QgsServerProjectParser* serverConfiguration( const QString& filePath );
|
||||||
QgsWfsProjectParser* wfsConfiguration( const QString& filePath, const QgsAccessControl* accessControl );
|
|
||||||
QgsWmsConfigParser* wmsConfiguration( const QString& filePath, const QgsAccessControl* accessControl, const QMap<QString, QString>& parameterMap = QMap< QString, QString >() );
|
QgsWmsConfigParser* wmsConfiguration( const QString& filePath, const QgsAccessControl* accessControl, const QMap<QString, QString>& parameterMap = QMap< QString, QString >() );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -123,6 +123,30 @@ namespace QgsServerProjectUtils
|
|||||||
*/
|
*/
|
||||||
QString wfsServiceUrl( const QgsProject& project );
|
QString wfsServiceUrl( const QgsProject& project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published in WFS.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
QStringList wfsLayerIds( const QgsProject& project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published as WFS-T with update capabilities.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
QStringList wfstUpdateLayerIds( const QgsProject& project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published as WFS-T with insert capabilities.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
QStringList wfstInsertLayerIds( const QgsProject& project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published as WFS-T with delete capabilities.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
QStringList wfstDeleteLayerIds( const QgsProject& project );
|
||||||
|
|
||||||
/** Returns the WCS service url defined in a QGIS project.
|
/** Returns the WCS service url defined in a QGIS project.
|
||||||
* @param project the QGIS project
|
* @param project the QGIS project
|
||||||
* @return url if defined in project, an empty string otherwise.
|
* @return url if defined in project, an empty string otherwise.
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgswfsserver.sip
|
|
||||||
-------------------
|
|
||||||
begin : May 2, 2015
|
|
||||||
copyright : (C) 2015 by Alessandro Pasotti
|
|
||||||
email : a dot pasotti at itopen dot it
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QGSWFSSERVER_H
|
|
||||||
#define QGSWFSSERVER_H
|
|
||||||
|
|
||||||
#include <QDomDocument>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QString>
|
|
||||||
#include <map>
|
|
||||||
#include "qgis.h"
|
|
||||||
#include "qgsowsserver.h"
|
|
||||||
#include "qgsvectorlayer.h"
|
|
||||||
#include "qgswfsprojectparser.h"
|
|
||||||
|
|
||||||
class QgsCoordinateReferenceSystem;
|
|
||||||
class QgsComposerLayerItem;
|
|
||||||
class QgsComposerLegendItem;
|
|
||||||
class QgsComposition;
|
|
||||||
class QgsFields;
|
|
||||||
class QgsMapLayer;
|
|
||||||
class QgsPoint;
|
|
||||||
class QgsRasterLayer;
|
|
||||||
class QgsConfigParser;
|
|
||||||
class QgsVectorLayer;
|
|
||||||
class QgsCoordinateReferenceSystem;
|
|
||||||
class QgsField;
|
|
||||||
class QgsFeature;
|
|
||||||
class QgsRectangle;
|
|
||||||
class QgsGeometry;
|
|
||||||
class QgsSymbol;
|
|
||||||
class QgsRequestHandler;
|
|
||||||
class QFile;
|
|
||||||
class QFont;
|
|
||||||
class QImage;
|
|
||||||
class QPaintDevice;
|
|
||||||
class QPainter;
|
|
||||||
|
|
||||||
|
|
||||||
/** This class handles all the wms server requests. The parameters and values have to be passed in the form of
|
|
||||||
a map<QString, QString>. This map is usually generated by a subclass of QgsWMSRequestHandler, which makes QgsWFSServer
|
|
||||||
independent from any server side technology*/
|
|
||||||
|
|
||||||
class QgsWfsServer: public QgsOWSServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)*/
|
|
||||||
QgsWfsServer( const QString& configFilePath, const QgsServerSettings& settings,
|
|
||||||
QMap<QString, QString>& parameters, QgsWfsProjectParser* cp,
|
|
||||||
QgsRequestHandler* rh, const QgsAccessControl* accessControl );
|
|
||||||
~QgsWfsServer();
|
|
||||||
|
|
||||||
void executeRequest() override;
|
|
||||||
|
|
||||||
/** Returns an XML file with the capabilities description (as described in the WFS specs)*/
|
|
||||||
QDomDocument getCapabilities();
|
|
||||||
|
|
||||||
/** Returns an XML file with the describe feature type (as described in the WFS specs)*/
|
|
||||||
QDomDocument describeFeatureType();
|
|
||||||
|
|
||||||
/** Creates a document that describes the result of the getFeature request.
|
|
||||||
@return 0 in case of success*/
|
|
||||||
int getFeature( QgsRequestHandler& request, const QString& format );
|
|
||||||
|
|
||||||
/** Read and apply the transaction
|
|
||||||
@return 0 in case of success*/
|
|
||||||
QDomDocument transaction( const QString& requestBody );
|
|
||||||
|
|
||||||
/** Sets configuration parser for administration settings. Does not take ownership*/
|
|
||||||
void setAdminConfigParser( QgsWfsProjectParser* parser ) { mConfigParser = parser; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
/** Don't use the default constructor*/
|
|
||||||
QgsWfsServer();
|
|
||||||
|
|
||||||
/** Get service address from REQUEST_URI if not specified in the configuration*/
|
|
||||||
QString serviceUrl() const;
|
|
||||||
|
|
||||||
/* The Type of Feature created */
|
|
||||||
QString mTypeName;
|
|
||||||
/* The list of Feature's Type requested */
|
|
||||||
QStringList mTypeNames;
|
|
||||||
QString mPropertyName;
|
|
||||||
bool mWithGeom;
|
|
||||||
/* Error messages */
|
|
||||||
QStringList mErrors;
|
|
||||||
|
|
||||||
QgsWFSProjectParser* mConfigParser;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void startGetFeature( QgsRequestHandler& request, const QString& format, int prec, QgsCoordinateReferenceSystem& crs, QgsRectangle* rect );
|
|
||||||
void setGetFeature( QgsRequestHandler& request, const QString& format, QgsFeature* feat, int featIdx, int prec, QgsCoordinateReferenceSystem& crs, const QgsAttributeList& attrIndexes, const QSet<QString>& excludedAttributes );
|
|
||||||
void endGetFeature( QgsRequestHandler& request, const QString& format );
|
|
||||||
|
|
||||||
//method for transaction
|
|
||||||
QgsFeatureIds getFeatureIdsFromFilter( const QDomElement& filter, QgsVectorLayer* layer );
|
|
||||||
|
|
||||||
//methods to write GeoJSON
|
|
||||||
QString createFeatureGeoJSON( QgsFeature* feat, int prec, QgsCoordinateReferenceSystem& crs, const QgsAttributeList& attrIndexes, const QSet<QString>& excludedAttributes ) /*const*/;
|
|
||||||
|
|
||||||
//methods to write GML2
|
|
||||||
QDomElement createFeatureGML2( QgsFeature* feat, QDomDocument& doc, int prec, QgsCoordinateReferenceSystem& crs, const QgsAttributeList& attrIndexes, const QSet<QString>& excludedAttributes ) /*const*/;
|
|
||||||
|
|
||||||
//methods to write GML3
|
|
||||||
QDomElement createFeatureGML3( QgsFeature* feat, QDomDocument& doc, int prec, QgsCoordinateReferenceSystem& crs, QgsAttributeList attrIndexes, QSet<QString> excludedAttributes ) /*const*/;
|
|
||||||
|
|
||||||
void addTransactionResult( QDomDocument& responseDoc, QDomElement& responseElem, const QString& status, const QString& locator, const QString& message );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -23,7 +23,6 @@
|
|||||||
%Include qgsserverprojectparser.sip
|
%Include qgsserverprojectparser.sip
|
||||||
%Include qgswmsconfigparser.sip
|
%Include qgswmsconfigparser.sip
|
||||||
%Include qgswmsprojectparser.sip
|
%Include qgswmsprojectparser.sip
|
||||||
%Include qgswfsprojectparser.sip
|
|
||||||
%Include qgsconfigcache.sip
|
%Include qgsconfigcache.sip
|
||||||
%Include qgsserversettings.sip
|
%Include qgsserversettings.sip
|
||||||
%Include qgsserverprojectutils.sip
|
%Include qgsserverprojectutils.sip
|
||||||
|
@ -34,7 +34,6 @@ SET(qgis_mapserv_SRCS
|
|||||||
qgsremotedatasourcebuilder.cpp
|
qgsremotedatasourcebuilder.cpp
|
||||||
qgssentdatasourcebuilder.cpp
|
qgssentdatasourcebuilder.cpp
|
||||||
qgsserverlogger.cpp
|
qgsserverlogger.cpp
|
||||||
qgswfsprojectparser.cpp
|
|
||||||
qgswmsconfigparser.cpp
|
qgswmsconfigparser.cpp
|
||||||
qgswmsprojectparser.cpp
|
qgswmsprojectparser.cpp
|
||||||
qgsserverprojectparser.cpp
|
qgsserverprojectparser.cpp
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "qgsconfigcache.h"
|
#include "qgsconfigcache.h"
|
||||||
#include "qgsmessagelog.h"
|
#include "qgsmessagelog.h"
|
||||||
#include "qgsmslayercache.h"
|
#include "qgsmslayercache.h"
|
||||||
#include "qgswfsprojectparser.h"
|
|
||||||
#include "qgswmsprojectparser.h"
|
#include "qgswmsprojectparser.h"
|
||||||
#include "qgssldconfigparser.h"
|
#include "qgssldconfigparser.h"
|
||||||
#include "qgsaccesscontrol.h"
|
#include "qgsaccesscontrol.h"
|
||||||
@ -76,32 +75,6 @@ QgsServerProjectParser *QgsConfigCache::serverConfiguration( const QString &file
|
|||||||
return new QgsServerProjectParser( doc, filePath );
|
return new QgsServerProjectParser( doc, filePath );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsWfsProjectParser *QgsConfigCache::wfsConfiguration(
|
|
||||||
const QString &filePath
|
|
||||||
, const QgsAccessControl *accessControl
|
|
||||||
)
|
|
||||||
{
|
|
||||||
QgsWfsProjectParser *p = mWFSConfigCache.object( filePath );
|
|
||||||
if ( !p )
|
|
||||||
{
|
|
||||||
QDomDocument *doc = xmlDocument( filePath );
|
|
||||||
if ( !doc )
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
p = new QgsWfsProjectParser(
|
|
||||||
filePath
|
|
||||||
, accessControl
|
|
||||||
);
|
|
||||||
mWFSConfigCache.insert( filePath, p );
|
|
||||||
p = mWFSConfigCache.object( filePath );
|
|
||||||
Q_ASSERT( p );
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsMSLayerCache::instance()->setProjectMaxLayers( p->wfsLayers().size() );
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsWmsConfigParser *QgsConfigCache::wmsConfiguration(
|
QgsWmsConfigParser *QgsConfigCache::wmsConfiguration(
|
||||||
const QString &filePath
|
const QString &filePath
|
||||||
, const QgsAccessControl *accessControl
|
, const QgsAccessControl *accessControl
|
||||||
@ -182,7 +155,6 @@ QDomDocument *QgsConfigCache::xmlDocument( const QString &filePath )
|
|||||||
void QgsConfigCache::removeChangedEntry( const QString &path )
|
void QgsConfigCache::removeChangedEntry( const QString &path )
|
||||||
{
|
{
|
||||||
mWMSConfigCache.remove( path );
|
mWMSConfigCache.remove( path );
|
||||||
mWFSConfigCache.remove( path );
|
|
||||||
|
|
||||||
//xml document must be removed last, as other config cache destructors may require it
|
//xml document must be removed last, as other config cache destructors may require it
|
||||||
mXmlDocumentCache.remove( path );
|
mXmlDocumentCache.remove( path );
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include "qgis_server.h"
|
#include "qgis_server.h"
|
||||||
#include "qgswmsconfigparser.h"
|
#include "qgswmsconfigparser.h"
|
||||||
#include "qgswfsprojectparser.h"
|
|
||||||
|
|
||||||
class QgsServerProjectParser;
|
class QgsServerProjectParser;
|
||||||
class QgsAccessControl;
|
class QgsAccessControl;
|
||||||
@ -41,10 +40,6 @@ class SERVER_EXPORT QgsConfigCache : public QObject
|
|||||||
static QgsConfigCache *instance();
|
static QgsConfigCache *instance();
|
||||||
|
|
||||||
QgsServerProjectParser *serverConfiguration( const QString &filePath );
|
QgsServerProjectParser *serverConfiguration( const QString &filePath );
|
||||||
QgsWfsProjectParser *wfsConfiguration(
|
|
||||||
const QString &filePath
|
|
||||||
, const QgsAccessControl *accessControl
|
|
||||||
);
|
|
||||||
QgsWmsConfigParser *wmsConfiguration(
|
QgsWmsConfigParser *wmsConfiguration(
|
||||||
const QString &filePath
|
const QString &filePath
|
||||||
, const QgsAccessControl *accessControl
|
, const QgsAccessControl *accessControl
|
||||||
@ -64,7 +59,6 @@ class SERVER_EXPORT QgsConfigCache : public QObject
|
|||||||
|
|
||||||
QCache<QString, QDomDocument> mXmlDocumentCache;
|
QCache<QString, QDomDocument> mXmlDocumentCache;
|
||||||
QCache<QString, QgsWmsConfigParser> mWMSConfigCache;
|
QCache<QString, QgsWmsConfigParser> mWMSConfigCache;
|
||||||
QCache<QString, QgsWfsProjectParser> mWFSConfigCache;
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
//! Removes changed entry from this cache
|
//! Removes changed entry from this cache
|
||||||
|
@ -97,6 +97,31 @@ QString QgsServerProjectUtils::wfsServiceUrl( const QgsProject &project )
|
|||||||
return project.readEntry( QStringLiteral( "WFSUrl" ), QStringLiteral( "/" ), "" );
|
return project.readEntry( QStringLiteral( "WFSUrl" ), QStringLiteral( "/" ), "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QgsServerProjectUtils::wfsLayerIds( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readListEntry( QStringLiteral( "WFSLayers" ), QStringLiteral( "/" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsServerProjectUtils::wfsLayerPrecision( const QString &layerId, const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readNumEntry( QStringLiteral( "WFSLayersPrecision" ), "/" + layerId, 6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList QgsServerProjectUtils::wfstUpdateLayerIds( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readListEntry( QStringLiteral( "WFSTLayers" ), QStringLiteral( "Update" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList QgsServerProjectUtils::wfstInsertLayerIds( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readListEntry( QStringLiteral( "WFSTLayers" ), QStringLiteral( "Insert" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList QgsServerProjectUtils::wfstDeleteLayerIds( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readListEntry( QStringLiteral( "WFSTLayers" ), QStringLiteral( "Delete" ) );
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsServerProjectUtils::wcsServiceUrl( const QgsProject &project )
|
QString QgsServerProjectUtils::wcsServiceUrl( const QgsProject &project )
|
||||||
{
|
{
|
||||||
return project.readEntry( QStringLiteral( "WCSUrl" ), QStringLiteral( "/" ), "" );
|
return project.readEntry( QStringLiteral( "WCSUrl" ), QStringLiteral( "/" ), "" );
|
||||||
|
@ -125,6 +125,32 @@ namespace QgsServerProjectUtils
|
|||||||
*/
|
*/
|
||||||
SERVER_EXPORT QString wfsServiceUrl( const QgsProject &project );
|
SERVER_EXPORT QString wfsServiceUrl( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published in WFS.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QStringList wfsLayerIds( const QgsProject &project );
|
||||||
|
|
||||||
|
SERVER_EXPORT int wfsLayerPrecision( const QString &layerId, const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published as WFS-T with update capabilities.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QStringList wfstUpdateLayerIds( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published as WFS-T with insert capabilities.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QStringList wfstInsertLayerIds( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the Layer ids list defined in a QGIS project as published as WFS-T with delete capabilities.
|
||||||
|
* @param project the QGIS project
|
||||||
|
* @return the Layer ids list.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QStringList wfstDeleteLayerIds( const QgsProject &project );
|
||||||
|
|
||||||
/** Returns the WCS service url defined in a QGIS project.
|
/** Returns the WCS service url defined in a QGIS project.
|
||||||
* \param project the QGIS project
|
* \param project the QGIS project
|
||||||
* \returns url if defined in project, an empty string otherwise.
|
* \returns url if defined in project, an empty string otherwise.
|
||||||
|
@ -1,572 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgswfsprojectparser.cpp
|
|
||||||
-----------------------
|
|
||||||
begin : March 25, 2014
|
|
||||||
copyright : (C) 2014 by Marco Hugentobler
|
|
||||||
email : marco dot hugentobler at sourcepole dot ch
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "qgswfsprojectparser.h"
|
|
||||||
#include "qgsconfigcache.h"
|
|
||||||
#include "qgsconfigparserutils.h"
|
|
||||||
#include "qgsproject.h"
|
|
||||||
#include "qgsvectordataprovider.h"
|
|
||||||
#include "qgsmapserviceexception.h"
|
|
||||||
#include "qgsaccesscontrol.h"
|
|
||||||
#include "qgslogger.h"
|
|
||||||
|
|
||||||
|
|
||||||
QgsWfsProjectParser::QgsWfsProjectParser(
|
|
||||||
const QString &filePath
|
|
||||||
, const QgsAccessControl *ac
|
|
||||||
)
|
|
||||||
: mAccessControl( ac )
|
|
||||||
{
|
|
||||||
#ifndef HAVE_SERVER_PYTHON_PLUGINS
|
|
||||||
Q_UNUSED( mAccessControl );
|
|
||||||
#endif
|
|
||||||
mProjectParser = QgsConfigCache::instance()->serverConfiguration( filePath );
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsWfsProjectParser::~QgsWfsProjectParser()
|
|
||||||
{
|
|
||||||
delete mProjectParser;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsWfsProjectParser::serviceCapabilities( QDomElement &parentElement, QDomDocument &doc ) const
|
|
||||||
{
|
|
||||||
mProjectParser->serviceCapabilities( parentElement, doc, QStringLiteral( "WFS" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsWfsProjectParser::featureTypeList( QDomElement &parentElement, QDomDocument &doc ) const
|
|
||||||
{
|
|
||||||
const QList<QDomElement> &projectLayerElements = mProjectParser->projectLayerElements();
|
|
||||||
if ( projectLayerElements.size() < 1 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList wfsLayersId = mProjectParser->wfsLayers();
|
|
||||||
QSet<QString> wfstUpdateLayersId = wfstUpdateLayers();
|
|
||||||
QSet<QString> wfstInsertLayersId = wfstInsertLayers();
|
|
||||||
QSet<QString> wfstDeleteLayersId = wfstDeleteLayers();
|
|
||||||
|
|
||||||
QMap<QString, QgsMapLayer *> layerMap;
|
|
||||||
|
|
||||||
Q_FOREACH ( const QDomElement &elem, projectLayerElements )
|
|
||||||
{
|
|
||||||
QString type = elem.attribute( QStringLiteral( "type" ) );
|
|
||||||
if ( type == QLatin1String( "vector" ) )
|
|
||||||
{
|
|
||||||
QString layerId = mProjectParser->layerId( elem );
|
|
||||||
if ( !wfsLayersId.contains( layerId ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QgsMapLayer *layer = mProjectParser->createLayerFromElement( elem );
|
|
||||||
if ( !layer )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
|
||||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) );
|
|
||||||
layerMap.insert( layer->id(), layer );
|
|
||||||
|
|
||||||
QDomElement layerElem = doc.createElement( QStringLiteral( "FeatureType" ) );
|
|
||||||
QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
|
|
||||||
//We use the layer name even though it might not be unique.
|
|
||||||
//Because the id sometimes contains user/pw information and the name is more descriptive
|
|
||||||
QString typeName = layer->name();
|
|
||||||
if ( !layer->shortName().isEmpty() )
|
|
||||||
typeName = layer->shortName();
|
|
||||||
typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
|
|
||||||
QDomText nameText = doc.createTextNode( typeName );
|
|
||||||
nameElem.appendChild( nameText );
|
|
||||||
layerElem.appendChild( nameElem );
|
|
||||||
|
|
||||||
QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
|
|
||||||
QString titleName = layer->title();
|
|
||||||
if ( titleName.isEmpty() )
|
|
||||||
{
|
|
||||||
titleName = layer->name();
|
|
||||||
}
|
|
||||||
QDomText titleText = doc.createTextNode( titleName );
|
|
||||||
titleElem.appendChild( titleText );
|
|
||||||
layerElem.appendChild( titleElem );
|
|
||||||
|
|
||||||
QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
|
|
||||||
QString abstractName = layer->abstract();
|
|
||||||
if ( abstractName.isEmpty() )
|
|
||||||
{
|
|
||||||
abstractName = QLatin1String( "" );
|
|
||||||
}
|
|
||||||
QDomText abstractText = doc.createTextNode( abstractName );
|
|
||||||
abstractElem.appendChild( abstractText );
|
|
||||||
layerElem.appendChild( abstractElem );
|
|
||||||
|
|
||||||
//keyword list
|
|
||||||
if ( !layer->keywordList().isEmpty() )
|
|
||||||
{
|
|
||||||
QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) );
|
|
||||||
QDomText keywordsText = doc.createTextNode( layer->keywordList() );
|
|
||||||
keywordsElem.appendChild( keywordsText );
|
|
||||||
layerElem.appendChild( keywordsElem );
|
|
||||||
}
|
|
||||||
|
|
||||||
//appendExGeographicBoundingBox( layerElem, doc, layer->extent(), layer->crs() );
|
|
||||||
|
|
||||||
QDomElement srsElem = doc.createElement( QStringLiteral( "SRS" ) );
|
|
||||||
QDomText srsText = doc.createTextNode( layer->crs().authid() );
|
|
||||||
srsElem.appendChild( srsText );
|
|
||||||
layerElem.appendChild( srsElem );
|
|
||||||
|
|
||||||
//wfs:Operations element
|
|
||||||
QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
|
|
||||||
//wfs:Query element
|
|
||||||
QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ );
|
|
||||||
operationsElement.appendChild( queryElement );
|
|
||||||
|
|
||||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
|
|
||||||
QgsVectorDataProvider *provider = vlayer->dataProvider();
|
|
||||||
if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
|
|
||||||
{
|
|
||||||
//wfs:Insert element
|
|
||||||
QDomElement insertElement = doc.createElement( QStringLiteral( "Insert" )/*wfs:Insert*/ );
|
|
||||||
operationsElement.appendChild( insertElement );
|
|
||||||
}
|
|
||||||
if ( ( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
|
|
||||||
( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
|
|
||||||
wfstUpdateLayersId.contains( layer->id() ) )
|
|
||||||
{
|
|
||||||
//wfs:Update element
|
|
||||||
QDomElement updateElement = doc.createElement( QStringLiteral( "Update" )/*wfs:Update*/ );
|
|
||||||
operationsElement.appendChild( updateElement );
|
|
||||||
}
|
|
||||||
if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
|
|
||||||
{
|
|
||||||
//wfs:Delete element
|
|
||||||
QDomElement deleteElement = doc.createElement( QStringLiteral( "Delete" )/*wfs:Delete*/ );
|
|
||||||
operationsElement.appendChild( deleteElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
layerElem.appendChild( operationsElement );
|
|
||||||
|
|
||||||
QgsRectangle layerExtent = layer->extent();
|
|
||||||
QDomElement bBoxElement = doc.createElement( QStringLiteral( "LatLongBoundingBox" ) );
|
|
||||||
bBoxElement.setAttribute( QStringLiteral( "minx" ), QString::number( layerExtent.xMinimum() ) );
|
|
||||||
bBoxElement.setAttribute( QStringLiteral( "miny" ), QString::number( layerExtent.yMinimum() ) );
|
|
||||||
bBoxElement.setAttribute( QStringLiteral( "maxx" ), QString::number( layerExtent.xMaximum() ) );
|
|
||||||
bBoxElement.setAttribute( QStringLiteral( "maxy" ), QString::number( layerExtent.yMaximum() ) );
|
|
||||||
layerElem.appendChild( bBoxElement );
|
|
||||||
|
|
||||||
// layer metadata URL
|
|
||||||
QString metadataUrl = layer->metadataUrl();
|
|
||||||
if ( !metadataUrl.isEmpty() )
|
|
||||||
{
|
|
||||||
QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
|
|
||||||
QString metadataUrlType = layer->metadataUrlType();
|
|
||||||
metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType );
|
|
||||||
QString metadataUrlFormat = layer->metadataUrlFormat();
|
|
||||||
if ( metadataUrlFormat == QLatin1String( "text/xml" ) )
|
|
||||||
{
|
|
||||||
metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "XML" ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "TXT" ) );
|
|
||||||
}
|
|
||||||
QDomText metaUrlText = doc.createTextNode( metadataUrl );
|
|
||||||
metaUrlElem.appendChild( metaUrlText );
|
|
||||||
layerElem.appendChild( metaUrlElem );
|
|
||||||
}
|
|
||||||
|
|
||||||
parentElement.appendChild( layerElem );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> QgsWfsProjectParser::wfstUpdateLayers() const
|
|
||||||
{
|
|
||||||
QSet<QString> publishedIds = wfsLayerSet();
|
|
||||||
QSet<QString> wfsList;
|
|
||||||
if ( !mProjectParser->xmlDocument() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDomElement propertiesElem = mProjectParser->propertiesElem();
|
|
||||||
if ( propertiesElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomElement wfstLayersElem = propertiesElem.firstChildElement( QStringLiteral( "WFSTLayers" ) );
|
|
||||||
if ( wfstLayersElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomElement wfstUpdateLayersElem = wfstLayersElem.firstChildElement( QStringLiteral( "Update" ) );
|
|
||||||
if ( wfstUpdateLayersElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomNodeList valueList = wfstUpdateLayersElem.elementsByTagName( QStringLiteral( "value" ) );
|
|
||||||
for ( int i = 0; i < valueList.size(); ++i )
|
|
||||||
{
|
|
||||||
QString id = valueList.at( i ).toElement().text();
|
|
||||||
if ( publishedIds.contains( id ) )
|
|
||||||
{
|
|
||||||
wfsList.insert( id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> QgsWfsProjectParser::wfstInsertLayers() const
|
|
||||||
{
|
|
||||||
QSet<QString> publishedIds = wfsLayerSet();
|
|
||||||
QSet<QString> wfsList;
|
|
||||||
if ( !mProjectParser->xmlDocument() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDomElement propertiesElem = mProjectParser->propertiesElem();
|
|
||||||
if ( propertiesElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomElement wfstLayersElem = propertiesElem.firstChildElement( QStringLiteral( "WFSTLayers" ) );
|
|
||||||
if ( wfstLayersElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomElement wfstInsertLayersElem = wfstLayersElem.firstChildElement( QStringLiteral( "Insert" ) );
|
|
||||||
if ( wfstInsertLayersElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomNodeList valueList = wfstInsertLayersElem.elementsByTagName( QStringLiteral( "value" ) );
|
|
||||||
for ( int i = 0; i < valueList.size(); ++i )
|
|
||||||
{
|
|
||||||
QString id = valueList.at( i ).toElement().text();
|
|
||||||
if ( publishedIds.contains( id ) )
|
|
||||||
{
|
|
||||||
wfsList.insert( id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> QgsWfsProjectParser::wfstDeleteLayers() const
|
|
||||||
{
|
|
||||||
QSet<QString> publishedIds = wfsLayerSet();
|
|
||||||
QSet<QString> wfsList;
|
|
||||||
if ( !mProjectParser->xmlDocument() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDomElement propertiesElem = mProjectParser->propertiesElem();
|
|
||||||
if ( propertiesElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomElement wfstLayersElem = propertiesElem.firstChildElement( QStringLiteral( "WFSTLayers" ) );
|
|
||||||
if ( wfstLayersElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomElement wfstDeleteLayersElem = wfstLayersElem.firstChildElement( QStringLiteral( "Delete" ) );
|
|
||||||
if ( wfstDeleteLayersElem.isNull() )
|
|
||||||
{
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
QDomNodeList valueList = wfstDeleteLayersElem.elementsByTagName( QStringLiteral( "value" ) );
|
|
||||||
for ( int i = 0; i < valueList.size(); ++i )
|
|
||||||
{
|
|
||||||
QString id = valueList.at( i ).toElement().text();
|
|
||||||
if ( publishedIds.contains( id ) )
|
|
||||||
{
|
|
||||||
wfsList.insert( id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wfsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 != QLatin1String( "" ) )
|
|
||||||
{
|
|
||||||
QStringList typeNameSplit = aTypeName.split( QStringLiteral( "," ) );
|
|
||||||
Q_FOREACH ( const QString &str, typeNameSplit )
|
|
||||||
{
|
|
||||||
if ( str.contains( QLatin1String( ":" ) ) )
|
|
||||||
typeNameList << str.section( QStringLiteral( ":" ), 1, 1 );
|
|
||||||
else
|
|
||||||
typeNameList << str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_FOREACH ( const QDomElement &elem, projectLayerElements )
|
|
||||||
{
|
|
||||||
QString type = elem.attribute( QStringLiteral( "type" ) );
|
|
||||||
if ( type == QLatin1String( "vector" ) )
|
|
||||||
{
|
|
||||||
QgsMapLayer *mLayer = mProjectParser->createLayerFromElement( elem );
|
|
||||||
QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mLayer );
|
|
||||||
if ( !layer )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
|
||||||
if ( !mAccessControl->layerReadPermission( layer ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QString typeName = layer->name();
|
|
||||||
if ( !layer->shortName().isEmpty() )
|
|
||||||
typeName = layer->shortName();
|
|
||||||
typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
|
|
||||||
|
|
||||||
if ( wfsLayersId.contains( layer->id() ) && ( aTypeName == QLatin1String( "" ) || typeNameList.contains( typeName ) ) )
|
|
||||||
{
|
|
||||||
//do a select with searchRect and go through all the features
|
|
||||||
QgsVectorDataProvider *provider = layer->dataProvider();
|
|
||||||
if ( !provider )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//hidden attributes for this layer
|
|
||||||
const QSet<QString> &layerExcludedAttributes = layer->excludeAttributesWfs();
|
|
||||||
|
|
||||||
//xsd:element
|
|
||||||
QDomElement elementElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );
|
|
||||||
elementElem.setAttribute( QStringLiteral( "name" ), typeName );
|
|
||||||
elementElem.setAttribute( QStringLiteral( "type" ), "qgs:" + typeName + "Type" );
|
|
||||||
elementElem.setAttribute( QStringLiteral( "substitutionGroup" ), QStringLiteral( "gml:_Feature" ) );
|
|
||||||
parentElement.appendChild( elementElem );
|
|
||||||
|
|
||||||
//xsd:complexType
|
|
||||||
QDomElement complexTypeElem = doc.createElement( QStringLiteral( "complexType" )/*xsd:complexType*/ );
|
|
||||||
complexTypeElem.setAttribute( QStringLiteral( "name" ), typeName + "Type" );
|
|
||||||
parentElement.appendChild( complexTypeElem );
|
|
||||||
|
|
||||||
//xsd:complexType
|
|
||||||
QDomElement complexContentElem = doc.createElement( QStringLiteral( "complexContent" )/*xsd:complexContent*/ );
|
|
||||||
complexTypeElem.appendChild( complexContentElem );
|
|
||||||
|
|
||||||
//xsd:extension
|
|
||||||
QDomElement extensionElem = doc.createElement( QStringLiteral( "extension" )/*xsd:extension*/ );
|
|
||||||
extensionElem.setAttribute( QStringLiteral( "base" ), QStringLiteral( "gml:AbstractFeatureType" ) );
|
|
||||||
complexContentElem.appendChild( extensionElem );
|
|
||||||
|
|
||||||
//xsd:sequence
|
|
||||||
QDomElement sequenceElem = doc.createElement( QStringLiteral( "sequence" )/*xsd:sequence*/ );
|
|
||||||
extensionElem.appendChild( sequenceElem );
|
|
||||||
|
|
||||||
//xsd:element
|
|
||||||
if ( layer->hasGeometryType() )
|
|
||||||
{
|
|
||||||
QDomElement geomElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );
|
|
||||||
geomElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
|
|
||||||
if ( provider->name() == QLatin1String( "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( QStringLiteral( "type" ), QStringLiteral( "gml:GeometryPropertyType" ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QgsWkbTypes::Type wkbType = layer->wkbType();
|
|
||||||
switch ( wkbType )
|
|
||||||
{
|
|
||||||
case QgsWkbTypes::Point25D:
|
|
||||||
case QgsWkbTypes::Point:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:PointPropertyType" ) );
|
|
||||||
break;
|
|
||||||
case QgsWkbTypes::LineString25D:
|
|
||||||
case QgsWkbTypes::LineString:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:LineStringPropertyType" ) );
|
|
||||||
break;
|
|
||||||
case QgsWkbTypes::Polygon25D:
|
|
||||||
case QgsWkbTypes::Polygon:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:PolygonPropertyType" ) );
|
|
||||||
break;
|
|
||||||
case QgsWkbTypes::MultiPoint25D:
|
|
||||||
case QgsWkbTypes::MultiPoint:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:MultiPointPropertyType" ) );
|
|
||||||
break;
|
|
||||||
case QgsWkbTypes::MultiLineString25D:
|
|
||||||
case QgsWkbTypes::MultiLineString:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:MultiLineStringPropertyType" ) );
|
|
||||||
break;
|
|
||||||
case QgsWkbTypes::MultiPolygon25D:
|
|
||||||
case QgsWkbTypes::MultiPolygon:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:MultiPolygonPropertyType" ) );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:GeometryPropertyType" ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
geomElem.setAttribute( QStringLiteral( "minOccurs" ), QStringLiteral( "0" ) );
|
|
||||||
geomElem.setAttribute( QStringLiteral( "maxOccurs" ), QStringLiteral( "1" ) );
|
|
||||||
sequenceElem.appendChild( geomElem );
|
|
||||||
}
|
|
||||||
|
|
||||||
//const QgsFields& fields = provider->fields();
|
|
||||||
const QgsFields &fields = layer->pendingFields();
|
|
||||||
for ( int idx = 0; idx < fields.count(); ++idx )
|
|
||||||
{
|
|
||||||
|
|
||||||
QString attributeName = fields.at( idx ).name();
|
|
||||||
//skip attribute if excluded from WFS publication
|
|
||||||
if ( layerExcludedAttributes.contains( attributeName ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//xsd:element
|
|
||||||
QDomElement attElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );
|
|
||||||
attElem.setAttribute( QStringLiteral( "name" ), attributeName );
|
|
||||||
QVariant::Type attributeType = fields.at( idx ).type();
|
|
||||||
if ( attributeType == QVariant::Int )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "integer" ) );
|
|
||||||
else if ( attributeType == QVariant::LongLong )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "long" ) );
|
|
||||||
else if ( attributeType == QVariant::Double )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "double" ) );
|
|
||||||
else if ( attributeType == QVariant::Bool )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "boolean" ) );
|
|
||||||
else if ( attributeType == QVariant::Date )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "date" ) );
|
|
||||||
else if ( attributeType == QVariant::Time )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "time" ) );
|
|
||||||
else if ( attributeType == QVariant::DateTime )
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "dateTime" ) );
|
|
||||||
else
|
|
||||||
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "string" ) );
|
|
||||||
|
|
||||||
sequenceElem.appendChild( attElem );
|
|
||||||
|
|
||||||
QString alias = fields.at( idx ).alias();
|
|
||||||
if ( !alias.isEmpty() )
|
|
||||||
{
|
|
||||||
attElem.setAttribute( QStringLiteral( "alias" ), alias );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QgsProject::instance()->removeAllMapLayers();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList QgsWfsProjectParser::wfsLayers() const
|
|
||||||
{
|
|
||||||
return mProjectParser->wfsLayers();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> QgsWfsProjectParser::wfsLayerSet() const
|
|
||||||
{
|
|
||||||
return QSet<QString>::fromList( wfsLayers() );
|
|
||||||
}
|
|
||||||
|
|
||||||
int QgsWfsProjectParser::wfsLayerPrecision( const QString &aLayerId ) const
|
|
||||||
{
|
|
||||||
QStringList wfsLayersId = mProjectParser->wfsLayers();
|
|
||||||
if ( !wfsLayersId.contains( aLayerId ) )
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int prec = 8;
|
|
||||||
QDomElement propertiesElem = mProjectParser->propertiesElem();
|
|
||||||
if ( !propertiesElem.isNull() )
|
|
||||||
{
|
|
||||||
QDomElement wfsPrecElem = propertiesElem.firstChildElement( QStringLiteral( "WFSLayersPrecision" ) );
|
|
||||||
if ( !wfsPrecElem.isNull() )
|
|
||||||
{
|
|
||||||
QDomElement wfsLayerPrecElem = wfsPrecElem.firstChildElement( aLayerId );
|
|
||||||
if ( !wfsLayerPrecElem.isNull() )
|
|
||||||
{
|
|
||||||
QString precStr = wfsLayerPrecElem.text();
|
|
||||||
prec = precStr.toInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prec;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QgsMapLayer *> QgsWfsProjectParser::mapLayerFromTypeName( const QString &aTypeName, bool useCache ) const
|
|
||||||
{
|
|
||||||
Q_UNUSED( useCache );
|
|
||||||
|
|
||||||
QList<QgsMapLayer *> layerList;
|
|
||||||
const QList<QDomElement> &projectLayerElements = mProjectParser->projectLayerElements();
|
|
||||||
|
|
||||||
if ( projectLayerElements.size() < 1 )
|
|
||||||
{
|
|
||||||
return layerList;
|
|
||||||
}
|
|
||||||
QStringList wfsLayersId = wfsLayers();
|
|
||||||
|
|
||||||
QStringList typeNameList;
|
|
||||||
if ( aTypeName != QLatin1String( "" ) )
|
|
||||||
{
|
|
||||||
QStringList typeNameSplit = aTypeName.split( QStringLiteral( "," ) );
|
|
||||||
Q_FOREACH ( const QString &str, typeNameSplit )
|
|
||||||
{
|
|
||||||
if ( str.contains( QLatin1String( ":" ) ) )
|
|
||||||
typeNameList << str.section( QStringLiteral( ":" ), 1, 1 );
|
|
||||||
else
|
|
||||||
typeNameList << str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_FOREACH ( const QDomElement &elem, projectLayerElements )
|
|
||||||
{
|
|
||||||
QString type = elem.attribute( QStringLiteral( "type" ) );
|
|
||||||
if ( type == QLatin1String( "vector" ) )
|
|
||||||
{
|
|
||||||
QgsMapLayer *mLayer = mProjectParser->createLayerFromElement( elem );
|
|
||||||
QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mLayer );
|
|
||||||
if ( !layer )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QString typeName = layer->name();
|
|
||||||
if ( !layer->shortName().isEmpty() )
|
|
||||||
typeName = layer->shortName();
|
|
||||||
typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
|
|
||||||
|
|
||||||
if ( wfsLayersId.contains( layer->id() ) && ( aTypeName == QLatin1String( "" ) || typeNameList.contains( typeName ) ) )
|
|
||||||
layerList.push_back( mLayer );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return layerList;
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
qgswfsprojectparser.h
|
|
||||||
---------------------
|
|
||||||
begin : March 25, 2014
|
|
||||||
copyright : (C) 2014 by Marco Hugentobler
|
|
||||||
email : marco dot hugentobler at sourcepole dot ch
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QGSWFSPROJECTPARSER_H
|
|
||||||
#define QGSWFSPROJECTPARSER_H
|
|
||||||
|
|
||||||
#include "qgsserverprojectparser.h"
|
|
||||||
#include "qgis_server.h"
|
|
||||||
|
|
||||||
|
|
||||||
class QgsAccessControl;
|
|
||||||
|
|
||||||
|
|
||||||
class SERVER_EXPORT QgsWfsProjectParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QgsWfsProjectParser(
|
|
||||||
const QString &filePath
|
|
||||||
, const QgsAccessControl *ac
|
|
||||||
);
|
|
||||||
~QgsWfsProjectParser();
|
|
||||||
|
|
||||||
QgsWfsProjectParser( const QgsWfsProjectParser &rh ) = delete;
|
|
||||||
QgsWfsProjectParser &operator=( const QgsWfsProjectParser &rh ) = delete;
|
|
||||||
|
|
||||||
void serviceCapabilities( QDomElement &parentElement, QDomDocument &doc ) const;
|
|
||||||
void featureTypeList( QDomElement &parentElement, QDomDocument &doc ) const;
|
|
||||||
|
|
||||||
void describeFeatureType( const QString &aTypeName, QDomElement &parentElement, QDomDocument &doc ) const;
|
|
||||||
|
|
||||||
QStringList wfsLayers() const;
|
|
||||||
QSet<QString> wfsLayerSet() const;
|
|
||||||
int wfsLayerPrecision( const QString &aLayerId ) const;
|
|
||||||
|
|
||||||
QList<QgsMapLayer *> mapLayerFromTypeName( const QString &aTypeName, bool useCache = true ) const;
|
|
||||||
|
|
||||||
QSet<QString> wfstUpdateLayers() const;
|
|
||||||
QSet<QString> wfstInsertLayers() const;
|
|
||||||
QSet<QString> wfstDeleteLayers() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QgsServerProjectParser *mProjectParser = nullptr;
|
|
||||||
const QgsAccessControl *mAccessControl = nullptr;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QGSWFSPROJECTPARSER_H
|
|
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler ( parts fron qgswmshandler)
|
copyright : (C) 2007 by Marco Hugentobler ( parts fron qgswmshandler)
|
||||||
|
(C) 2012 by René-Luc D'Hont ( parts fron qgswmshandler)
|
||||||
(C) 2014 by Alessandro Pasotti ( parts from qgswmshandler)
|
(C) 2014 by Alessandro Pasotti ( parts from qgswmshandler)
|
||||||
(C) 2016 by David Marteau
|
(C) 2016 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -78,11 +79,11 @@ namespace QgsWfs
|
|||||||
}
|
}
|
||||||
else if ( QSTR_COMPARE( req, "DescribeFeatureType" ) )
|
else if ( QSTR_COMPARE( req, "DescribeFeatureType" ) )
|
||||||
{
|
{
|
||||||
writeDescribeFeatureType( mServerIface, versionString, request, response );
|
writeDescribeFeatureType( mServerIface, project, versionString, request, response );
|
||||||
}
|
}
|
||||||
else if ( QSTR_COMPARE( req, "Transaction" ) )
|
else if ( QSTR_COMPARE( req, "Transaction" ) )
|
||||||
{
|
{
|
||||||
writeTransaction( mServerIface, versionString, request, response );
|
writeTransaction( mServerIface, project, versionString, request, response );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler (original code)
|
copyright : (C) 2007 by Marco Hugentobler (original code)
|
||||||
|
(C) 2012 by René-Luc D'Hont (original code)
|
||||||
(C) 2014 by Alessandro Pasotti (original code)
|
(C) 2014 by Alessandro Pasotti (original code)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -19,31 +20,42 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "qgswfsutils.h"
|
#include "qgswfsutils.h"
|
||||||
|
#include "qgsserverprojectutils.h"
|
||||||
#include "qgswfsdescribefeaturetype.h"
|
#include "qgswfsdescribefeaturetype.h"
|
||||||
|
|
||||||
|
#include "qgsproject.h"
|
||||||
|
#include "qgscsexception.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsvectordataprovider.h"
|
||||||
|
#include "qgsmapserviceexception.h"
|
||||||
|
#include "qgscoordinatereferencesystem.h"
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
namespace QgsWfs
|
namespace QgsWfs
|
||||||
{
|
{
|
||||||
|
|
||||||
void writeDescribeFeatureType( QgsServerInterface *serverIface, const QString &version,
|
void writeDescribeFeatureType( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
|
||||||
const QgsServerRequest &request, QgsServerResponse &response )
|
const QgsServerRequest &request, QgsServerResponse &response )
|
||||||
{
|
{
|
||||||
QDomDocument doc = createDescribeFeatureTypeDocument( serverIface, version, request );
|
QDomDocument doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
|
||||||
|
|
||||||
response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
|
response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
|
||||||
response.write( doc.toByteArray() );
|
response.write( doc.toByteArray() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QDomDocument createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QString &version,
|
QDomDocument createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
|
||||||
const QgsServerRequest &request )
|
const QgsServerRequest &request )
|
||||||
{
|
{
|
||||||
Q_UNUSED( version );
|
Q_UNUSED( version );
|
||||||
|
|
||||||
QDomDocument doc;
|
QDomDocument doc;
|
||||||
|
|
||||||
QgsWfsProjectParser *configParser = getConfigParser( serverIface );
|
|
||||||
QgsServerRequest::Parameters parameters = request.parameters();
|
QgsServerRequest::Parameters parameters = request.parameters();
|
||||||
|
|
||||||
|
QgsAccessControl *accessControl = serverIface->accessControls();
|
||||||
|
|
||||||
//xsd:schema
|
//xsd:schema
|
||||||
QDomElement schemaElement = doc.createElement( QStringLiteral( "schema" )/*xsd:schema*/ );
|
QDomElement schemaElement = doc.createElement( QStringLiteral( "schema" )/*xsd:schema*/ );
|
||||||
schemaElement.setAttribute( QStringLiteral( "xmlns" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema" ) );
|
schemaElement.setAttribute( QStringLiteral( "xmlns" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema" ) );
|
||||||
@ -62,9 +74,7 @@ namespace QgsWfs
|
|||||||
importElement.setAttribute( QStringLiteral( "schemaLocation" ), QStringLiteral( "http://schemas.opengis.net/gml/2.1.2/feature.xsd" ) );
|
importElement.setAttribute( QStringLiteral( "schemaLocation" ), QStringLiteral( "http://schemas.opengis.net/gml/2.1.2/feature.xsd" ) );
|
||||||
schemaElement.appendChild( importElement );
|
schemaElement.appendChild( importElement );
|
||||||
|
|
||||||
//defining typename
|
QStringList typeNameList;
|
||||||
QString typeName = QLatin1String( "" );
|
|
||||||
|
|
||||||
QDomDocument queryDoc;
|
QDomDocument queryDoc;
|
||||||
QString errorMsg;
|
QString errorMsg;
|
||||||
if ( queryDoc.setContent( parameters.value( QStringLiteral( "REQUEST_BODY" ) ), true, &errorMsg ) )
|
if ( queryDoc.setContent( parameters.value( QStringLiteral( "REQUEST_BODY" ) ), true, &errorMsg ) )
|
||||||
@ -79,23 +89,208 @@ namespace QgsWfs
|
|||||||
QDomElement docChildElem = docChildNodes.at( i ).toElement();
|
QDomElement docChildElem = docChildNodes.at( i ).toElement();
|
||||||
if ( docChildElem.tagName() == QLatin1String( "TypeName" ) )
|
if ( docChildElem.tagName() == QLatin1String( "TypeName" ) )
|
||||||
{
|
{
|
||||||
if ( typeName == QLatin1String( "" ) )
|
QString typeName = docChildElem.text().trimmed();
|
||||||
typeName = docChildElem.text();
|
if ( typeName.contains( QLatin1String( ":" ) ) )
|
||||||
|
typeNameList << typeName.section( QStringLiteral( ":" ), 1, 1 );
|
||||||
else
|
else
|
||||||
typeName += "," + docChildElem.text();
|
typeNameList << typeName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typeName = request.getParameter( QStringLiteral( "TYPENAME" ) );
|
QString typeNames = request.getParameter( QStringLiteral( "TYPENAME" ) );
|
||||||
|
if ( !typeNames.isEmpty() )
|
||||||
|
{
|
||||||
|
QStringList typeNameSplit = typeNames.split( QStringLiteral( "," ) );
|
||||||
|
for ( int i = 0; i < typeNameSplit.size(); ++i )
|
||||||
|
{
|
||||||
|
QString typeName = typeNameSplit.at( i ).trimmed();
|
||||||
|
if ( typeName.contains( QLatin1String( ":" ) ) )
|
||||||
|
typeNameList << typeName.section( QStringLiteral( ":" ), 1, 1 );
|
||||||
|
else
|
||||||
|
typeNameList << typeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configParser->describeFeatureType( typeName, schemaElement, doc );
|
QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
|
||||||
|
for ( int i = 0; i < wfsLayerIds.size(); ++i )
|
||||||
|
{
|
||||||
|
QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) );
|
||||||
|
if ( layer->type() != QgsMapLayer::LayerType::VectorLayer )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString name = layer->name();
|
||||||
|
if ( !layer->shortName().isEmpty() )
|
||||||
|
name = layer->shortName();
|
||||||
|
name = name.replace( QLatin1String( " " ), QLatin1String( "_" ) );
|
||||||
|
|
||||||
|
if ( !typeNameList.isEmpty() && !typeNameList.contains( name ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( accessControl && !accessControl->layerReadPermission( layer ) )
|
||||||
|
{
|
||||||
|
if ( !typeNameList.isEmpty() )
|
||||||
|
{
|
||||||
|
throw QgsSecurityAccessException( QStringLiteral( "Feature access permission denied" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer );
|
||||||
|
QgsVectorDataProvider *provider = vLayer->dataProvider();
|
||||||
|
if ( !provider )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
setSchemaLayer( schemaElement, doc, const_cast<QgsVectorLayer *>( vLayer ) );
|
||||||
|
}
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSchemaLayer( QDomElement &parentElement, QDomDocument &doc, const QgsVectorLayer *layer )
|
||||||
|
{
|
||||||
|
const QgsVectorDataProvider *provider = layer->dataProvider();
|
||||||
|
if ( !provider )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString typeName = layer->name();
|
||||||
|
if ( !layer->shortName().isEmpty() )
|
||||||
|
typeName = layer->shortName();
|
||||||
|
typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
|
||||||
|
|
||||||
|
//xsd:element
|
||||||
|
QDomElement elementElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );
|
||||||
|
elementElem.setAttribute( QStringLiteral( "name" ), typeName );
|
||||||
|
elementElem.setAttribute( QStringLiteral( "type" ), "qgs:" + typeName + "Type" );
|
||||||
|
elementElem.setAttribute( QStringLiteral( "substitutionGroup" ), QStringLiteral( "gml:_Feature" ) );
|
||||||
|
parentElement.appendChild( elementElem );
|
||||||
|
|
||||||
|
//xsd:complexType
|
||||||
|
QDomElement complexTypeElem = doc.createElement( QStringLiteral( "complexType" )/*xsd:complexType*/ );
|
||||||
|
complexTypeElem.setAttribute( QStringLiteral( "name" ), typeName + "Type" );
|
||||||
|
parentElement.appendChild( complexTypeElem );
|
||||||
|
|
||||||
|
//xsd:complexType
|
||||||
|
QDomElement complexContentElem = doc.createElement( QStringLiteral( "complexContent" )/*xsd:complexContent*/ );
|
||||||
|
complexTypeElem.appendChild( complexContentElem );
|
||||||
|
|
||||||
|
//xsd:extension
|
||||||
|
QDomElement extensionElem = doc.createElement( QStringLiteral( "extension" )/*xsd:extension*/ );
|
||||||
|
extensionElem.setAttribute( QStringLiteral( "base" ), QStringLiteral( "gml:AbstractFeatureType" ) );
|
||||||
|
complexContentElem.appendChild( extensionElem );
|
||||||
|
|
||||||
|
//xsd:sequence
|
||||||
|
QDomElement sequenceElem = doc.createElement( QStringLiteral( "sequence" )/*xsd:sequence*/ );
|
||||||
|
extensionElem.appendChild( sequenceElem );
|
||||||
|
|
||||||
|
//xsd:element
|
||||||
|
if ( layer->hasGeometryType() )
|
||||||
|
{
|
||||||
|
QDomElement geomElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );
|
||||||
|
geomElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
|
||||||
|
if ( provider->name() == QLatin1String( "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( QStringLiteral( "type" ), QStringLiteral( "gml:GeometryPropertyType" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QgsWkbTypes::Type wkbType = layer->wkbType();
|
||||||
|
switch ( wkbType )
|
||||||
|
{
|
||||||
|
case QgsWkbTypes::Point25D:
|
||||||
|
case QgsWkbTypes::Point:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:PointPropertyType" ) );
|
||||||
|
break;
|
||||||
|
case QgsWkbTypes::LineString25D:
|
||||||
|
case QgsWkbTypes::LineString:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:LineStringPropertyType" ) );
|
||||||
|
break;
|
||||||
|
case QgsWkbTypes::Polygon25D:
|
||||||
|
case QgsWkbTypes::Polygon:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:PolygonPropertyType" ) );
|
||||||
|
break;
|
||||||
|
case QgsWkbTypes::MultiPoint25D:
|
||||||
|
case QgsWkbTypes::MultiPoint:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:MultiPointPropertyType" ) );
|
||||||
|
break;
|
||||||
|
case QgsWkbTypes::MultiLineString25D:
|
||||||
|
case QgsWkbTypes::MultiLineString:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:MultiLineStringPropertyType" ) );
|
||||||
|
break;
|
||||||
|
case QgsWkbTypes::MultiPolygon25D:
|
||||||
|
case QgsWkbTypes::MultiPolygon:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:MultiPolygonPropertyType" ) );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
geomElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "gml:GeometryPropertyType" ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
geomElem.setAttribute( QStringLiteral( "minOccurs" ), QStringLiteral( "0" ) );
|
||||||
|
geomElem.setAttribute( QStringLiteral( "maxOccurs" ), QStringLiteral( "1" ) );
|
||||||
|
sequenceElem.appendChild( geomElem );
|
||||||
|
|
||||||
|
//Attributes
|
||||||
|
const QgsFields &fields = layer->pendingFields();
|
||||||
|
//hidden attributes for this layer
|
||||||
|
const QSet<QString> &layerExcludedAttributes = layer->excludeAttributesWfs();
|
||||||
|
for ( int idx = 0; idx < fields.count(); ++idx )
|
||||||
|
{
|
||||||
|
|
||||||
|
QString attributeName = fields.at( idx ).name();
|
||||||
|
//skip attribute if excluded from WFS publication
|
||||||
|
if ( layerExcludedAttributes.contains( attributeName ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//xsd:element
|
||||||
|
QDomElement attElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );
|
||||||
|
attElem.setAttribute( QStringLiteral( "name" ), attributeName );
|
||||||
|
QVariant::Type attributeType = fields.at( idx ).type();
|
||||||
|
if ( attributeType == QVariant::Int )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "integer" ) );
|
||||||
|
else if ( attributeType == QVariant::LongLong )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "long" ) );
|
||||||
|
else if ( attributeType == QVariant::Double )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "double" ) );
|
||||||
|
else if ( attributeType == QVariant::Bool )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "boolean" ) );
|
||||||
|
else if ( attributeType == QVariant::Date )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "date" ) );
|
||||||
|
else if ( attributeType == QVariant::Time )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "time" ) );
|
||||||
|
else if ( attributeType == QVariant::DateTime )
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "dateTime" ) );
|
||||||
|
else
|
||||||
|
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "string" ) );
|
||||||
|
|
||||||
|
sequenceElem.appendChild( attElem );
|
||||||
|
|
||||||
|
QString alias = fields.at( idx ).alias();
|
||||||
|
if ( !alias.isEmpty() )
|
||||||
|
{
|
||||||
|
attElem.setAttribute( QStringLiteral( "alias" ), alias );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // samespace QgsWfs
|
} // samespace QgsWfs
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler (original code)
|
copyright : (C) 2007 by Marco Hugentobler (original code)
|
||||||
|
(C) 2012 by René-Luc D'Hont (original code)
|
||||||
(C) 2014 by Alessandro Pasotti (original code)
|
(C) 2014 by Alessandro Pasotti (original code)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -21,20 +22,24 @@
|
|||||||
#ifndef QGSWFSDESCRIBEFEATURETYPE_H
|
#ifndef QGSWFSDESCRIBEFEATURETYPE_H
|
||||||
#define QGSWFSDESCRIBEFEATURETYPE_H
|
#define QGSWFSDESCRIBEFEATURETYPE_H
|
||||||
|
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
|
#include <QDomElement>
|
||||||
|
|
||||||
namespace QgsWfs
|
namespace QgsWfs
|
||||||
{
|
{
|
||||||
|
void setSchemaLayer( QDomElement &parentElement, QDomDocument &doc, const QgsVectorLayer *layer );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create get capabilities document
|
* Create get capabilities document
|
||||||
*/
|
*/
|
||||||
QDomDocument createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QString &version,
|
QDomDocument createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
|
||||||
const QgsServerRequest &request );
|
const QgsServerRequest &request );
|
||||||
|
|
||||||
/** Output WFS GetCapabilities response
|
/** Output WFS GetCapabilities response
|
||||||
*/
|
*/
|
||||||
void writeDescribeFeatureType( QgsServerInterface *serverIface, const QString &version,
|
void writeDescribeFeatureType( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
|
||||||
const QgsServerRequest &request, QgsServerResponse &response );
|
const QgsServerRequest &request, QgsServerResponse &response );
|
||||||
|
|
||||||
} // samespace QgsWfs
|
} // samespace QgsWfs
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler (original code)
|
copyright : (C) 2007 by Marco Hugentobler (original code)
|
||||||
|
(C) 2012 by René-Luc D'Hont (original code)
|
||||||
(C) 2014 by Alessandro Pasotti (original code)
|
(C) 2014 by Alessandro Pasotti (original code)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -19,8 +20,18 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "qgswfsutils.h"
|
#include "qgswfsutils.h"
|
||||||
|
#include "qgsserverprojectutils.h"
|
||||||
#include "qgswfsgetcapabilities.h"
|
#include "qgswfsgetcapabilities.h"
|
||||||
|
|
||||||
|
#include "qgsproject.h"
|
||||||
|
#include "qgscsexception.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsvectordataprovider.h"
|
||||||
|
#include "qgsmapserviceexception.h"
|
||||||
|
#include "qgscoordinatereferencesystem.h"
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
namespace QgsWfs
|
namespace QgsWfs
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -44,8 +55,6 @@ namespace QgsWfs
|
|||||||
|
|
||||||
QDomDocument doc;
|
QDomDocument doc;
|
||||||
|
|
||||||
QgsWfsProjectParser *configParser = getConfigParser( serverIface );
|
|
||||||
|
|
||||||
//wfs:WFS_Capabilities element
|
//wfs:WFS_Capabilities element
|
||||||
QDomElement wfsCapabilitiesElement = doc.createElement( QStringLiteral( "WFS_Capabilities" )/*wms:WFS_Capabilities*/ );
|
QDomElement wfsCapabilitiesElement = doc.createElement( QStringLiteral( "WFS_Capabilities" )/*wms:WFS_Capabilities*/ );
|
||||||
wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE );
|
wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE );
|
||||||
@ -59,7 +68,9 @@ namespace QgsWfs
|
|||||||
wfsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
|
wfsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
|
||||||
doc.appendChild( wfsCapabilitiesElement );
|
doc.appendChild( wfsCapabilitiesElement );
|
||||||
|
|
||||||
configParser->serviceCapabilities( wfsCapabilitiesElement, doc );
|
//configParser->serviceCapabilities( wfsCapabilitiesElement, doc );
|
||||||
|
//INSERT Service
|
||||||
|
wfsCapabilitiesElement.appendChild( getServiceElement( doc, project ) );
|
||||||
|
|
||||||
//wfs:Capability element
|
//wfs:Capability element
|
||||||
QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wfs:Capability*/ );
|
QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wfs:Capability*/ );
|
||||||
@ -125,19 +136,8 @@ namespace QgsWfs
|
|||||||
transactionDhcTypeElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
|
transactionDhcTypeElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
|
||||||
transactionElement.appendChild( transactionDhcTypeElement );
|
transactionElement.appendChild( transactionDhcTypeElement );
|
||||||
|
|
||||||
//wfs:FeatureTypeList element
|
//wfs:FeatureTypeList
|
||||||
QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" )/*wfs:FeatureTypeList*/ );
|
wfsCapabilitiesElement.appendChild( getFeatureTypeListElement( doc, serverIface, project ) );
|
||||||
wfsCapabilitiesElement.appendChild( featureTypeListElement );
|
|
||||||
//wfs:Operations element
|
|
||||||
QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
|
|
||||||
featureTypeListElement.appendChild( operationsElement );
|
|
||||||
//wfs:Query element
|
|
||||||
QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ );
|
|
||||||
operationsElement.appendChild( queryElement );
|
|
||||||
/*
|
|
||||||
* Adding layer liste in featureTypeListElement
|
|
||||||
*/
|
|
||||||
configParser->featureTypeList( featureTypeListElement, doc );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adding ogc:Filter_Capabilities in capabilityElement
|
* Adding ogc:Filter_Capabilities in capabilityElement
|
||||||
@ -169,6 +169,224 @@ namespace QgsWfs
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDomElement getServiceElement( QDomDocument &doc, const QgsProject *project )
|
||||||
|
{
|
||||||
|
//Service element
|
||||||
|
QDomElement serviceElem = doc.createElement( QStringLiteral( "Service" ) );
|
||||||
|
|
||||||
|
//Service name
|
||||||
|
QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
|
||||||
|
QDomText nameText = doc.createTextNode( "WFS" );
|
||||||
|
nameElem.appendChild( nameText );
|
||||||
|
serviceElem.appendChild( nameElem );
|
||||||
|
|
||||||
|
QString title = QgsServerProjectUtils::owsServiceTitle( *project );
|
||||||
|
if ( !title.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
|
||||||
|
QDomText titleText = doc.createTextNode( title );
|
||||||
|
titleElem.appendChild( titleText );
|
||||||
|
serviceElem.appendChild( titleElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project );
|
||||||
|
if ( !abstract.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
|
||||||
|
QDomText abstractText = doc.createCDATASection( abstract );
|
||||||
|
abstractElem.appendChild( abstractText );
|
||||||
|
serviceElem.appendChild( abstractElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project );
|
||||||
|
if ( !keywords.isEmpty() && !keywords.join( QStringLiteral( ", " ) ).isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) );
|
||||||
|
QDomText keywordsText = doc.createTextNode( keywords.join( QStringLiteral( ", " ) ) );
|
||||||
|
keywordsElem.appendChild( keywordsText );
|
||||||
|
serviceElem.appendChild( keywordsElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement onlineResourceElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
|
||||||
|
QString onlineResource = QgsServerProjectUtils::owsServiceOnlineResource( *project );
|
||||||
|
if ( !onlineResource.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomText onlineResourceText = doc.createTextNode( onlineResource );
|
||||||
|
onlineResourceElem.appendChild( onlineResourceText );
|
||||||
|
}
|
||||||
|
serviceElem.appendChild( onlineResourceElem );
|
||||||
|
|
||||||
|
QString fees = QgsServerProjectUtils::owsServiceFees( *project );
|
||||||
|
if ( !fees.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement feesElem = doc.createElement( QStringLiteral( "Fees" ) );
|
||||||
|
QDomText feesText = doc.createTextNode( fees );
|
||||||
|
feesElem.appendChild( feesText );
|
||||||
|
serviceElem.appendChild( feesElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString accessConstraints = QgsServerProjectUtils::owsServiceAccessConstraints( *project );
|
||||||
|
if ( !accessConstraints.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( "AccessConstraints" ) );
|
||||||
|
QDomText accessConstraintsText = doc.createTextNode( accessConstraints );
|
||||||
|
accessConstraintsElem.appendChild( accessConstraintsText );
|
||||||
|
serviceElem.appendChild( accessConstraintsElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceElem;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project )
|
||||||
|
{
|
||||||
|
QgsAccessControl *accessControl = serverIface->accessControls();
|
||||||
|
|
||||||
|
//wfs:FeatureTypeList element
|
||||||
|
QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" )/*wfs:FeatureTypeList*/ );
|
||||||
|
//wfs:Operations element
|
||||||
|
QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
|
||||||
|
featureTypeListElement.appendChild( operationsElement );
|
||||||
|
//wfs:Query element
|
||||||
|
QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ );
|
||||||
|
operationsElement.appendChild( queryElement );
|
||||||
|
|
||||||
|
QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
|
||||||
|
QStringList wfstUpdateLayersId = QgsServerProjectUtils::wfstUpdateLayerIds( *project );
|
||||||
|
QStringList wfstInsertLayersId = QgsServerProjectUtils::wfstInsertLayerIds( *project );
|
||||||
|
QStringList wfstDeleteLayersId = QgsServerProjectUtils::wfstDeleteLayerIds( *project );
|
||||||
|
for ( int i = 0; i < wfsLayerIds.size(); ++i )
|
||||||
|
{
|
||||||
|
QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) );
|
||||||
|
if ( layer->type() != QgsMapLayer::LayerType::VectorLayer )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( accessControl && !accessControl->layerReadPermission( layer ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement layerElem = doc.createElement( QStringLiteral( "FeatureType" ) );
|
||||||
|
|
||||||
|
//create Name
|
||||||
|
QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
|
||||||
|
QString typeName = layer->name();
|
||||||
|
if ( !layer->shortName().isEmpty() )
|
||||||
|
typeName = layer->shortName();
|
||||||
|
typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
|
||||||
|
QDomText nameText = doc.createTextNode( typeName );
|
||||||
|
nameElem.appendChild( nameText );
|
||||||
|
layerElem.appendChild( nameElem );
|
||||||
|
|
||||||
|
//create Title
|
||||||
|
QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
|
||||||
|
QString title = layer->title();
|
||||||
|
if ( title.isEmpty() )
|
||||||
|
{
|
||||||
|
title = layer->name();
|
||||||
|
}
|
||||||
|
QDomText titleText = doc.createTextNode( title );
|
||||||
|
titleElem.appendChild( titleText );
|
||||||
|
layerElem.appendChild( titleElem );
|
||||||
|
|
||||||
|
//create Abstract
|
||||||
|
QString abstract = layer->abstract();
|
||||||
|
if ( !abstract.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
|
||||||
|
QDomText abstractText = doc.createTextNode( abstract );
|
||||||
|
abstractElem.appendChild( abstractText );
|
||||||
|
layerElem.appendChild( abstractElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
//create keywords
|
||||||
|
QString keywords = layer->keywordList();
|
||||||
|
if ( !keywords.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) );
|
||||||
|
QDomText keywordsText = doc.createTextNode( keywords );
|
||||||
|
keywordsElem.appendChild( keywordsText );
|
||||||
|
layerElem.appendChild( keywordsElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
//create SRS
|
||||||
|
QDomElement srsElem = doc.createElement( QStringLiteral( "SRS" ) );
|
||||||
|
QDomText srsText = doc.createTextNode( layer->crs().authid() );
|
||||||
|
srsElem.appendChild( srsText );
|
||||||
|
layerElem.appendChild( srsElem );
|
||||||
|
|
||||||
|
//create LatLongBoundingBox
|
||||||
|
QgsRectangle layerExtent = layer->extent();
|
||||||
|
QDomElement bBoxElement = doc.createElement( QStringLiteral( "LatLongBoundingBox" ) );
|
||||||
|
bBoxElement.setAttribute( QStringLiteral( "minx" ), QString::number( layerExtent.xMinimum() ) );
|
||||||
|
bBoxElement.setAttribute( QStringLiteral( "miny" ), QString::number( layerExtent.yMinimum() ) );
|
||||||
|
bBoxElement.setAttribute( QStringLiteral( "maxx" ), QString::number( layerExtent.xMaximum() ) );
|
||||||
|
bBoxElement.setAttribute( QStringLiteral( "maxy" ), QString::number( layerExtent.yMaximum() ) );
|
||||||
|
layerElem.appendChild( bBoxElement );
|
||||||
|
|
||||||
|
// layer metadata URL
|
||||||
|
QString metadataUrl = layer->metadataUrl();
|
||||||
|
if ( !metadataUrl.isEmpty() )
|
||||||
|
{
|
||||||
|
QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
|
||||||
|
QString metadataUrlType = layer->metadataUrlType();
|
||||||
|
metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType );
|
||||||
|
QString metadataUrlFormat = layer->metadataUrlFormat();
|
||||||
|
if ( metadataUrlFormat == QLatin1String( "text/xml" ) )
|
||||||
|
{
|
||||||
|
metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "XML" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "TXT" ) );
|
||||||
|
}
|
||||||
|
QDomText metaUrlText = doc.createTextNode( metadataUrl );
|
||||||
|
metaUrlElem.appendChild( metaUrlText );
|
||||||
|
layerElem.appendChild( metaUrlElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
//wfs:Operations element
|
||||||
|
QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
|
||||||
|
//wfs:Query element
|
||||||
|
QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ );
|
||||||
|
operationsElement.appendChild( queryElement );
|
||||||
|
if ( wfstUpdateLayersId.contains( layer->id() ) ||
|
||||||
|
wfstInsertLayersId.contains( layer->id() ) ||
|
||||||
|
wfstDeleteLayersId.contains( layer->id() ) )
|
||||||
|
{
|
||||||
|
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
|
||||||
|
QgsVectorDataProvider *provider = vlayer->dataProvider();
|
||||||
|
if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
|
||||||
|
{
|
||||||
|
//wfs:Insert element
|
||||||
|
QDomElement insertElement = doc.createElement( QStringLiteral( "Insert" )/*wfs:Insert*/ );
|
||||||
|
operationsElement.appendChild( insertElement );
|
||||||
|
}
|
||||||
|
if ( ( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
|
||||||
|
( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
|
||||||
|
wfstUpdateLayersId.contains( layer->id() ) )
|
||||||
|
{
|
||||||
|
//wfs:Update element
|
||||||
|
QDomElement updateElement = doc.createElement( QStringLiteral( "Update" )/*wfs:Update*/ );
|
||||||
|
operationsElement.appendChild( updateElement );
|
||||||
|
}
|
||||||
|
if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
|
||||||
|
{
|
||||||
|
//wfs:Delete element
|
||||||
|
QDomElement deleteElement = doc.createElement( QStringLiteral( "Delete" )/*wfs:Delete*/ );
|
||||||
|
operationsElement.appendChild( deleteElement );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layerElem.appendChild( operationsElement );
|
||||||
|
|
||||||
|
featureTypeListElement.appendChild( layerElem );
|
||||||
|
}
|
||||||
|
|
||||||
|
return featureTypeListElement;
|
||||||
|
}
|
||||||
|
|
||||||
} // samespace QgsWfs
|
} // samespace QgsWfs
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler (original code)
|
copyright : (C) 2007 by Marco Hugentobler (original code)
|
||||||
|
(C) 2012 by René-Luc D'Hont (original code)
|
||||||
(C) 2014 by Alessandro Pasotti (original code)
|
(C) 2014 by Alessandro Pasotti (original code)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -26,6 +27,16 @@
|
|||||||
namespace QgsWfs
|
namespace QgsWfs
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create FeatureTypeList element for get capabilities document
|
||||||
|
*/
|
||||||
|
QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Service element for get capabilities document
|
||||||
|
*/
|
||||||
|
QDomElement getServiceElement( QDomDocument &doc, const QgsProject *project );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create get capabilities document
|
* Create get capabilities document
|
||||||
*/
|
*/
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler (original code)
|
copyright : (C) 2007 by Marco Hugentobler (original code)
|
||||||
|
(C) 2012 by René-Luc D'Hont (original code)
|
||||||
(C) 2014 by Alessandro Pasotti (original code)
|
(C) 2014 by Alessandro Pasotti (original code)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -24,6 +25,39 @@
|
|||||||
|
|
||||||
namespace QgsWfs
|
namespace QgsWfs
|
||||||
{
|
{
|
||||||
|
struct getFeatureQuery
|
||||||
|
{
|
||||||
|
QString typeName;
|
||||||
|
|
||||||
|
QgsFeatureRequest featureRequest;
|
||||||
|
|
||||||
|
QStringList propertyList;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct getFeatureRequest
|
||||||
|
{
|
||||||
|
long maxFeatures;
|
||||||
|
|
||||||
|
long startIndex;
|
||||||
|
|
||||||
|
QString outputFormat;
|
||||||
|
|
||||||
|
QList< getFeatureQuery > queries;
|
||||||
|
|
||||||
|
QString geometryName;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Transform Query element to getFeatureQuery
|
||||||
|
*/
|
||||||
|
getFeatureQuery parseQueryElement( QDomElement &queryElem );
|
||||||
|
|
||||||
|
/** Transform RequestBody root element to getFeatureRequest
|
||||||
|
*/
|
||||||
|
getFeatureRequest parseGetFeatureRequestBody( QDomElement &docElem );
|
||||||
|
|
||||||
|
/** Transform parameters to getFeatureRequest
|
||||||
|
*/
|
||||||
|
getFeatureRequest parseGetFeatureParameters( QgsServerRequest::Parameters parameters );
|
||||||
|
|
||||||
/** Output WFS GetFeature response
|
/** Output WFS GetFeature response
|
||||||
*/
|
*/
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler (original code)
|
copyright : (C) 2007 by Marco Hugentobler (original code)
|
||||||
|
(C) 2012 by René-Luc D'Hont (original code)
|
||||||
(C) 2014 by Alessandro Pasotti (original code)
|
(C) 2014 by Alessandro Pasotti (original code)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -24,19 +25,99 @@
|
|||||||
|
|
||||||
namespace QgsWfs
|
namespace QgsWfs
|
||||||
{
|
{
|
||||||
|
struct transactionInsert
|
||||||
|
{
|
||||||
|
QString typeName;
|
||||||
|
|
||||||
|
QString handle;
|
||||||
|
|
||||||
|
QDomNodeList featureNodeList;
|
||||||
|
|
||||||
|
QStringList insertFeatureIds;
|
||||||
|
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
QString errorMsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct transactionUpdate
|
||||||
|
{
|
||||||
|
QString typeName;
|
||||||
|
|
||||||
|
QString handle;
|
||||||
|
|
||||||
|
QMap<QString, QString> propertyMap;
|
||||||
|
|
||||||
|
QDomElement geometryElement;
|
||||||
|
|
||||||
|
QgsFeatureRequest featureRequest;
|
||||||
|
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
QString errorMsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct transactionDelete
|
||||||
|
{
|
||||||
|
QString typeName;
|
||||||
|
|
||||||
|
QString handle;
|
||||||
|
|
||||||
|
QgsFeatureRequest featureRequest;
|
||||||
|
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
QString errorMsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct transactionRequest
|
||||||
|
{
|
||||||
|
QList< transactionInsert > inserts;
|
||||||
|
|
||||||
|
QList< transactionUpdate > updates;
|
||||||
|
|
||||||
|
QList< transactionDelete > deletes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Transform Insert element to transactionInsert
|
||||||
|
*/
|
||||||
|
transactionInsert parseInsertActionElement( QDomElement &actionElem );
|
||||||
|
|
||||||
|
/** Transform Update element to transactionUpdate
|
||||||
|
*/
|
||||||
|
transactionUpdate parseUpdateActionElement( QDomElement &actionElem );
|
||||||
|
|
||||||
|
/** Transform Delete element to transactionDelete
|
||||||
|
*/
|
||||||
|
transactionDelete parseDeleteActionElement( QDomElement &actionElem );
|
||||||
|
|
||||||
|
/** Transform RequestBody root element to getFeatureRequest
|
||||||
|
*/
|
||||||
|
transactionRequest parseTransactionRequestBody( QDomElement &docElem );
|
||||||
|
|
||||||
|
transactionRequest parseTransactionParameters( QgsServerRequest::Parameters parameters );
|
||||||
|
|
||||||
|
/** Transform GML feature nodes to features
|
||||||
|
*/
|
||||||
|
QgsFeatureList featuresFromGML( QDomNodeList featureNodeList, QgsVectorDataProvider *provider );
|
||||||
|
|
||||||
|
/** Perform the transaction
|
||||||
|
*/
|
||||||
|
void performTransaction( transactionRequest &aRequest, QgsServerInterface *serverIface, const QgsProject *project );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output WFS transaction response
|
* Output WFS transaction response
|
||||||
*/
|
*/
|
||||||
void writeTransaction( QgsServerInterface *serverIface, const QString &version,
|
void writeTransaction( QgsServerInterface *serverIface, const QgsProject *project,
|
||||||
const QgsServerRequest &request, QgsServerResponse &response );
|
const QString &version, const QgsServerRequest &request,
|
||||||
|
QgsServerResponse &response );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a wfs transaction document
|
* Create a wfs transaction document
|
||||||
*/
|
*/
|
||||||
QDomDocument createTransactionDocument( QgsServerInterface *serverIface, const QString &version,
|
QDomDocument createTransactionDocument( QgsServerInterface *serverIface, const QgsProject *project,
|
||||||
const QgsServerRequest &request );
|
const QString &version, const QgsServerRequest &request );
|
||||||
|
|
||||||
} // samespace QgsWfs
|
} // samespace QgsWfs
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
-------------------------
|
-------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler ( parts fron qgswmshandler)
|
copyright : (C) 2007 by Marco Hugentobler ( parts fron qgswmshandler)
|
||||||
|
(C) 2012 by René-Luc D'Hont ( parts from qgswmshandler)
|
||||||
(C) 2014 by Alessandro Pasotti ( parts from qgswmshandler)
|
(C) 2014 by Alessandro Pasotti ( parts from qgswmshandler)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -20,6 +21,7 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "qgswfsutils.h"
|
#include "qgswfsutils.h"
|
||||||
|
#include "qgsogcutils.h"
|
||||||
#include "qgsconfigcache.h"
|
#include "qgsconfigcache.h"
|
||||||
#include "qgsserverprojectutils.h"
|
#include "qgsserverprojectutils.h"
|
||||||
|
|
||||||
@ -30,21 +32,6 @@ namespace QgsWfs
|
|||||||
return QStringLiteral( "1.0.0" );
|
return QStringLiteral( "1.0.0" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the wms config parser (Transitional)
|
|
||||||
QgsWfsProjectParser *getConfigParser( QgsServerInterface *serverIface )
|
|
||||||
{
|
|
||||||
QString configFilePath = serverIface->configFilePath();
|
|
||||||
|
|
||||||
QgsWfsProjectParser *parser = QgsConfigCache::instance()->wfsConfiguration( configFilePath, serverIface->accessControls() );
|
|
||||||
if ( !parser )
|
|
||||||
{
|
|
||||||
throw QgsServiceException(
|
|
||||||
QStringLiteral( "WFS configuration error" ),
|
|
||||||
QStringLiteral( "There was an error reading the project file or the SLD configuration" ) );
|
|
||||||
}
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString serviceUrl( const QgsServerRequest &request, const QgsProject *project )
|
QString serviceUrl( const QgsServerRequest &request, const QgsProject *project )
|
||||||
{
|
{
|
||||||
QString href;
|
QString href;
|
||||||
@ -71,6 +58,86 @@ namespace QgsWfs
|
|||||||
return href;
|
return href;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem )
|
||||||
|
{
|
||||||
|
QgsFeatureRequest request;
|
||||||
|
|
||||||
|
QDomNodeList fidNodes = filterElem.elementsByTagName( QStringLiteral( "FeatureId" ) );
|
||||||
|
if ( !fidNodes.isEmpty() )
|
||||||
|
{
|
||||||
|
QgsFeatureIds fids;
|
||||||
|
QDomElement fidElem;
|
||||||
|
for ( int f = 0; f < fidNodes.size(); f++ )
|
||||||
|
{
|
||||||
|
fidElem = fidNodes.at( f ).toElement();
|
||||||
|
if ( !fidElem.hasAttribute( QStringLiteral( "fid" ) ) )
|
||||||
|
{
|
||||||
|
throw QgsRequestNotWellFormedException( "FeatureId element without fid attribute" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fid = fidElem.attribute( QStringLiteral( "fid" ) );
|
||||||
|
if ( fid.contains( QLatin1String( "." ) ) )
|
||||||
|
{
|
||||||
|
if ( fid.section( QStringLiteral( "." ), 0, 0 ) != typeName )
|
||||||
|
continue;
|
||||||
|
fid = fid.section( QStringLiteral( "." ), 1, 1 );
|
||||||
|
}
|
||||||
|
fids.insert( fid.toInt() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fids.size() > 0 )
|
||||||
|
{
|
||||||
|
request.setFilterFids( fids );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw QgsRequestNotWellFormedException( QStringLiteral( "No FeatureId element corrcetly parse against typeName '%1'" ).arg( typeName ) );
|
||||||
|
}
|
||||||
|
request.setFlags( QgsFeatureRequest::NoFlags );
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
else if ( filterElem.firstChildElement().tagName() == QLatin1String( "BBOX" ) )
|
||||||
|
{
|
||||||
|
QDomElement bboxElem = filterElem.firstChildElement();
|
||||||
|
QDomElement childElem = bboxElem.firstChildElement();
|
||||||
|
|
||||||
|
while ( !childElem.isNull() )
|
||||||
|
{
|
||||||
|
if ( childElem.tagName() == QLatin1String( "Box" ) )
|
||||||
|
{
|
||||||
|
request.setFilterRect( QgsOgcUtils::rectangleFromGMLBox( childElem ) );
|
||||||
|
}
|
||||||
|
else if ( childElem.tagName() != QLatin1String( "PropertyName" ) )
|
||||||
|
{
|
||||||
|
QgsGeometry geom = QgsOgcUtils::geometryFromGML( childElem );
|
||||||
|
request.setFilterRect( geom.boundingBox() );
|
||||||
|
}
|
||||||
|
childElem = childElem.nextSiblingElement();
|
||||||
|
}
|
||||||
|
request.setFlags( QgsFeatureRequest::ExactIntersect | QgsFeatureRequest::NoFlags );
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::shared_ptr<QgsExpression> filter( QgsOgcUtils::expressionFromOgcFilter( filterElem ) );
|
||||||
|
if ( filter )
|
||||||
|
{
|
||||||
|
if ( filter->hasParserError() )
|
||||||
|
{
|
||||||
|
throw QgsRequestNotWellFormedException( filter->parserErrorString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( filter->needsGeometry() )
|
||||||
|
{
|
||||||
|
request.setFlags( QgsFeatureRequest::NoFlags );
|
||||||
|
}
|
||||||
|
request.setFilterExpression( filter->expression() );
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QgsWfs
|
} // namespace QgsWfs
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
------------------------------------
|
------------------------------------
|
||||||
begin : December 20 , 2016
|
begin : December 20 , 2016
|
||||||
copyright : (C) 2007 by Marco Hugentobler ( parts fron qgswfshandler)
|
copyright : (C) 2007 by Marco Hugentobler ( parts fron qgswfshandler)
|
||||||
|
(C) 2012 by René-Luc D'Hont ( parts from qgswmshandler)
|
||||||
(C) 2014 by Alessandro Pasotti ( parts from qgswfshandler)
|
(C) 2014 by Alessandro Pasotti ( parts from qgswfshandler)
|
||||||
(C) 2017 by David Marteau
|
(C) 2017 by David Marteau
|
||||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
@ -24,7 +25,7 @@
|
|||||||
#define QGSWFSUTILS_H
|
#define QGSWFSUTILS_H
|
||||||
|
|
||||||
#include "qgsmodule.h"
|
#include "qgsmodule.h"
|
||||||
#include "qgswfsprojectparser.h"
|
#include "qgsfeaturerequest.h"
|
||||||
#include "qgswfsserviceexception.h"
|
#include "qgswfsserviceexception.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,19 +41,15 @@ namespace QgsWfs
|
|||||||
*/
|
*/
|
||||||
QString implementationVersion();
|
QString implementationVersion();
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the wms config parser (Transitional)
|
|
||||||
*
|
|
||||||
* XXX This is needed in the current implementation.
|
|
||||||
* This should disappear as soon we get rid of singleton.
|
|
||||||
*/
|
|
||||||
QgsWfsProjectParser *getConfigParser( QgsServerInterface *serverIface );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service URL string
|
* Service URL string
|
||||||
*/
|
*/
|
||||||
QString serviceUrl( const QgsServerRequest &request, const QgsProject *project );
|
QString serviceUrl( const QgsServerRequest &request, const QgsProject *project );
|
||||||
|
|
||||||
|
/** Transform a Filter element to a feature request
|
||||||
|
*/
|
||||||
|
QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem );
|
||||||
|
|
||||||
// Define namespaces used in WFS documents
|
// Define namespaces used in WFS documents
|
||||||
const QString WFS_NAMESPACE = QStringLiteral( "http://www.opengis.net/wfs" );
|
const QString WFS_NAMESPACE = QStringLiteral( "http://www.opengis.net/wfs" );
|
||||||
const QString GML_NAMESPACE = QStringLiteral( "http://www.opengis.net/gml" );
|
const QString GML_NAMESPACE = QStringLiteral( "http://www.opengis.net/gml" );
|
||||||
|
@ -458,7 +458,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
query_string = "&".join(["%s=%s" % i for i in list({
|
query_string = "&".join(["%s=%s" % i for i in list({
|
||||||
"MAP": urllib.parse.quote(self.projectPath),
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
"SERVICE": "WFS",
|
"SERVICE": "WFS",
|
||||||
"VERSION": "1.1.0",
|
"VERSION": "1.0.0",
|
||||||
"REQUEST": "GetCapabilities"
|
"REQUEST": "GetCapabilities"
|
||||||
}.items())])
|
}.items())])
|
||||||
|
|
||||||
@ -482,7 +482,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
query_string = "&".join(["%s=%s" % i for i in list({
|
query_string = "&".join(["%s=%s" % i for i in list({
|
||||||
"MAP": urllib.parse.quote(self.projectPath),
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
"SERVICE": "WFS",
|
"SERVICE": "WFS",
|
||||||
"VERSION": "1.1.0",
|
"VERSION": "1.0.0",
|
||||||
"REQUEST": "DescribeFeatureType",
|
"REQUEST": "DescribeFeatureType",
|
||||||
"TYPENAME": "Hello"
|
"TYPENAME": "Hello"
|
||||||
}.items())])
|
}.items())])
|
||||||
@ -501,7 +501,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
query_string = "&".join(["%s=%s" % i for i in list({
|
query_string = "&".join(["%s=%s" % i for i in list({
|
||||||
"MAP": urllib.parse.quote(self.projectPath),
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
"SERVICE": "WFS",
|
"SERVICE": "WFS",
|
||||||
"VERSION": "1.1.0",
|
"VERSION": "1.0.0",
|
||||||
"REQUEST": "DescribeFeatureType",
|
"REQUEST": "DescribeFeatureType",
|
||||||
"TYPENAME": "Country"
|
"TYPENAME": "Country"
|
||||||
}.items())])
|
}.items())])
|
||||||
@ -722,8 +722,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
||||||
"Content type for Insert is wrong: %s" % headers.get("Content-Type"))
|
"Content type for Insert is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find("<SUCCESS/>") == -1,
|
||||||
'<ServiceException code="Security">Feature modify permission denied</ServiceException>') != -1,
|
|
||||||
"WFS/Transactions Insert succeed\n%s" % response)
|
"WFS/Transactions Insert succeed\n%s" % response)
|
||||||
|
|
||||||
response, headers = self._post_restricted(data.format(color="red"), "LAYER_PERM=no")
|
response, headers = self._post_restricted(data.format(color="red"), "LAYER_PERM=no")
|
||||||
@ -732,7 +731,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
"Content type for Insert is wrong: %s" % headers.get("Content-Type"))
|
"Content type for Insert is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find(
|
||||||
'<ServiceException code="Security">Feature insert permission denied</ServiceException>') != -1,
|
'<ServiceException code="Security">No permissions to do WFS changes on layer \\\'db_point\\\'</ServiceException>') != -1,
|
||||||
"WFS/Transactions Insert succeed\n%s" % response)
|
"WFS/Transactions Insert succeed\n%s" % response)
|
||||||
|
|
||||||
response, headers = self._post_restricted(data.format(color="yellow"), "LAYER_PERM=yes")
|
response, headers = self._post_restricted(data.format(color="yellow"), "LAYER_PERM=yes")
|
||||||
@ -753,8 +752,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
||||||
"Content type for GetMap is wrong: %s" % headers.get("Content-Type"))
|
"Content type for GetMap is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find("<SUCCESS/>") == -1,
|
||||||
'<ServiceException code="Security">Feature modify permission denied</ServiceException>') != -1,
|
|
||||||
"WFS/Transactions Update succeed\n%s" % response)
|
"WFS/Transactions Update succeed\n%s" % response)
|
||||||
self._test_colors({1: "blue"})
|
self._test_colors({1: "blue"})
|
||||||
|
|
||||||
@ -772,8 +770,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
||||||
"Content type for Update is wrong: %s" % headers.get("Content-Type"))
|
"Content type for Update is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find("<SUCCESS/>") == -1,
|
||||||
'<ServiceException code="Security">Feature modify permission denied</ServiceException>') != -1,
|
|
||||||
"WFS/Transactions Update succeed\n%s" % response)
|
"WFS/Transactions Update succeed\n%s" % response)
|
||||||
self._test_colors({1: "red"})
|
self._test_colors({1: "red"})
|
||||||
|
|
||||||
@ -783,7 +780,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
"Content type for Update is wrong: %s" % headers.get("Content-Type"))
|
"Content type for Update is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find(
|
||||||
'<ServiceException code="Security">Feature update permission denied</ServiceException>') != -1,
|
'<ServiceException code="Security">No permissions to do WFS changes on layer \\\'db_point\\\'</ServiceException>') != -1,
|
||||||
"WFS/Transactions Update succeed\n%s" % response)
|
"WFS/Transactions Update succeed\n%s" % response)
|
||||||
self._test_colors({1: "red"})
|
self._test_colors({1: "red"})
|
||||||
|
|
||||||
@ -817,8 +814,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
||||||
"Content type for GetMap is wrong: %s" % headers.get("Content-Type"))
|
"Content type for GetMap is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find("<SUCCESS/>") == -1,
|
||||||
'<ServiceException code="Security">Feature modify permission denied</ServiceException>') != -1,
|
|
||||||
"WFS/Transactions Delete succeed\n%s" % response)
|
"WFS/Transactions Delete succeed\n%s" % response)
|
||||||
|
|
||||||
data_update = WFS_TRANSACTION_UPDATE.format(id="1", color="red", xml_ns=XML_NS)
|
data_update = WFS_TRANSACTION_UPDATE.format(id="1", color="red", xml_ns=XML_NS)
|
||||||
@ -831,7 +827,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
"Content type for GetMap is wrong: %s" % headers.get("Content-Type"))
|
"Content type for GetMap is wrong: %s" % headers.get("Content-Type"))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find(
|
str(response).find(
|
||||||
'<ServiceException code="Security">Feature delete permission denied</ServiceException>') != -1,
|
'<ServiceException code="Security">No permissions to do WFS changes on layer \\\'db_point\\\'</ServiceException>') != -1,
|
||||||
"WFS/Transactions Delete succeed\n%s" % response)
|
"WFS/Transactions Delete succeed\n%s" % response)
|
||||||
|
|
||||||
response, headers = self._post_restricted(data, "LAYER_PERM=yes")
|
response, headers = self._post_restricted(data, "LAYER_PERM=yes")
|
||||||
|
@ -183,6 +183,7 @@ class TestWFST(unittest.TestCase):
|
|||||||
layer = self._getLayer(layer.name())
|
layer = self._getLayer(layer.name())
|
||||||
self.assertTrue(layer.isValid())
|
self.assertTrue(layer.isValid())
|
||||||
self.assertEqual(layer.featureCount(), len(features))
|
self.assertEqual(layer.featureCount(), len(features))
|
||||||
|
self.assertEqual(wfs_layer.dataProvider().featureCount(), len(features))
|
||||||
|
|
||||||
def _checkUpdateFeatures(self, wfs_layer, old_features, new_features):
|
def _checkUpdateFeatures(self, wfs_layer, old_features, new_features):
|
||||||
"""
|
"""
|
||||||
|
@ -6,21 +6,19 @@ Content-Type: text/xml; charset=utf-8
|
|||||||
<Name>WFS</Name>
|
<Name>WFS</Name>
|
||||||
<Title>QGIS TestProject</Title>
|
<Title>QGIS TestProject</Title>
|
||||||
<Abstract>Some UTF8 text èòù</Abstract>
|
<Abstract>Some UTF8 text èòù</Abstract>
|
||||||
<OnlineResource></OnlineResource>
|
<OnlineResource/>
|
||||||
<Fees>None</Fees>
|
|
||||||
<AccessConstraints>None</AccessConstraints>
|
|
||||||
</Service>
|
</Service>
|
||||||
<Capability>
|
<Capability>
|
||||||
<Request>
|
<Request>
|
||||||
<GetCapabilities>
|
<GetCapabilities>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Get onlineResource="http:"/>
|
<Get onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Post onlineResource="http:"/>
|
<Post onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
</GetCapabilities>
|
</GetCapabilities>
|
||||||
@ -30,12 +28,12 @@ Content-Type: text/xml; charset=utf-8
|
|||||||
</SchemaDescriptionLanguage>
|
</SchemaDescriptionLanguage>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Get onlineResource="http:"/>
|
<Get onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Post onlineResource="http:"/>
|
<Post onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
</DescribeFeatureType>
|
</DescribeFeatureType>
|
||||||
@ -47,19 +45,19 @@ Content-Type: text/xml; charset=utf-8
|
|||||||
</ResultFormat>
|
</ResultFormat>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Get onlineResource="http:"/>
|
<Get onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Post onlineResource="http:"/>
|
<Post onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
</GetFeature>
|
</GetFeature>
|
||||||
<Transaction>
|
<Transaction>
|
||||||
<DCPType>
|
<DCPType>
|
||||||
<HTTP>
|
<HTTP>
|
||||||
<Post onlineResource="http:"/>
|
<Post onlineResource="?"/>
|
||||||
</HTTP>
|
</HTTP>
|
||||||
</DCPType>
|
</DCPType>
|
||||||
</Transaction>
|
</Transaction>
|
||||||
@ -74,13 +72,13 @@ Content-Type: text/xml; charset=utf-8
|
|||||||
<Title>A test vector layer</Title>
|
<Title>A test vector layer</Title>
|
||||||
<Abstract>A test vector layer with unicode òà</Abstract>
|
<Abstract>A test vector layer with unicode òà</Abstract>
|
||||||
<SRS>EPSG:4326</SRS>
|
<SRS>EPSG:4326</SRS>
|
||||||
|
<LatLongBoundingBox maxx="8.20355" minx="8.20346" maxy="44.9015" miny="44.9014"/>
|
||||||
<Operations>
|
<Operations>
|
||||||
<Query/>
|
<Query/>
|
||||||
<Insert/>
|
<Insert/>
|
||||||
<Update/>
|
<Update/>
|
||||||
<Delete/>
|
<Delete/>
|
||||||
</Operations>
|
</Operations>
|
||||||
<LatLongBoundingBox maxx="8.20355" minx="8.20346" maxy="44.9015" miny="44.9014"/>
|
|
||||||
</FeatureType>
|
</FeatureType>
|
||||||
</FeatureTypeList>
|
</FeatureTypeList>
|
||||||
<ogc:Filter_Capabilities>
|
<ogc:Filter_Capabilities>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user