Skip to content

Commit 1558b03

Browse files
committedOct 12, 2017
[Server][WFS] Update Transaction 1.1.0
1 parent 24a6854 commit 1558b03

File tree

7 files changed

+1462
-77
lines changed

7 files changed

+1462
-77
lines changed
 

‎src/server/services/wfs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ SET (wfs_SRCS
1010
qgswfsdescribefeaturetype.cpp
1111
qgswfsgetfeature.cpp
1212
qgswfstransaction.cpp
13+
qgswfstransaction_1_0_0.cpp
1314
qgswfsparameters.cpp
1415
)
1516

‎src/server/services/wfs/qgswfs.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "qgswfsgetfeature.h"
2828
#include "qgswfsdescribefeaturetype.h"
2929
#include "qgswfstransaction.h"
30+
#include "qgswfstransaction_1_0_0.h"
3031

3132
#define QSTR_COMPARE( str, lit )\
3233
(str.compare( QStringLiteral( lit ), Qt::CaseInsensitive ) == 0)
@@ -92,7 +93,15 @@ namespace QgsWfs
9293
}
9394
else if ( QSTR_COMPARE( req, "Transaction" ) )
9495
{
95-
writeTransaction( mServerIface, project, versionString, request, response );
96+
// Supports WFS 1.0.0
97+
if ( QSTR_COMPARE( versionString, "1.0.0" ) )
98+
{
99+
v1_0_0::writeTransaction( mServerIface, project, versionString, request, response );
100+
}
101+
else
102+
{
103+
writeTransaction( mServerIface, project, versionString, request, response );
104+
}
96105
}
97106
else
98107
{

‎src/server/services/wfs/qgswfstransaction.cpp

Lines changed: 88 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace QgsWfs
3636
{
3737
namespace
3838
{
39-
void addTransactionResult( QDomDocument &responseDoc, QDomElement &responseElem, const QString &status,
39+
void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
4040
const QString &locator, const QString &message );
4141
}
4242

@@ -84,110 +84,125 @@ namespace QgsWfs
8484
// It's time to make the transaction
8585
// Create the response document
8686
QDomDocument resp;
87-
//wfs:WFS_TransactionRespone element
88-
QDomElement respElem = resp.createElement( QStringLiteral( "WFS_TransactionResponse" )/*wfs:WFS_TransactionResponse*/ );
87+
//wfs:TransactionRespone element
88+
QDomElement respElem = resp.createElement( QStringLiteral( "TransactionResponse" )/*wfs:TransactionResponse*/ );
8989
respElem.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE );
9090
respElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
91-
respElem.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
91+
respElem.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
9292
respElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE );
93-
respElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
93+
respElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1.0" ) );
9494
resp.appendChild( respElem );
9595

96+
int totalInserted = 0;
97+
int totalUpdated = 0;
98+
int totalDeleted = 0;
9699
int errorCount = 0;
97-
QStringList errorLocators;
98-
QStringList errorMessages;
99100

100-
QList<transactionUpdate>::iterator tuIt = aRequest.updates.begin();
101-
for ( ; tuIt != aRequest.updates.end(); ++tuIt )
102-
{
103-
transactionUpdate &action = *tuIt;
104-
if ( action.error )
105-
{
106-
errorCount += 1;
107-
if ( action.handle.isEmpty() )
108-
{
109-
errorLocators << QStringLiteral( "Update:%1" ).arg( action.typeName );
110-
}
111-
else
112-
{
113-
errorLocators << action.handle;
114-
}
115-
errorMessages << action.errorMsg;
116-
}
117-
}
118-
119-
QList<transactionDelete>::iterator tdIt = aRequest.deletes.begin();
120-
for ( ; tdIt != aRequest.deletes.end(); ++tdIt )
121-
{
122-
transactionDelete &action = *tdIt;
123-
if ( action.error )
124-
{
125-
errorCount += 1;
126-
if ( action.handle.isEmpty() )
127-
{
128-
errorLocators << QStringLiteral( "Delete:%1" ).arg( action.typeName );
129-
}
130-
else
131-
{
132-
errorLocators << action.handle;
133-
}
134-
errorMessages << action.errorMsg;
135-
}
136-
}
101+
//wfs:TransactionResults element
102+
QDomElement trsElem = doc.createElement( QStringLiteral( "TransactionResults" ) );
137103

104+
//wfs:InsertResults element
105+
QDomElement irsElem = doc.createElement( QStringLiteral( "InsertResults" ) );
138106
QList<transactionInsert>::iterator tiIt = aRequest.inserts.begin();
139107
for ( ; tiIt != aRequest.inserts.end(); ++tiIt )
140108
{
141109
transactionInsert &action = *tiIt;
142110
if ( action.error )
143111
{
144112
errorCount += 1;
145-
if ( action.handle.isEmpty() )
146-
{
147-
errorLocators << QStringLiteral( "Insert:%1" ).arg( action.typeName );
148-
}
149-
else
113+
QString locator = action.handle;
114+
if ( locator.isEmpty() )
150115
{
151-
errorLocators << action.handle;
116+
locator = QStringLiteral( "Insert:%1" ).arg( action.typeName );
152117
}
153-
errorMessages << action.errorMsg;
118+
addTransactionResult( resp, trsElem, locator, action.errorMsg );
154119
}
155120
else
156121
{
157122
QStringList::const_iterator fidIt = action.insertFeatureIds.constBegin();
158123
for ( ; fidIt != action.insertFeatureIds.constEnd(); ++fidIt )
159124
{
160125
QString fidStr = *fidIt;
161-
QDomElement irElem = doc.createElement( QStringLiteral( "InsertResult" ) );
126+
QDomElement irElem = doc.createElement( QStringLiteral( "Feature" ) );
162127
if ( !action.handle.isEmpty() )
163128
{
164129
irElem.setAttribute( QStringLiteral( "handle" ), action.handle );
165130
}
166131
QDomElement fiElem = doc.createElement( QStringLiteral( "ogc:FeatureId" ) );
167132
fiElem.setAttribute( QStringLiteral( "fid" ), fidStr );
168133
irElem.appendChild( fiElem );
169-
respElem.appendChild( irElem );
134+
irsElem.appendChild( irElem );
170135
}
171136
}
137+
totalInserted += action.insertFeatureIds.count();
172138
}
173139

174-
// addTransactionResult
175-
if ( errorCount == 0 )
176-
{
177-
addTransactionResult( resp, respElem, QStringLiteral( "SUCCESS" ), QString(), QString() );
178-
}
179-
else
140+
QList<transactionUpdate>::iterator tuIt = aRequest.updates.begin();
141+
for ( ; tuIt != aRequest.updates.end(); ++tuIt )
180142
{
181-
QString locator = errorLocators.join( QStringLiteral( "; " ) );
182-
QString message = errorMessages.join( QStringLiteral( "; " ) );
183-
if ( errorCount != actionCount )
143+
transactionUpdate &action = *tuIt;
144+
if ( action.error )
184145
{
185-
addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), locator, message );
146+
errorCount += 1;
147+
QString locator = action.handle;
148+
if ( locator.isEmpty() )
149+
{
150+
locator = QStringLiteral( "Update:%1" ).arg( action.typeName );
151+
}
152+
addTransactionResult( resp, trsElem, locator, action.errorMsg );
186153
}
187-
else
154+
totalUpdated += action.totalUpdated;
155+
}
156+
157+
QList<transactionDelete>::iterator tdIt = aRequest.deletes.begin();
158+
for ( ; tdIt != aRequest.deletes.end(); ++tdIt )
159+
{
160+
transactionDelete &action = *tdIt;
161+
if ( action.error )
188162
{
189-
addTransactionResult( resp, respElem, QStringLiteral( "ERROR" ), locator, message );
163+
errorCount += 1;
164+
QString locator = action.handle;
165+
if ( locator.isEmpty() )
166+
{
167+
locator = QStringLiteral( "Delete:%1" ).arg( action.typeName );
168+
}
169+
addTransactionResult( resp, trsElem, locator, action.errorMsg );
190170
}
171+
totalDeleted += action.totalDeleted;
172+
}
173+
174+
//wfs:TransactionSummary element
175+
QDomElement summaryElem = doc.createElement( QStringLiteral( "TransactionSummary" ) );
176+
if ( aRequest.inserts.size() > 0 )
177+
{
178+
QDomElement totalInsertedElem = doc.createElement( QStringLiteral( "TotalInserted" ) );
179+
totalInsertedElem.appendChild( doc.createTextNode( QString::number( totalInserted ) ) );
180+
summaryElem.appendChild( totalInsertedElem );
181+
}
182+
if ( aRequest.updates.size() > 0 )
183+
{
184+
QDomElement totalUpdatedElem = doc.createElement( QStringLiteral( "TotalUpdated" ) );
185+
totalUpdatedElem.appendChild( doc.createTextNode( QString::number( totalUpdated ) ) );
186+
summaryElem.appendChild( totalUpdatedElem );
187+
}
188+
if ( aRequest.deletes.size() > 0 )
189+
{
190+
QDomElement totalDeletedElem = doc.createElement( QStringLiteral( "TotalDeleted" ) );
191+
totalDeletedElem.appendChild( doc.createTextNode( QString::number( totalDeleted ) ) );
192+
summaryElem.appendChild( totalDeletedElem );
193+
}
194+
respElem.appendChild( summaryElem );
195+
196+
// add TransactionResults
197+
if ( errorCount > 0 && trsElem.hasChildNodes() )
198+
{
199+
respElem.appendChild( trsElem );
200+
}
201+
202+
// add InsertResults
203+
if ( aRequest.inserts.size() > 0 && irsElem.hasChildNodes() )
204+
{
205+
respElem.appendChild( irsElem );
191206
}
192207
return resp;
193208
}
@@ -356,6 +371,7 @@ namespace QgsWfs
356371
// get iterator
357372
QgsFeatureIterator fit = vlayer->getFeatures( featureRequest );
358373
QgsFeature feature;
374+
int totalUpdated = 0;
359375
// get action properties
360376
QMap<QString, QString> propertyMap = action.propertyMap;
361377
QDomElement geometryElem = action.geometryElement;
@@ -433,6 +449,7 @@ namespace QgsWfs
433449
break;
434450
}
435451
}
452+
totalUpdated += 1;
436453
}
437454
if ( action.error )
438455
{
@@ -467,6 +484,7 @@ namespace QgsWfs
467484
continue;
468485
}
469486
// all the changes are OK!
487+
action.totalUpdated = totalUpdated;
470488
action.error = false;
471489

472490
}
@@ -564,6 +582,7 @@ namespace QgsWfs
564582
continue;
565583
}
566584
// all the changes are OK!
585+
action.totalDeleted = fids.count();
567586
action.error = false;
568587
}
569588

@@ -1159,21 +1178,15 @@ namespace QgsWfs
11591178
namespace
11601179
{
11611180

1162-
void addTransactionResult( QDomDocument &responseDoc, QDomElement &responseElem, const QString &status,
1181+
void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
11631182
const QString &locator, const QString &message )
11641183
{
1165-
QDomElement trElem = responseDoc.createElement( QStringLiteral( "TransactionResult" ) );
1166-
QDomElement stElem = responseDoc.createElement( QStringLiteral( "Status" ) );
1167-
QDomElement successElem = responseDoc.createElement( status );
1168-
stElem.appendChild( successElem );
1169-
trElem.appendChild( stElem );
1170-
responseElem.appendChild( trElem );
1184+
QDomElement trElem = responseDoc.createElement( QStringLiteral( "Action" ) );
1185+
resultsElem.appendChild( trElem );
11711186

11721187
if ( !locator.isEmpty() )
11731188
{
1174-
QDomElement locElem = responseDoc.createElement( QStringLiteral( "Locator" ) );
1175-
locElem.appendChild( responseDoc.createTextNode( locator ) );
1176-
trElem.appendChild( locElem );
1189+
trElem.setAttribute( QStringLiteral( "locator" ), locator );
11771190
}
11781191

11791192
if ( !message.isEmpty() )

‎src/server/services/wfs/qgswfstransaction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ namespace QgsWfs
5252

5353
QgsFeatureRequest featureRequest;
5454

55+
int totalUpdated = 0;
56+
5557
bool error;
5658

5759
QString errorMsg;
@@ -65,6 +67,8 @@ namespace QgsWfs
6567

6668
QgsFeatureRequest featureRequest;
6769

70+
int totalDeleted = 0;
71+
6872
bool error;
6973

7074
QString errorMsg;

‎src/server/services/wfs/qgswfstransaction_1_0_0.cpp

Lines changed: 1194 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/***************************************************************************
2+
qgswfstransaction.h
3+
-------------------------
4+
begin : December 20 , 2016
5+
copyright : (C) 2007 by Marco Hugentobler (original code)
6+
(C) 2012 by René-Luc D'Hont (original code)
7+
(C) 2014 by Alessandro Pasotti (original code)
8+
(C) 2017 by David Marteau
9+
email : marco dot hugentobler at karto dot baug dot ethz dot ch
10+
a dot pasotti at itopen dot it
11+
david dot marteau at 3liz dot com
12+
***************************************************************************/
13+
14+
/***************************************************************************
15+
* *
16+
* This program is free software; you can redistribute it and/or modify *
17+
* it under the terms of the GNU General Public License as published by *
18+
* the Free Software Foundation; either version 2 of the License, or *
19+
* (at your option) any later version. *
20+
* *
21+
***************************************************************************/
22+
#ifndef QGSWFSTRANSACTION_1_0_0_H
23+
#define QGSWFSTRANSACTION_1_0_0_H
24+
25+
26+
namespace QgsWfs
27+
{
28+
namespace v1_0_0
29+
{
30+
struct transactionInsert
31+
{
32+
QString typeName;
33+
34+
QString handle;
35+
36+
QDomNodeList featureNodeList;
37+
38+
QStringList insertFeatureIds;
39+
40+
bool error;
41+
42+
QString errorMsg;
43+
};
44+
45+
struct transactionUpdate
46+
{
47+
QString typeName;
48+
49+
QString handle;
50+
51+
QMap<QString, QString> propertyMap;
52+
53+
QDomElement geometryElement;
54+
55+
QgsFeatureRequest featureRequest;
56+
57+
bool error;
58+
59+
QString errorMsg;
60+
};
61+
62+
struct transactionDelete
63+
{
64+
QString typeName;
65+
66+
QString handle;
67+
68+
QgsFeatureRequest featureRequest;
69+
70+
bool error;
71+
72+
QString errorMsg;
73+
};
74+
75+
struct transactionRequest
76+
{
77+
QList< transactionInsert > inserts;
78+
79+
QList< transactionUpdate > updates;
80+
81+
QList< transactionDelete > deletes;
82+
};
83+
84+
/** Transform Insert element to transactionInsert
85+
*/
86+
transactionInsert parseInsertActionElement( QDomElement &actionElem );
87+
88+
/** Transform Update element to transactionUpdate
89+
*/
90+
transactionUpdate parseUpdateActionElement( QDomElement &actionElem );
91+
92+
/** Transform Delete element to transactionDelete
93+
*/
94+
transactionDelete parseDeleteActionElement( QDomElement &actionElem );
95+
96+
/** Transform RequestBody root element to getFeatureRequest
97+
*/
98+
transactionRequest parseTransactionRequestBody( QDomElement &docElem );
99+
100+
transactionRequest parseTransactionParameters( QgsServerRequest::Parameters parameters );
101+
102+
/** Transform GML feature nodes to features
103+
*/
104+
QgsFeatureList featuresFromGML( QDomNodeList featureNodeList, QgsVectorDataProvider *provider );
105+
106+
/** Perform the transaction
107+
*/
108+
void performTransaction( transactionRequest &aRequest, QgsServerInterface *serverIface, const QgsProject *project );
109+
110+
/**
111+
* Output WFS transaction response
112+
*/
113+
void writeTransaction( QgsServerInterface *serverIface, const QgsProject *project,
114+
const QString &version, const QgsServerRequest &request,
115+
QgsServerResponse &response );
116+
117+
118+
/**
119+
* Create a wfs transaction document
120+
*/
121+
QDomDocument createTransactionDocument( QgsServerInterface *serverIface, const QgsProject *project,
122+
const QString &version, const QgsServerRequest &request );
123+
124+
} // namespace v1_0_0
125+
} // samespace QgsWfs
126+
127+
#endif
128+

‎src/server/services/wfs/qgswfsutils.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ namespace QgsWfs
6363
QgsFeatureRequest request;
6464

6565
QDomNodeList fidNodes = filterElem.elementsByTagName( QStringLiteral( "FeatureId" ) );
66+
QDomNodeList goidNodes = filterElem.elementsByTagName( QStringLiteral( "GmlObjectId" ) );
6667
if ( !fidNodes.isEmpty() )
6768
{
6869
QgsFeatureIds fids;
@@ -91,7 +92,42 @@ namespace QgsWfs
9192
}
9293
else
9394
{
94-
throw QgsRequestNotWellFormedException( QStringLiteral( "No FeatureId element corrcetly parse against typeName '%1'" ).arg( typeName ) );
95+
throw QgsRequestNotWellFormedException( QStringLiteral( "No FeatureId element correctly parse against typeName '%1'" ).arg( typeName ) );
96+
}
97+
request.setFlags( QgsFeatureRequest::NoFlags );
98+
return request;
99+
}
100+
else if ( !goidNodes.isEmpty() )
101+
{
102+
QgsFeatureIds fids;
103+
QDomElement goidElem;
104+
for ( int f = 0; f < goidNodes.size(); f++ )
105+
{
106+
goidElem = goidNodes.at( f ).toElement();
107+
if ( !goidElem.hasAttribute( QStringLiteral( "id" ) ) && !goidElem.hasAttribute( QStringLiteral( "gml:id" ) ) )
108+
{
109+
throw QgsRequestNotWellFormedException( "GmlObjectId element without gml:id attribute" );
110+
}
111+
112+
QString fid = goidElem.attribute( QStringLiteral( "id" ) );
113+
if ( fid.isEmpty() )
114+
fid = goidElem.attribute( QStringLiteral( "gml:id" ) );
115+
if ( fid.contains( QLatin1String( "." ) ) )
116+
{
117+
if ( fid.section( QStringLiteral( "." ), 0, 0 ) != typeName )
118+
continue;
119+
fid = fid.section( QStringLiteral( "." ), 1, 1 );
120+
}
121+
fids.insert( fid.toInt() );
122+
}
123+
124+
if ( !fids.isEmpty() )
125+
{
126+
request.setFilterFids( fids );
127+
}
128+
else
129+
{
130+
throw QgsRequestNotWellFormedException( QStringLiteral( "No GmlObjectId element correctly parse against typeName '%1'" ).arg( typeName ) );
95131
}
96132
request.setFlags( QgsFeatureRequest::NoFlags );
97133
return request;

0 commit comments

Comments
 (0)
Please sign in to comment.