wfs-server-1_7-V3.patch
src/core/qgsgeometry.cpp | ||
---|---|---|
4101 | 4101 |
} |
4102 | 4102 |
} |
4103 | 4103 | |
4104 |
QString QgsGeometry::exportToGeoJSON() |
|
4105 |
{ |
|
4106 |
QgsDebugMsg( "entered." ); |
|
4107 | ||
4108 |
// TODO: implement with GEOS |
|
4109 |
if ( mDirtyWkb ) |
|
4110 |
{ |
|
4111 |
exportGeosToWkb(); |
|
4112 |
} |
|
4113 | ||
4114 |
if ( !mGeometry ) |
|
4115 |
{ |
|
4116 |
QgsDebugMsg( "WKB geometry not available!" ); |
|
4117 |
return QString::null; |
|
4118 |
} |
|
4119 | ||
4120 |
QGis::WkbType wkbType; |
|
4121 |
bool hasZValue = false; |
|
4122 |
double *x, *y; |
|
4123 | ||
4124 |
QString mWkt; // TODO: rename |
|
4125 | ||
4126 |
// Will this really work when mGeometry[0] == 0 ???? I (gavin) think not. |
|
4127 |
//wkbType = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4]; |
|
4128 |
memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) ); |
|
4129 | ||
4130 |
switch ( wkbType ) |
|
4131 |
{ |
|
4132 |
case QGis::WKBPoint25D: |
|
4133 |
case QGis::WKBPoint: |
|
4134 |
{ |
|
4135 |
mWkt += "{ \"type\": \"Point\", \"coordinates\": ["; |
|
4136 |
x = ( double * )( mGeometry + 5 ); |
|
4137 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4138 |
mWkt += ", "; |
|
4139 |
y = ( double * )( mGeometry + 5 + sizeof( double ) ); |
|
4140 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4141 |
mWkt += "] }"; |
|
4142 |
return mWkt; |
|
4143 |
} |
|
4144 | ||
4145 |
case QGis::WKBLineString25D: |
|
4146 |
hasZValue = true; |
|
4147 |
case QGis::WKBLineString: |
|
4148 |
{ |
|
4149 |
QgsDebugMsg( "LINESTRING found" ); |
|
4150 |
unsigned char *ptr; |
|
4151 |
int *nPoints; |
|
4152 |
int idx; |
|
4153 | ||
4154 |
mWkt += "{ \"type\": \"LineString\", \"coordinates\": [ "; |
|
4155 |
// get number of points in the line |
|
4156 |
ptr = mGeometry + 5; |
|
4157 |
nPoints = ( int * ) ptr; |
|
4158 |
ptr = mGeometry + 1 + 2 * sizeof( int ); |
|
4159 |
for ( idx = 0; idx < *nPoints; ++idx ) |
|
4160 |
{ |
|
4161 |
if ( idx != 0 ) |
|
4162 |
{ |
|
4163 |
mWkt += ", "; |
|
4164 |
} |
|
4165 |
mWkt += "["; |
|
4166 |
x = ( double * ) ptr; |
|
4167 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4168 |
mWkt += ", "; |
|
4169 |
ptr += sizeof( double ); |
|
4170 |
y = ( double * ) ptr; |
|
4171 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4172 |
ptr += sizeof( double ); |
|
4173 |
if ( hasZValue ) |
|
4174 |
{ |
|
4175 |
ptr += sizeof( double ); |
|
4176 |
} |
|
4177 |
mWkt += "]"; |
|
4178 |
} |
|
4179 |
mWkt += " ] }"; |
|
4180 |
return mWkt; |
|
4181 |
} |
|
4182 | ||
4183 |
case QGis::WKBPolygon25D: |
|
4184 |
hasZValue = true; |
|
4185 |
case QGis::WKBPolygon: |
|
4186 |
{ |
|
4187 |
QgsDebugMsg( "POLYGON found" ); |
|
4188 |
unsigned char *ptr; |
|
4189 |
int idx, jdx; |
|
4190 |
int *numRings, *nPoints; |
|
4191 | ||
4192 |
mWkt += "{ \"type\": \"Polygon\", \"coordinates\": [ "; |
|
4193 |
// get number of rings in the polygon |
|
4194 |
numRings = ( int * )( mGeometry + 1 + sizeof( int ) ); |
|
4195 |
if ( !( *numRings ) ) // sanity check for zero rings in polygon |
|
4196 |
{ |
|
4197 |
return QString(); |
|
4198 |
} |
|
4199 |
int *ringStart; // index of first point for each ring |
|
4200 |
int *ringNumPoints; // number of points in each ring |
|
4201 |
ringStart = new int[*numRings]; |
|
4202 |
ringNumPoints = new int[*numRings]; |
|
4203 |
ptr = mGeometry + 1 + 2 * sizeof( int ); // set pointer to the first ring |
|
4204 |
for ( idx = 0; idx < *numRings; idx++ ) |
|
4205 |
{ |
|
4206 |
if ( idx != 0 ) |
|
4207 |
{ |
|
4208 |
mWkt += ", "; |
|
4209 |
} |
|
4210 |
mWkt += "[ "; |
|
4211 |
// get number of points in the ring |
|
4212 |
nPoints = ( int * ) ptr; |
|
4213 |
ringNumPoints[idx] = *nPoints; |
|
4214 |
ptr += 4; |
|
4215 | ||
4216 |
for ( jdx = 0; jdx < *nPoints; jdx++ ) |
|
4217 |
{ |
|
4218 |
if ( jdx != 0 ) |
|
4219 |
{ |
|
4220 |
mWkt += ", "; |
|
4221 |
} |
|
4222 |
mWkt += "["; |
|
4223 |
x = ( double * ) ptr; |
|
4224 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4225 |
mWkt += ", "; |
|
4226 |
ptr += sizeof( double ); |
|
4227 |
y = ( double * ) ptr; |
|
4228 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4229 |
ptr += sizeof( double ); |
|
4230 |
if ( hasZValue ) |
|
4231 |
{ |
|
4232 |
ptr += sizeof( double ); |
|
4233 |
} |
|
4234 |
mWkt += "]"; |
|
4235 |
} |
|
4236 |
mWkt += " ]"; |
|
4237 |
} |
|
4238 |
mWkt += " ] }"; |
|
4239 |
delete [] ringStart; |
|
4240 |
delete [] ringNumPoints; |
|
4241 |
return mWkt; |
|
4242 |
} |
|
4243 | ||
4244 |
case QGis::WKBMultiPoint25D: |
|
4245 |
hasZValue = true; |
|
4246 |
case QGis::WKBMultiPoint: |
|
4247 |
{ |
|
4248 |
unsigned char *ptr; |
|
4249 |
int idx; |
|
4250 |
int *nPoints; |
|
4251 | ||
4252 |
mWkt += "{ \"type\": \"MultiPoint\", \"coordinates\": [ "; |
|
4253 |
nPoints = ( int* )( mGeometry + 5 ); |
|
4254 |
ptr = mGeometry + 5 + sizeof( int ); |
|
4255 |
for ( idx = 0; idx < *nPoints; ++idx ) |
|
4256 |
{ |
|
4257 |
ptr += ( 1 + sizeof( int ) ); |
|
4258 |
if ( idx != 0 ) |
|
4259 |
{ |
|
4260 |
mWkt += ", "; |
|
4261 |
} |
|
4262 |
mWkt += "["; |
|
4263 |
x = ( double * )( ptr ); |
|
4264 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4265 |
mWkt += ", "; |
|
4266 |
ptr += sizeof( double ); |
|
4267 |
y = ( double * )( ptr ); |
|
4268 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4269 |
ptr += sizeof( double ); |
|
4270 |
if ( hasZValue ) |
|
4271 |
{ |
|
4272 |
ptr += sizeof( double ); |
|
4273 |
} |
|
4274 |
mWkt += "]"; |
|
4275 |
} |
|
4276 |
mWkt += " ] }"; |
|
4277 |
return mWkt; |
|
4278 |
} |
|
4279 | ||
4280 |
case QGis::WKBMultiLineString25D: |
|
4281 |
hasZValue = true; |
|
4282 |
case QGis::WKBMultiLineString: |
|
4283 |
{ |
|
4284 |
QgsDebugMsg( "MULTILINESTRING found" ); |
|
4285 |
unsigned char *ptr; |
|
4286 |
int idx, jdx, numLineStrings; |
|
4287 |
int *nPoints; |
|
4288 | ||
4289 |
mWkt += "{ \"type\": \"MultiLineString\", \"coordinates\": [ "; |
|
4290 |
numLineStrings = ( int )( mGeometry[5] ); |
|
4291 |
ptr = mGeometry + 9; |
|
4292 |
for ( jdx = 0; jdx < numLineStrings; jdx++ ) |
|
4293 |
{ |
|
4294 |
if ( jdx != 0 ) |
|
4295 |
{ |
|
4296 |
mWkt += ", "; |
|
4297 |
} |
|
4298 |
mWkt += "[ "; |
|
4299 |
ptr += 5; // skip type since we know its 2 |
|
4300 |
nPoints = ( int * ) ptr; |
|
4301 |
ptr += sizeof( int ); |
|
4302 |
for ( idx = 0; idx < *nPoints; idx++ ) |
|
4303 |
{ |
|
4304 |
if ( idx != 0 ) |
|
4305 |
{ |
|
4306 |
mWkt += ", "; |
|
4307 |
} |
|
4308 |
mWkt += "["; |
|
4309 |
x = ( double * ) ptr; |
|
4310 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4311 |
ptr += sizeof( double ); |
|
4312 |
mWkt += ", "; |
|
4313 |
y = ( double * ) ptr; |
|
4314 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4315 |
ptr += sizeof( double ); |
|
4316 |
if ( hasZValue ) |
|
4317 |
{ |
|
4318 |
ptr += sizeof( double ); |
|
4319 |
} |
|
4320 |
mWkt += "]"; |
|
4321 |
} |
|
4322 |
mWkt += " ]"; |
|
4323 |
} |
|
4324 |
mWkt += " ] }"; |
|
4325 |
return mWkt; |
|
4326 |
} |
|
4327 | ||
4328 |
case QGis::WKBMultiPolygon25D: |
|
4329 |
hasZValue = true; |
|
4330 |
case QGis::WKBMultiPolygon: |
|
4331 |
{ |
|
4332 |
QgsDebugMsg( "MULTIPOLYGON found" ); |
|
4333 |
unsigned char *ptr; |
|
4334 |
int idx, jdx, kdx; |
|
4335 |
int *numPolygons, *numRings, *nPoints; |
|
4336 | ||
4337 |
mWkt += "{ \"type\": \"MultiPolygon\", \"coordinates\": [ "; |
|
4338 |
ptr = mGeometry + 5; |
|
4339 |
numPolygons = ( int * ) ptr; |
|
4340 |
ptr = mGeometry + 9; |
|
4341 |
for ( kdx = 0; kdx < *numPolygons; kdx++ ) |
|
4342 |
{ |
|
4343 |
if ( kdx != 0 ) |
|
4344 |
{ |
|
4345 |
mWkt += ", "; |
|
4346 |
} |
|
4347 |
mWkt += "[ "; |
|
4348 |
ptr += 5; |
|
4349 |
numRings = ( int * ) ptr; |
|
4350 |
ptr += 4; |
|
4351 |
for ( idx = 0; idx < *numRings; idx++ ) |
|
4352 |
{ |
|
4353 |
if ( idx != 0 ) |
|
4354 |
{ |
|
4355 |
mWkt += ", "; |
|
4356 |
} |
|
4357 |
mWkt += "[ "; |
|
4358 |
nPoints = ( int * ) ptr; |
|
4359 |
ptr += 4; |
|
4360 |
for ( jdx = 0; jdx < *nPoints; jdx++ ) |
|
4361 |
{ |
|
4362 |
if ( jdx != 0 ) |
|
4363 |
{ |
|
4364 |
mWkt += ", "; |
|
4365 |
} |
|
4366 |
mWkt += "["; |
|
4367 |
x = ( double * ) ptr; |
|
4368 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4369 |
ptr += sizeof( double ); |
|
4370 |
mWkt += ", "; |
|
4371 |
y = ( double * ) ptr; |
|
4372 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4373 |
ptr += sizeof( double ); |
|
4374 |
if ( hasZValue ) |
|
4375 |
{ |
|
4376 |
ptr += sizeof( double ); |
|
4377 |
} |
|
4378 |
mWkt += "]"; |
|
4379 |
} |
|
4380 |
mWkt += " ]"; |
|
4381 |
} |
|
4382 |
mWkt += " ]"; |
|
4383 |
} |
|
4384 |
mWkt += " ] }"; |
|
4385 |
return mWkt; |
|
4386 |
} |
|
4387 | ||
4388 |
default: |
|
4389 |
QgsDebugMsg( "error: mGeometry type not recognized" ); |
|
4390 |
return QString::null; |
|
4391 |
} |
|
4392 |
} |
|
4393 | ||
4104 | 4394 |
bool QgsGeometry::exportWkbToGeos() |
4105 | 4395 |
{ |
4106 | 4396 |
QgsDebugMsgLevel( "entered.", 3 ); |
src/core/qgsgeometry.h | ||
---|---|---|
360 | 360 |
*/ |
361 | 361 |
QString exportToWkt(); |
362 | 362 | |
363 |
/** Exports the geometry to mGeoJSON |
|
364 |
@return true in case of success and false else |
|
365 |
*/ |
|
366 |
QString exportToGeoJSON(); |
|
367 | ||
363 | 368 |
/* Accessor functions for getting geometry data */ |
364 | 369 | |
365 | 370 |
/** return contents of the geometry as a point |
src/mapserver/CMakeLists.txt | ||
---|---|---|
27 | 27 |
qgssldparser.cpp |
28 | 28 |
qgssldrenderer.cpp |
29 | 29 |
qgswmsserver.cpp |
30 |
qgswfsserver.cpp |
|
30 | 31 |
qgsmapserviceexception.cpp |
31 | 32 |
qgsmapserverlogger.cpp |
32 | 33 |
qgsmslayercache.cpp |
src/mapserver/qgis_map_serv.cpp | ||
---|---|---|
28 | 28 |
#include "qgsmapserviceexception.h" |
29 | 29 |
#include "qgsprojectparser.h" |
30 | 30 |
#include "qgssldparser.h" |
31 |
#include "qgswfsserver.h" |
|
31 | 32 |
#include <QDomDocument> |
32 | 33 |
#include <QImage> |
33 | 34 |
#include <QSettings> |
... | ... | |
264 | 265 |
} |
265 | 266 | |
266 | 267 |
QgsWMSServer* theServer = 0; |
268 |
if ( serviceIt->second == "WFS" ) |
|
269 |
{ |
|
270 |
delete theServer; |
|
271 |
QgsWFSServer* theServer = 0; |
|
272 |
try |
|
273 |
{ |
|
274 |
theServer = new QgsWFSServer( parameterMap ); |
|
275 |
} |
|
276 |
catch ( QgsMapServiceException e ) //admin.sld may be invalid |
|
277 |
{ |
|
278 |
theRequestHandler->sendServiceException( e ); |
|
279 |
continue; |
|
280 |
} |
|
281 | ||
282 |
theServer->setAdminConfigParser( adminConfigParser ); |
|
283 | ||
284 | ||
285 |
//request type |
|
286 |
std::map<QString, QString>::const_iterator requestIt = parameterMap.find( "REQUEST" ); |
|
287 |
if ( requestIt == parameterMap.end() ) |
|
288 |
{ |
|
289 |
//do some error handling |
|
290 |
QgsMSDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); |
|
291 |
theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); |
|
292 |
delete theRequestHandler; |
|
293 |
delete theServer; |
|
294 |
continue; |
|
295 |
} |
|
296 | ||
297 |
if ( requestIt->second == "GetCapabilities" ) |
|
298 |
{ |
|
299 |
QDomDocument capabilitiesDocument; |
|
300 |
try |
|
301 |
{ |
|
302 |
capabilitiesDocument = theServer->getCapabilities(); |
|
303 |
} |
|
304 |
catch ( QgsMapServiceException& ex ) |
|
305 |
{ |
|
306 |
theRequestHandler->sendServiceException( ex ); |
|
307 |
delete theRequestHandler; |
|
308 |
delete theServer; |
|
309 |
continue; |
|
310 |
} |
|
311 |
QgsMSDebugMsg( "sending GetCapabilities response" ); |
|
312 |
theRequestHandler->sendGetCapabilitiesResponse( capabilitiesDocument ); |
|
313 |
delete theRequestHandler; |
|
314 |
delete theServer; |
|
315 |
continue; |
|
316 |
} |
|
317 |
else if ( requestIt->second == "DescribeFeatureType" ) |
|
318 |
{ |
|
319 |
QDomDocument describeDocument; |
|
320 |
try |
|
321 |
{ |
|
322 |
describeDocument = theServer->describeFeatureType(); |
|
323 |
} |
|
324 |
catch ( QgsMapServiceException& ex ) |
|
325 |
{ |
|
326 |
theRequestHandler->sendServiceException( ex ); |
|
327 |
delete theRequestHandler; |
|
328 |
delete theServer; |
|
329 |
continue; |
|
330 |
} |
|
331 |
QgsMSDebugMsg( "sending GetCapabilities response" ); |
|
332 |
theRequestHandler->sendGetCapabilitiesResponse( describeDocument ); |
|
333 |
delete theRequestHandler; |
|
334 |
delete theServer; |
|
335 |
continue; |
|
336 |
} |
|
337 |
else if ( requestIt->second == "GetFeature" ) |
|
338 |
{ |
|
339 |
//output format for GetFeature |
|
340 |
QString outputFormat; |
|
341 |
std::map<QString, QString>::const_iterator p_it = parameterMap.find( "OUTPUTFORMAT" ); |
|
342 |
if ( p_it != parameterMap.end() ) |
|
343 |
{ |
|
344 |
outputFormat = p_it->second; |
|
345 |
} |
|
346 | ||
347 |
try |
|
348 |
{ |
|
349 |
if ( theServer->getFeature( *theRequestHandler, outputFormat ) != 0 ) |
|
350 |
{ |
|
351 |
delete theRequestHandler; |
|
352 |
delete theServer; |
|
353 |
continue; |
|
354 |
} else { |
|
355 |
delete theRequestHandler; |
|
356 |
delete theServer; |
|
357 |
continue; |
|
358 |
} |
|
359 |
} |
|
360 |
catch ( QgsMapServiceException& ex ) |
|
361 |
{ |
|
362 |
theRequestHandler->sendServiceException( ex ); |
|
363 |
delete theRequestHandler; |
|
364 |
delete theServer; |
|
365 |
continue; |
|
366 |
} |
|
367 |
} |
|
368 | ||
369 |
return 0; |
|
370 |
} |
|
371 |
else |
|
372 |
{ |
|
267 | 373 |
try |
268 | 374 |
{ |
269 | 375 |
theServer = new QgsWMSServer( parameterMap, theMapRenderer ); |
... | ... | |
273 | 379 |
theRequestHandler->sendServiceException( e ); |
274 | 380 |
continue; |
275 | 381 |
} |
382 |
} |
|
276 | 383 | |
277 | 384 |
theServer->setAdminConfigParser( adminConfigParser ); |
278 | 385 |
src/mapserver/qgsconfigparser.h | ||
---|---|---|
40 | 40 |
/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.*/ |
41 | 41 |
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc ) const = 0; |
42 | 42 | |
43 |
virtual void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const = 0; |
|
44 | ||
43 | 45 |
/**Returns one or possibly several maplayers for a given layer name and style. If there are several layers, the layers should be drawn in inverse list order. |
44 | 46 |
If no layers/style are found, an empty list is returned*/ |
45 | 47 |
virtual QList<QgsMapLayer*> mapLayerFromStyle( const QString& layerName, const QString& styleName, bool allowCaching = true ) const = 0; |
src/mapserver/qgsgetrequesthandler.cpp | ||
---|---|---|
11 | 11 |
#include <QImage> |
12 | 12 |
#include <QStringList> |
13 | 13 |
#include <QUrl> |
14 |
#include <fcgi_stdio.h> |
|
14 | 15 | |
15 | 16 |
QgsGetRequestHandler::QgsGetRequestHandler(): QgsHttpRequestHandler() |
16 | 17 |
{ |
... | ... | |
306 | 307 |
{ |
307 | 308 |
sendHttpResponse( ba, formatToMimeType( mFormat ) ); |
308 | 309 |
} |
310 | ||
311 |
bool QgsGetRequestHandler::startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const |
|
312 |
{ |
|
313 |
if ( !ba ) |
|
314 |
{ |
|
315 |
return false; |
|
316 |
} |
|
317 | ||
318 |
if ( ba->size() < 1 ) |
|
319 |
{ |
|
320 |
return false; |
|
321 |
} |
|
322 | ||
323 |
QString format; |
|
324 |
if (infoFormat == "GeoJSON") |
|
325 |
format = "text/plain"; |
|
326 |
else |
|
327 |
format = "text/xml"; |
|
328 | ||
329 |
printf( "Content-Type: " ); |
|
330 |
printf( format.toLocal8Bit() ); |
|
331 |
printf( "\n" ); |
|
332 |
printf( "\n" ); |
|
333 |
fwrite( ba->data(), ba->size(), 1, FCGI_stdout ); |
|
334 |
return true; |
|
335 |
} |
|
336 | ||
337 |
void QgsGetRequestHandler::sendGetFeatureResponse( QByteArray* ba ) const |
|
338 |
{ |
|
339 |
if ( !ba ) |
|
340 |
{ |
|
341 |
return; |
|
342 |
} |
|
343 | ||
344 |
if ( ba->size() < 1 ) |
|
345 |
{ |
|
346 |
return; |
|
347 |
} |
|
348 |
fwrite( ba->data(), ba->size(), 1, FCGI_stdout ); |
|
349 |
} |
|
350 | ||
351 |
void QgsGetRequestHandler::endGetFeatureResponse( QByteArray* ba ) const |
|
352 |
{ |
|
353 |
if ( !ba ) |
|
354 |
{ |
|
355 |
return; |
|
356 |
} |
|
357 | ||
358 |
fwrite( ba->data(), ba->size(), 1, FCGI_stdout ); |
|
359 |
} |
src/mapserver/qgsgetrequesthandler.h | ||
---|---|---|
30 | 30 |
void sendServiceException( const QgsMapServiceException& ex ) const; |
31 | 31 |
void sendGetStyleResponse( const QDomDocument& doc ) const; |
32 | 32 |
void sendGetPrintResponse( QByteArray* ba ) const; |
33 |
bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const; |
|
34 |
void sendGetFeatureResponse( QByteArray* ba ) const; |
|
35 |
void endGetFeatureResponse( QByteArray* ba ) const; |
|
33 | 36 |
}; |
src/mapserver/qgsprojectparser.cpp | ||
---|---|---|
115 | 115 |
parentElement.appendChild( layerParentElem ); |
116 | 116 |
} |
117 | 117 | |
118 |
void QgsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const |
|
119 |
{ |
|
120 |
QList<QDomElement> layerElems = projectLayerElements(); |
|
121 | ||
122 |
QStringList nonIdentifiableLayers = identifyDisabledLayers(); |
|
123 | ||
124 |
if ( layerElems.size() < 1 ) |
|
125 |
{ |
|
126 |
return; |
|
127 |
} |
|
128 | ||
129 |
QMap<QString, QgsMapLayer *> layerMap; |
|
130 | ||
131 |
QList<QDomElement>::const_iterator layerIt = layerElems.constBegin(); |
|
132 |
for ( ; layerIt != layerElems.constEnd(); ++layerIt ) |
|
133 |
{ |
|
134 |
QDomElement elem = *layerIt; |
|
135 |
QString type = elem.attribute( "type" ); |
|
136 |
if ( type == "vector" ) |
|
137 |
{ |
|
138 |
QgsMapLayer *layer = createLayerFromElement( *layerIt ); |
|
139 |
if ( layer ) |
|
140 |
{ |
|
141 |
QgsMSDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) ); |
|
142 |
layerMap.insert( layer->id(), layer ); |
|
143 | ||
144 |
QDomElement layerElem = doc.createElement( "FeatureType" ); |
|
145 |
QDomElement nameElem = doc.createElement( "Name" ); |
|
146 |
//We use the layer name even though it might not be unique. |
|
147 |
//Because the id sometimes contains user/pw information and the name is more descriptive |
|
148 |
QDomText nameText = doc.createTextNode( layer->name() ); |
|
149 |
nameElem.appendChild( nameText ); |
|
150 |
layerElem.appendChild( nameElem ); |
|
151 | ||
152 |
QDomElement titleElem = doc.createElement( "Title" ); |
|
153 |
QDomText titleText = doc.createTextNode( layer->name() ); |
|
154 |
titleElem.appendChild( titleText ); |
|
155 |
layerElem.appendChild( titleElem ); |
|
156 | ||
157 |
//appendExGeographicBoundingBox( layerElem, doc, layer->extent(), layer->crs() ); |
|
158 | ||
159 |
QDomElement srsElem = doc.createElement( "SRS" ); |
|
160 |
QDomText srsText = doc.createTextNode( layer->crs().authid() ); |
|
161 |
srsElem.appendChild( srsText ); |
|
162 |
layerElem.appendChild( srsElem ); |
|
163 | ||
164 |
QgsRectangle layerExtent = layer->extent(); |
|
165 |
QDomElement bBoxElement = doc.createElement( "LatLongBoundingBox" ); |
|
166 |
bBoxElement.setAttribute( "minx", QString::number( layerExtent.xMinimum() ) ); |
|
167 |
bBoxElement.setAttribute( "miny", QString::number( layerExtent.yMinimum() ) ); |
|
168 |
bBoxElement.setAttribute( "maxx", QString::number( layerExtent.xMaximum() ) ); |
|
169 |
bBoxElement.setAttribute( "maxy", QString::number( layerExtent.yMaximum() ) ); |
|
170 |
layerElem.appendChild( bBoxElement ); |
|
171 | ||
172 |
parentElement.appendChild(layerElem); |
|
173 |
} |
|
174 |
#if QGSMSDEBUG |
|
175 |
else |
|
176 |
{ |
|
177 |
QString buf; |
|
178 |
QTextStream s( &buf ); |
|
179 |
layerIt->save( s, 0 ); |
|
180 |
QgsMSDebugMsg( QString( "layer %1 not found" ).arg( buf ) ); |
|
181 |
} |
|
182 |
#endif |
|
183 |
} |
|
184 |
} |
|
185 |
return; |
|
186 |
} |
|
187 | ||
118 | 188 |
void QgsProjectParser::addLayers( QDomDocument &doc, |
119 | 189 |
QDomElement &parentElem, |
120 | 190 |
const QDomElement &legendElem, |
src/mapserver/qgsprojectparser.h | ||
---|---|---|
38 | 38 |
/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.*/ |
39 | 39 |
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc ) const; |
40 | 40 | |
41 |
virtual void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const; |
|
42 | ||
41 | 43 |
int numberOfLayers() const; |
42 | 44 | |
43 | 45 |
/**Returns one or possibly several maplayers for a given layer name and style. If no layers/style are found, an empty list is returned*/ |
src/mapserver/qgsrequesthandler.h | ||
---|---|---|
41 | 41 |
virtual void sendServiceException( const QgsMapServiceException& ex ) const = 0; |
42 | 42 |
virtual void sendGetStyleResponse( const QDomDocument& doc ) const = 0; |
43 | 43 |
virtual void sendGetPrintResponse( QByteArray* ba ) const = 0; |
44 |
virtual void sendGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const = 0; |
|
44 | 45 |
QString format() const { return mFormat; } |
45 | 46 |
protected: |
46 | 47 |
/**This is set by the parseInput methods of the subclasses (parameter FORMAT, e.g. 'FORMAT=PNG')*/ |
src/mapserver/qgssldparser.h | ||
---|---|---|
57 | 57 |
/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.*/ |
58 | 58 |
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc ) const; |
59 | 59 | |
60 |
void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const {}; |
|
61 | ||
60 | 62 |
/**Returns number of layers in configuration*/ |
61 | 63 |
int numberOfLayers() const; |
62 | 64 |
src/mapserver/qgssoaprequesthandler.h | ||
---|---|---|
35 | 35 |
void sendServiceException( const QgsMapServiceException& ex ) const; |
36 | 36 |
void sendGetStyleResponse( const QDomDocument& doc ) const; |
37 | 37 |
void sendGetPrintResponse( QByteArray* ba ) const; |
38 |
bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const { return false; }; |
|
39 |
void sendGetFeatureResponse( QByteArray* ba ) const {}; |
|
40 |
void endGetFeatureResponse( QByteArray* ba ) const {}; |
|
38 | 41 |
private: |
39 | 42 |
/**Parses the xml of a getMap request and fills the parameters into the map. Returns 0 in case of success*/ |
40 | 43 |
int parseGetMapElement( std::map<QString, QString>& parameterMap, const QDomElement& getMapElement ) const; |
src/mapserver/qgswfsserver.cpp | ||
---|---|---|
1 |
#include "qgswfsserver.h" |
|
2 |
#include "qgsconfigparser.h" |
|
3 |
#include "qgsepsgcache.h" |
|
4 |
#include "qgsfield.h" |
|
5 |
#include "qgsgeometry.h" |
|
6 |
#include "qgsmaplayer.h" |
|
7 |
#include "qgsmaplayerregistry.h" |
|
8 |
#include "qgsmaprenderer.h" |
|
9 |
#include "qgsmaptopixel.h" |
|
10 |
#include "qgspallabeling.h" |
|
11 |
#include "qgsproject.h" |
|
12 |
#include "qgsrasterlayer.h" |
|
13 |
#include "qgsscalecalculator.h" |
|
14 |
#include "qgscoordinatereferencesystem.h" |
|
15 |
#include "qgsvectordataprovider.h" |
|
16 |
#include "qgsvectorlayer.h" |
|
17 |
#include "qgsfilter.h" |
|
18 |
#include "qgsmapserverlogger.h" |
|
19 |
#include "qgsmapserviceexception.h" |
|
20 |
#include "qgssldparser.h" |
|
21 |
#include "qgssymbol.h" |
|
22 |
#include "qgssymbolv2.h" |
|
23 |
#include "qgsrenderer.h" |
|
24 |
#include "qgslegendmodel.h" |
|
25 |
#include "qgscomposerlegenditem.h" |
|
26 |
#include "qgslogger.h" |
|
27 |
#include "qgsrequesthandler.h" |
|
28 |
#include <QImage> |
|
29 |
#include <QPainter> |
|
30 |
#include <QStringList> |
|
31 |
#include <QTextStream> |
|
32 |
#include <QDir> |
|
33 | ||
34 |
//for printing |
|
35 |
#include "qgscomposition.h" |
|
36 |
#include <QBuffer> |
|
37 |
#include <QPrinter> |
|
38 |
#include <QSvgGenerator> |
|
39 |
#include <QUrl> |
|
40 |
#include <QPaintEngine> |
|
41 | ||
42 |
QgsWFSServer::QgsWFSServer( std::map<QString, QString> parameters ) |
|
43 |
: mParameterMap( parameters ) |
|
44 |
, mConfigParser( 0 ) |
|
45 |
{ |
|
46 |
} |
|
47 | ||
48 |
QgsWFSServer::~QgsWFSServer() |
|
49 |
{ |
|
50 |
} |
|
51 | ||
52 |
QgsWFSServer::QgsWFSServer() |
|
53 |
{ |
|
54 |
} |
|
55 | ||
56 |
QDomDocument QgsWFSServer::getCapabilities() |
|
57 |
{ |
|
58 |
QgsMSDebugMsg( "Entering." ); |
|
59 |
QDomDocument doc; |
|
60 |
//wfs:WFS_Capabilities element |
|
61 |
QDomElement wfsCapabilitiesElement = doc.createElement( "WFS_Capabilities"/*wms:WFS_Capabilities*/ ); |
|
62 |
wfsCapabilitiesElement.setAttribute( "xmlns", "http://www.opengis.net/wfs" ); |
|
63 |
wfsCapabilitiesElement.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); |
|
64 |
wfsCapabilitiesElement.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" ); |
|
65 |
wfsCapabilitiesElement.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" ); |
|
66 |
wfsCapabilitiesElement.setAttribute( "xmlns:gml", "http://www.opengis.net/gml" ); |
|
67 |
wfsCapabilitiesElement.setAttribute( "xmlns:ows", "http://www.opengis.net/ows" ); |
|
68 |
wfsCapabilitiesElement.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); |
|
69 |
wfsCapabilitiesElement.setAttribute( "version", "1.0.0" ); |
|
70 |
wfsCapabilitiesElement.setAttribute( "updateSequence", "0" ); |
|
71 |
doc.appendChild( wfsCapabilitiesElement ); |
|
72 | ||
73 |
if ( mConfigParser ) |
|
74 |
{ |
|
75 |
mConfigParser->serviceCapabilities( wfsCapabilitiesElement, doc ); |
|
76 |
} |
|
77 | ||
78 |
//wfs:Capability element |
|
79 |
QDomElement capabilityElement = doc.createElement( "Capability"/*wfs:Capability*/ ); |
|
80 |
wfsCapabilitiesElement.appendChild( capabilityElement ); |
|
81 |
|
|
82 |
//wfs:Request element |
|
83 |
QDomElement requestElement = doc.createElement( "Request"/*wfs:Request*/ ); |
|
84 |
capabilityElement.appendChild( requestElement ); |
|
85 |
//wfs:GetCapabilities |
|
86 |
QDomElement getCapabilitiesElement = doc.createElement( "GetCapabilities"/*wfs:GetCapabilities*/ ); |
|
87 |
requestElement.appendChild( getCapabilitiesElement ); |
|
88 |
QDomElement capabilitiesFormatElement = doc.createElement( "Format" );/*wfs:Format*/ |
|
89 |
getCapabilitiesElement.appendChild( capabilitiesFormatElement ); |
|
90 |
QDomText capabilitiesFormatText = doc.createTextNode( "text/xml" ); |
|
91 |
capabilitiesFormatElement.appendChild( capabilitiesFormatText ); |
|
92 | ||
93 |
QDomElement dcpTypeElement = doc.createElement( "DCPType"/*wfs:DCPType*/ ); |
|
94 |
getCapabilitiesElement.appendChild( dcpTypeElement ); |
|
95 |
QDomElement httpElement = doc.createElement( "HTTP"/*wfs:HTTP*/ ); |
|
96 |
dcpTypeElement.appendChild( httpElement ); |
|
97 | ||
98 |
//Prepare url |
|
99 |
//Some client requests already have http://<SERVER_NAME> in the REQUEST_URI variable |
|
100 |
QString hrefString; |
|
101 |
QString requestUrl = getenv( "REQUEST_URI" ); |
|
102 |
QUrl mapUrl( requestUrl ); |
|
103 |
mapUrl.setHost( QString( getenv( "SERVER_NAME" ) ) ); |
|
104 |
mapUrl.removeQueryItem( "REQUEST" ); |
|
105 |
mapUrl.removeQueryItem( "VERSION" ); |
|
106 |
mapUrl.removeQueryItem( "SERVICE" ); |
|
107 |
hrefString = mapUrl.toString(); |
|
108 | ||
109 |
//only Get supported for the moment |
|
110 |
QDomElement getElement = doc.createElement( "Get"/*wfs:Get*/ ); |
|
111 |
httpElement.appendChild( getElement ); |
|
112 |
QDomElement olResourceElement = doc.createElement( "OnlineResource"/*wfs:OnlineResource*/ ); |
|
113 |
olResourceElement.setAttribute( "xlink:type", "simple" ); |
|
114 |
requestUrl.truncate( requestUrl.indexOf( "?" ) + 1 ); |
|
115 |
olResourceElement.setAttribute( "xlink:href", hrefString ); |
|
116 |
getElement.appendChild( olResourceElement ); |
|
117 | ||
118 |
//wfs:DescribeFeatureType |
|
119 |
QDomElement describeFeatureTypeElement = doc.createElement( "DescribeFeatureType"/*wfs:DescribeFeatureType*/ ); |
|
120 |
requestElement.appendChild( describeFeatureTypeElement ); |
|
121 |
QDomElement schemaDescriptionLanguageElement = doc.createElement( "SchemaDescriptionLanguage"/*wfs:SchemaDescriptionLanguage*/ ); |
|
122 |
describeFeatureTypeElement.appendChild( schemaDescriptionLanguageElement ); |
|
123 |
QDomElement xmlSchemaElement = doc.createElement( "XMLSCHEMA"/*wfs:XMLSCHEMA*/ ); |
|
124 |
schemaDescriptionLanguageElement.appendChild( xmlSchemaElement ); |
|
125 |
QDomElement describeFeatureTypeDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' |
|
126 |
describeFeatureTypeElement.appendChild( describeFeatureTypeDhcTypeElement ); |
|
127 | ||
128 |
//wfs:GetFeature |
|
129 |
QDomElement getFeatureElement = doc.createElement( "GetFeature"/*wfs:GetFeature*/ ); |
|
130 |
requestElement.appendChild( getFeatureElement ); |
|
131 |
QDomElement getFeatureFormatElement = doc.createElement( "ResultFormat" );/*wfs:ResultFormat*/ |
|
132 |
getFeatureElement.appendChild( getFeatureFormatElement ); |
|
133 |
QDomElement gmlFormatElement = doc.createElement( "GML2" );/*wfs:GML2*/ |
|
134 |
getFeatureFormatElement.appendChild( gmlFormatElement ); |
|
135 |
QDomElement geojsonFormatElement = doc.createElement( "GeoJSON" );/*wfs:GeoJSON*/ |
|
136 |
getFeatureFormatElement.appendChild( geojsonFormatElement ); |
|
137 |
QDomElement getFeatureDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' |
|
138 |
getFeatureElement.appendChild( getFeatureDhcTypeElement ); |
|
139 | ||
140 |
//wfs:FeatureTypeList element |
|
141 |
QDomElement featureTypeListElement = doc.createElement( "FeatureTypeList"/*wfs:FeatureTypeList*/ ); |
|
142 |
capabilityElement.appendChild( featureTypeListElement ); |
|
143 |
//wfs:Operations element |
|
144 |
QDomElement operationsElement = doc.createElement( "Operations"/*wfs:Operations*/ ); |
|
145 |
featureTypeListElement.appendChild( operationsElement ); |
|
146 |
//wfs:Query element |
|
147 |
QDomElement queryElement = doc.createElement( "Query"/*wfs:Query*/ ); |
|
148 |
operationsElement.appendChild( queryElement ); |
|
149 |
/* |
|
150 |
* Adding layer liste in featureTypeListElement |
|
151 |
*/ |
|
152 |
if ( mConfigParser ) |
|
153 |
{ |
|
154 |
mConfigParser->featureTypeList( featureTypeListElement, doc ); |
|
155 |
} |
|
156 | ||
157 |
/* |
|
158 |
* Adding ogc:Filter_Capabilities in capabilityElement |
|
159 |
*/ |
|
160 |
//ogc:Filter_Capabilities element |
|
161 |
QDomElement filterCapabilitiesElement = doc.createElement( "ogc:Filter_Capabilities"/*ogc:Filter_Capabilities*/ ); |
|
162 |
capabilityElement.appendChild( filterCapabilitiesElement ); |
|
163 |
QDomElement spatialCapabilitiesElement = doc.createElement( "ogc:Spatial_Capabilities"/*ogc:Spatial_Capabilities*/ ); |
|
164 |
filterCapabilitiesElement.appendChild( spatialCapabilitiesElement ); |
|
165 |
QDomElement spatialOperatorsElement = doc.createElement( "ogc:Spatial_Operators"/*ogc:Spatial_Operators*/ ); |
|
166 |
spatialCapabilitiesElement.appendChild( spatialOperatorsElement ); |
|
167 |
QDomElement ogcBboxElement = doc.createElement( "ogc:BBOX"/*ogc:BBOX*/ ); |
|
168 |
spatialOperatorsElement.appendChild( ogcBboxElement ); |
|
169 |
QDomElement scalarCapabilitiesElement = doc.createElement( "ogc:Scalar_Capabilities"/*ogc:Scalar_Capabilities*/ ); |
|
170 |
filterCapabilitiesElement.appendChild( scalarCapabilitiesElement ); |
|
171 |
QDomElement comparisonOperatorsElement = doc.createElement( "ogc:Comparison_Operators"/*ogc:Comparison_Operators*/ ); |
|
172 |
scalarCapabilitiesElement.appendChild( comparisonOperatorsElement ); |
|
173 |
QDomElement simpleComparisonsElement = doc.createElement( "ogc:Simple_Comparisons"/*ogc:Simple_Comparisons*/ ); |
|
174 |
comparisonOperatorsElement.appendChild( simpleComparisonsElement ); |
|
175 |
return doc; |
|
176 |
} |
|
177 | ||
178 |
QDomDocument QgsWFSServer::describeFeatureType() |
|
179 |
{ |
|
180 |
QgsMSDebugMsg( "Entering." ); |
|
181 |
QDomDocument doc; |
|
182 |
//xsd:schema |
|
183 |
QDomElement schemaElement = doc.createElement( "schema"/*xsd:schema*/ ); |
|
184 |
schemaElement.setAttribute( "xmlns", "http://www.w3.org/2001/XMLSchema" ); |
|
185 |
schemaElement.setAttribute( "xmlns:xsd", "http://www.w3.org/2001/XMLSchema" ); |
|
186 |
schemaElement.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" ); |
|
187 |
schemaElement.setAttribute( "xmlns:gml", "http://www.opengis.net/gml" ); |
|
188 |
schemaElement.setAttribute( "xmlns:qgs", "http://www.qgis.org/gml" ); |
|
189 |
schemaElement.setAttribute( "targetNamespace", "http://www.qgis.org/gml" ); |
|
190 |
doc.appendChild( schemaElement ); |
|
191 | ||
192 |
//xsd:import |
|
193 |
QDomElement importElement = doc.createElement( "import"/*xsd:import*/ ); |
|
194 |
importElement.setAttribute( "namespace", "http://www.opengis.net/gml" ); |
|
195 |
importElement.setAttribute( "schemaLocation", "http://schemas.opengis.net/gml/2.1.2/feature.xsd" ); |
|
196 |
schemaElement.appendChild( importElement ); |
|
197 | ||
198 |
//read TYPENAME |
|
199 |
QString typeName; |
|
200 |
std::map<QString, QString>::const_iterator type_name_it = mParameterMap.find( "TYPENAME" ); |
|
201 |
if ( type_name_it != mParameterMap.end() ) |
|
202 |
{ |
|
203 |
typeName = type_name_it->second; |
|
204 |
} |
|
205 |
else |
|
206 |
{ |
|
207 |
return doc; |
|
208 |
} |
|
209 | ||
210 |
QStringList nonIdentifiableLayers = mConfigParser->identifyDisabledLayers(); |
|
211 |
QMap< QString, QMap< int, QString > > aliasInfo = mConfigParser->layerAliasInfo(); |
|
212 |
QMap< QString, QSet<QString> > hiddenAttributes = mConfigParser->hiddenAttributes(); |
|
213 |
|
|
214 |
QList<QgsMapLayer*> layerList; |
|
215 |
QgsMapLayer* currentLayer = 0; |
|
216 | ||
217 |
layerList = mConfigParser->mapLayerFromStyle( typeName, "" ); |
|
218 |
currentLayer = layerList.at( 0 ); |
|
219 |
|
|
220 |
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer ); |
|
221 |
if ( layer ) |
|
222 |
{ |
|
223 |
//is there alias info for this vector layer? |
|
224 |
QMap< int, QString > layerAliasInfo; |
|
225 |
QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() ); |
|
226 |
if ( aliasIt != aliasInfo.constEnd() ) |
|
227 |
{ |
|
228 |
layerAliasInfo = aliasIt.value(); |
|
229 |
} |
|
230 | ||
231 |
//hidden attributes for this layer |
|
232 |
QSet<QString> layerHiddenAttributes; |
|
233 |
QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() ); |
|
234 |
if ( hiddenIt != hiddenAttributes.constEnd() ) |
|
235 |
{ |
|
236 |
layerHiddenAttributes = hiddenIt.value(); |
|
237 |
} |
|
238 |
|
|
239 |
//do a select with searchRect and go through all the features |
|
240 |
QgsVectorDataProvider* provider = layer->dataProvider(); |
|
241 |
if ( !provider ) |
|
242 |
{ |
|
243 |
return doc; |
|
244 |
} |
|
245 | ||
246 |
typeName = typeName.replace( QString(" "), QString("_") ); |
|
247 |
|
|
248 |
//xsd:element |
|
249 |
QDomElement elementElem = doc.createElement( "element"/*xsd:element*/ ); |
|
250 |
elementElem.setAttribute( "name", typeName ); |
|
251 |
elementElem.setAttribute( "type", "qgs:" + typeName + "Type" ); |
|
252 |
elementElem.setAttribute( "substitutionGroup", "gml:_Feature" ); |
|
253 |
schemaElement.appendChild( elementElem ); |
|
254 | ||
255 |
//xsd:complexType |
|
256 |
QDomElement complexTypeElem = doc.createElement( "complexType"/*xsd:complexType*/ ); |
|
257 |
complexTypeElem.setAttribute( "name", typeName + "Type" ); |
|
258 |
schemaElement.appendChild( complexTypeElem ); |
|
259 | ||
260 |
//xsd:complexType |
|
261 |
QDomElement complexContentElem = doc.createElement( "complexContent"/*xsd:complexContent*/ ); |
|
262 |
complexTypeElem.appendChild( complexContentElem ); |
|
263 | ||
264 |
//xsd:extension |
|
265 |
QDomElement extensionElem = doc.createElement( "extension"/*xsd:extension*/ ); |
|
266 |
extensionElem.setAttribute( "base", "gml:AbstractFeatureType" ); |
|
267 |
complexContentElem.appendChild( extensionElem ); |
|
268 | ||
269 |
//xsd:sequence |
|
270 |
QDomElement sequenceElem = doc.createElement( "sequence"/*xsd:sequence*/ ); |
|
271 |
extensionElem.appendChild( sequenceElem ); |
|
272 | ||
273 |
//xsd:element |
|
274 |
QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ ); |
|
275 |
geomElem.setAttribute( "name", "geometry" ); |
|
276 |
geomElem.setAttribute( "type", "gml:GeometryPropertyType" ); |
|
277 |
geomElem.setAttribute( "minOccurs", "0" ); |
|
278 |
geomElem.setAttribute( "maxOccurs", "1" ); |
|
279 |
sequenceElem.appendChild( geomElem ); |
|
280 | ||
281 |
const QgsFieldMap& fields = provider->fields(); |
|
282 |
for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it ) |
|
283 |
{ |
|
284 | ||
285 |
QString attributeName = it.value().name(); |
|
286 |
//skip attribute if it has edit type 'hidden' |
|
287 |
if ( layerHiddenAttributes.contains( attributeName ) ) |
|
288 |
{ |
|
289 |
continue; |
|
290 |
} |
|
291 | ||
292 |
//check if the attribute name should be replaced with an alias |
|
293 |
QMap<int, QString>::const_iterator aliasIt = layerAliasInfo.find( it.key() ); |
|
294 |
if ( aliasIt != layerAliasInfo.constEnd() ) |
|
295 |
{ |
|
296 |
attributeName = aliasIt.value(); |
|
297 |
} |
|
298 | ||
299 |
//xsd:element |
|
300 |
QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ ); |
|
301 |
geomElem.setAttribute( "name", attributeName ); |
|
302 |
if ( it.value().type() == 2 ) |
|
303 |
geomElem.setAttribute( "type", "integer" ); |
|
304 |
else if ( it.value().type() == 6 ) |
|
305 |
geomElem.setAttribute( "type", "double" ); |
|
306 |
else |
|
307 |
geomElem.setAttribute( "type", "string" ); |
|
308 | ||
309 |
sequenceElem.appendChild( geomElem ); |
|
310 | ||
311 |
} |
|
312 |
} |
|
313 | ||
314 |
return doc; |
|
315 |
} |
|
316 | ||
317 |
int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format ) |
|
318 |
{ |
|
319 |
QByteArray result; |
|
320 |
QgsMSDebugMsg( "Info format is:" + infoFormat ); |
|
321 | ||
322 |
//read TYPENAME |
|
323 |
QString typeName; |
|
324 |
std::map<QString, QString>::const_iterator type_name_it = mParameterMap.find( "TYPENAME" ); |
|
325 |
if ( type_name_it != mParameterMap.end() ) |
|
326 |
{ |
|
327 |
typeName = type_name_it->second; |
|
328 |
} |
|
329 |
else |
|
330 |
{ |
|
331 |
return 1; |
|
332 |
} |
|
333 | ||
334 |
QStringList nonIdentifiableLayers = mConfigParser->identifyDisabledLayers(); |
|
335 |
QMap< QString, QMap< int, QString > > aliasInfo = mConfigParser->layerAliasInfo(); |
|
336 |
QMap< QString, QSet<QString> > hiddenAttributes = mConfigParser->hiddenAttributes(); |
|
337 |
|
|
338 |
QList<QgsMapLayer*> layerList; |
|
339 |
QgsMapLayer* currentLayer = 0; |
|
340 | ||
341 |
layerList = mConfigParser->mapLayerFromStyle( typeName, "" ); |
|
342 |
currentLayer = layerList.at( 0 ); |
|
343 |
|
|
344 |
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer ); |
|
345 |
if ( layer ) |
|
346 |
{ |
|
347 |
//is there alias info for this vector layer? |
|
348 |
QMap< int, QString > layerAliasInfo; |
|
349 |
QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() ); |
|
350 |
if ( aliasIt != aliasInfo.constEnd() ) |
|
351 |
{ |
|
352 |
layerAliasInfo = aliasIt.value(); |
|
353 |
} |
|
354 | ||
355 |
//hidden attributes for this layer |
|
356 |
QSet<QString> layerHiddenAttributes; |
|
357 |
QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() ); |
|
358 |
if ( hiddenIt != hiddenAttributes.constEnd() ) |
|
359 |
{ |
|
360 |
layerHiddenAttributes = hiddenIt.value(); |
|
361 |
} |
|
362 |
|
|
363 |
//do a select with searchRect and go through all the features |
|
364 |
QgsVectorDataProvider* provider = layer->dataProvider(); |
|
365 |
if ( !provider ) |
|
366 |
{ |
|
367 |
return 2; |
|
368 |
} |
|
369 | ||
370 |
QgsFeature feature; |
|
371 |
QgsAttributeMap featureAttributes; |
|
372 |
const QgsFieldMap& fields = provider->fields(); |
|
373 | ||
374 |
//map extent |
|
375 |
QgsRectangle searchRect = layer->extent(); |
|
376 | ||
377 |
//read FEATUREDID |
|
378 |
bool fidOk = false; |
|
379 |
QString fid; |
|
380 |
std::map<QString, QString>::const_iterator fidIt = mParameterMap.find( "FEATUREID" ); |
|
381 |
if ( fidIt != mParameterMap.end() ) { |
|
382 |
fidOk = true; |
|
383 |
fid = fidIt->second; |
|
384 |
} |
|
385 | ||
386 |
//read FILTER |
|
387 |
bool filterOk = false; |
|
388 |
QDomDocument filter; |
|
389 |
std::map<QString, QString>::const_iterator filterIt = mParameterMap.find( "FILTER" ); |
|
390 |
if ( filterIt != mParameterMap.end() ) { |
|
391 |
try { |
|
392 |
QString errorMsg; |
|
393 |
if ( !filter.setContent( filterIt->second, true, &errorMsg ) ) |
|
394 |
{ |
|
395 |
QgsMSDebugMsg( "soap request parse error" ); |
|
396 |
QgsMSDebugMsg( "error message: " + errorMsg ); |
|
397 |
QgsMSDebugMsg( "the xml string was:" ); |
|
398 |
QgsMSDebugMsg( filterIt->second ); |
|
399 |
} |
|
400 |
else |
|
401 |
{ |
|
402 |
filterOk = true; |
|
403 |
} |
|
404 |
} catch(QgsMapServiceException& e ) { |
|
405 |
filterOk = false; |
|
406 |
} |
|
407 |
} |
|
408 | ||
409 |
//read BBOX |
|
410 |
bool conversionSuccess; |
|
411 |
double minx, miny, maxx, maxy; |
|
412 |
bool bboxOk = false; |
|
413 |
std::map<QString, QString>::const_iterator bbIt = mParameterMap.find( "BBOX" ); |
|
414 |
if ( bbIt == mParameterMap.end() ) |
|
415 |
{ |
|
416 |
minx = 0; miny = 0; maxx = 0; maxy = 0; |
|
417 |
} |
|
418 |
else |
|
419 |
{ |
|
420 |
bboxOk = true; |
|
421 |
QString bbString = bbIt->second; |
|
422 |
minx = bbString.section( ",", 0, 0 ).toDouble( &conversionSuccess ); |
|
423 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
424 |
miny = bbString.section( ",", 1, 1 ).toDouble( &conversionSuccess ); |
|
425 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
426 |
maxx = bbString.section( ",", 2, 2 ).toDouble( &conversionSuccess ); |
|
427 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
428 |
maxy = bbString.section( ",", 3, 3 ).toDouble( &conversionSuccess ); |
|
429 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
430 |
} |
|
431 | ||
432 |
//read MAXFEATURES |
|
433 |
long maxFeat = layer->featureCount(); |
|
434 |
long featureCounter = 0; |
|
435 |
std::map<QString, QString>::const_iterator mfIt = mParameterMap.find( "MAXFEATURES" ); |
|
436 |
if ( mfIt != mParameterMap.end() ) |
|
437 |
{ |
|
438 |
QString mfString = mfIt->second; |
|
439 |
bool mfOk; |
|
440 |
maxFeat = mfString.toLong(&mfOk, 10); |
|
441 |
if ( !mfOk ) { maxFeat = layer->featureCount(); } |
|
442 |
} |
|
443 | ||
444 |
//read PROPERTYNAME |
|
445 |
bool withGeom = true; |
|
446 |
QgsAttributeList attrIndexes = provider->attributeIndexes(); |
|
447 |
std::map<QString, QString>::const_iterator pnIt = mParameterMap.find( "PROPERTYNAME" ); |
|
448 |
if ( pnIt != mParameterMap.end() ) |
|
449 |
{ |
|
450 |
QStringList attrList = pnIt->second.split( "," ); |
|
451 |
if ( attrList.size() > 0 ) |
|
452 |
{ |
|
453 |
withGeom = false; |
|
454 |
QStringList::const_iterator alstIt; |
|
455 |
QList<int> idxList; |
|
456 |
QMap<QString, int> fieldMap = provider->fieldNameMap(); |
|
457 |
QMap<QString, int>::const_iterator fieldIt; |
|
458 |
QString fieldName; |
|
459 |
for ( alstIt = attrList.begin(); alstIt != attrList.end(); ++alstIt ) |
|
460 |
{ |
|
461 |
fieldName = *alstIt; |
|
462 |
fieldIt = fieldMap.find( fieldName ); |
|
463 |
if ( fieldIt != fieldMap.end() ) |
|
464 |
{ |
|
465 |
idxList.append( fieldIt.value() ); |
|
466 |
} |
|
467 |
else if ( fieldName == "geometry" ) |
|
468 |
{ |
|
469 |
withGeom = true; |
|
470 |
} |
|
471 |
} |
|
472 |
if ( idxList.size() > 0 || withGeom) |
|
473 |
{ |
|
474 |
attrIndexes = idxList; |
|
475 |
} |
|
476 |
else |
|
477 |
{ |
|
478 |
withGeom = true; |
|
479 |
} |
|
480 |
} |
|
481 |
} |
|
482 | ||
483 |
QList<QgsFeature> featureList; |
|
484 |
if ( fidOk ) |
|
485 |
{ |
|
486 |
provider->featureAtId( fid.toInt(), feature, withGeom, attrIndexes ); |
|
487 |
featureList.append(feature); |
|
488 |
} |
|
489 |
else if ( filterOk ) |
|
490 |
{ |
|
491 |
provider->select( attrIndexes, searchRect, withGeom, true ); |
|
492 |
try { |
|
493 |
QgsFilter* mFilter = QgsFilter::createFilterFromXml( filter.firstChild().toElement().firstChild().toElement(), layer ); |
|
494 |
while ( provider->nextFeature( feature ) && featureCounter < maxFeat) |
|
495 |
{ |
|
496 |
if ( mFilter ) |
|
497 |
{ |
|
498 |
if ( mFilter->evaluate( feature ) ) |
|
499 |
{ |
|
500 |
featureList.append(feature); |
|
501 |
++featureCounter; |
|
502 |
} |
|
503 |
} |
|
504 |
else |
|
505 |
{ |
|
506 |
featureList.append(feature); |
|
507 |
++featureCounter; |
|
508 |
} |
|
509 |
} |
|
510 |
delete mFilter; |
|
511 |
} catch(QgsMapServiceException& e ) { |
|
512 |
while ( provider->nextFeature( feature ) && featureCounter < maxFeat) |
|
513 |
{ |
|
514 |
featureList.append(feature); |
|
515 |
++featureCounter; |
|
516 |
} |
|
517 |
} |
|
518 |
} |
|
519 |
else |
|
520 |
{ |
|
521 |
if ( bboxOk ) |
|
522 |
searchRect.set( minx, miny, maxx, maxy ); |
|
523 |
provider->select( attrIndexes, searchRect, withGeom, true ); |
|
524 |
while ( provider->nextFeature( feature ) && featureCounter < maxFeat ) |
|
525 |
{ |
|
526 |
featureList.append(feature); |
|
527 |
++featureCounter; |
|
528 |
} |
|
529 |
} |
|
530 |
QList<QgsFeature>::const_iterator featureIt = featureList.constBegin(); |
|
531 | ||
532 |
QString fcString; |
|
533 |
if ( format == "GeoJSON" ) |
|
534 |
{ |
|
535 |
featureCounter = 0; |
|
536 | ||
537 |
fcString = "{\"type\": \"FeatureCollection\",\n"; |
|
538 |
fcString += " \"features\": [\n"; |
|
539 |
result = fcString.toUtf8(); |
|
540 |
request.startGetFeatureResponse(&result, format); |
|
541 |
fcString = ""; |
|
542 | ||
543 |
for ( ; featureIt != featureList.constEnd(); ++featureIt ) |
|
544 |
{ |
|
545 |
feature = *featureIt; |
|
546 |
if (featureCounter == 0) |
|
547 |
fcString += " {\"type\": \"Feature\",\n"; |
|
548 |
else |
|
549 |
fcString += " ,{\"type\": \"Feature\",\n"; |
|
550 | ||
551 |
fcString += " \"id\": "; |
|
552 |
fcString += QString::number( feature.id() ); |
|
553 |
fcString += ",\n"; |
|
554 | ||
555 |
QgsGeometry* geom = feature.geometry(); |
|
556 |
if ( geom && withGeom ) |
|
557 |
{ |
|
558 |
fcString += " \"geometry\": "; |
|
559 |
fcString += geom->exportToGeoJSON(); |
|
560 |
fcString += ",\n"; |
|
561 |
} |
|
562 | ||
563 |
fcString += " \"properties\": {\n"; |
|
564 | ||
565 |
//read all attribute values from the feature |
|
566 |
featureAttributes = feature.attributeMap(); |
|
567 |
int attributeCounter = 0; |
|
568 |
for ( QgsAttributeMap::const_iterator it = featureAttributes.begin(); it != featureAttributes.end(); ++it ) |
|
569 |
{ |
|
570 | ||
571 |
QString attributeName = fields[it.key()].name(); |
|
572 |
//skip attribute if it has edit type 'hidden' |
|
573 |
if ( layerHiddenAttributes.contains( attributeName ) ) |
|
574 |
{ |
|
575 |
continue; |
|
576 |
} |
|
577 | ||
578 |
//check if the attribute name should be replaced with an alias |
|
579 |
QMap<int, QString>::const_iterator aliasIt = layerAliasInfo.find( it.key() ); |
|
580 |
if ( aliasIt != layerAliasInfo.constEnd() ) |
|
581 |
{ |
|
582 |
attributeName = aliasIt.value(); |
|
583 |
} |
|
584 | ||
585 |
if (attributeCounter == 0) |
|
586 |
fcString += " \""; |
|
587 |
else |
|
588 |
fcString += " ,\""; |
|
589 |
fcString += attributeName; |
|
590 |
fcString += "\": "; |
|
591 |
if (it->type() == 6 || it->type() == 2) |
|
592 |
{ |
|
593 |
fcString += it->toString(); |
|
594 |
} |
|
595 |
else |
|
596 |
{ |
|
597 |
fcString += "\""; |
|
598 |
fcString += it->toString().replace( QString( "\"" ), QString( "\\\"" ) ); |
|
599 |
fcString += "\""; |
|
600 |
} |
|
601 |
fcString += "\n"; |
|
602 |
++attributeCounter; |
|
603 |
} |
|
604 | ||
605 |
fcString += " }\n"; |
|
606 | ||
607 |
fcString += " }"; |
|
608 |
fcString += "\n"; |
|
609 | ||
610 |
result = fcString.toUtf8(); |
|
611 |
request.sendGetFeatureResponse( &result ); |
|
612 |
fcString = ""; |
|
613 | ||
614 |
++featureCounter; |
|
615 |
} |
|
616 |
fcString = ""; |
|
617 |
fcString += " ]\n"; |
|
618 |
fcString += "}"; |
|
619 | ||
620 |
result = fcString.toUtf8(); |
|
621 |
request.endGetFeatureResponse( &result ); |
|
622 |
fcString = ""; |
|
623 |
} |
|
624 |
else |
|
625 |
{ |
|
626 |
QDomDocument gmlDoc; |
|
627 |
//wfs:FeatureCollection |
|
628 |
fcString = "<wfs:FeatureCollection"; |
|
629 |
fcString += " xmlns=\"http://www.opengis.net/wfs\""; |
|
630 |
fcString += " xmlns:wfs=\"http://www.opengis.net/wfs\""; |
|
631 |
fcString += " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""; |
|
632 |
fcString += " xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\""; |
|
633 |
fcString += " xmlns:ogc=\"http://www.opengis.net/ogc\""; |
|
634 |
fcString += " xmlns:gml=\"http://www.opengis.net/gml\""; |
|
635 |
fcString += " xmlns:ows=\"http://www.opengis.net/ows\""; |
|
636 |
fcString += " xmlns:xlink=\"http://www.w3.org/1999/xlink\""; |
|
637 |
fcString += " xmlns:qgs=\"http://www.qgis.org/gml\""; |
|
638 |
fcString += ">"; |
|
639 |
result = fcString.toUtf8(); |
|
640 |
request.startGetFeatureResponse(&result, format); |
|
641 |
fcString = ""; |
|
642 | ||
643 |
for ( ; featureIt != featureList.constEnd(); ++featureIt ) |
|
644 |
{ |
|
645 |
feature = *featureIt; |
|
646 |
//gml:FeatureMember |
|
647 |
QDomElement featureElement = gmlDoc.createElement( "gml:featureMember"/*wfs:FeatureMember*/ ); |
|
648 |
gmlDoc.appendChild(featureElement); |
|
649 | ||
650 |
//qgs:%TYPENAME% |
|
651 |
QDomElement typeNameElement = gmlDoc.createElement( "qgs:"+typeName.replace( QString(" "), QString("_") )/*qgs:%TYPENAME%*/ ); |
|
652 |
typeNameElement.setAttribute( "fid", QString::number( feature.id() ) ); |
|
653 |
featureElement.appendChild(typeNameElement); |
|
654 | ||
655 |
if ( withGeom ) |
|
656 |
{ |
|
657 |
//add geometry column (as gml) |
|
658 |
QDomElement geomElem = gmlDoc.createElement( "qgs:geometry" ); |
|
659 |
QDomElement gmlElem = createGeometryElem( feature.geometry(), gmlDoc ); |
|
660 |
if ( !gmlElem.isNull() ) |
|
661 |
{ |
|
662 |
QgsCoordinateReferenceSystem layerCrs = layer->crs(); |
|
663 |
if ( layerCrs.isValid() ) |
|
664 |
{ |
|
665 |
gmlElem.setAttribute( "srsName", layerCrs.authid() ); |
|
666 |
} |
|
667 |
geomElem.appendChild( gmlElem ); |
|
668 |
typeNameElement.appendChild( geomElem ); |
|
669 |
} |
|
670 |
} |
|
671 | ||
672 |
//read all attribute values from the feature |
|
673 |
featureAttributes = feature.attributeMap(); |
|
674 |
for ( QgsAttributeMap::const_iterator it = featureAttributes.begin(); it != featureAttributes.end(); ++it ) |
|
675 |
{ |
|
676 | ||
677 |
QString attributeName = fields[it.key()].name(); |
|
678 |
//skip attribute if it has edit type 'hidden' |
|
679 |
if ( layerHiddenAttributes.contains( attributeName ) ) |
|
680 |
{ |
|
681 |
continue; |
|
682 |
} |
|
683 | ||
684 |
//check if the attribute name should be replaced with an alias |
|
685 |
QMap<int, QString>::const_iterator aliasIt = layerAliasInfo.find( it.key() ); |
|
686 |
if ( aliasIt != layerAliasInfo.constEnd() ) |
|
687 |
{ |
|
688 |
attributeName = aliasIt.value(); |
|
689 |
} |
|
690 |
|
|
691 |
QDomElement fieldElem = gmlDoc.createElement( "qgs:"+attributeName ); |
|
692 |
QDomText fieldText = gmlDoc.createTextNode( it->toString() ); |
|
693 |
fieldElem.appendChild( fieldText ); |
|
694 |
typeNameElement.appendChild( fieldElem ); |
|
695 |
} |
|
696 |
result = gmlDoc.toByteArray(); |
|
697 |
request.sendGetFeatureResponse( &result ); |
|
698 |
gmlDoc.removeChild(featureElement); |
|
699 |
} |
|
700 | ||
701 |
fcString = "</wfs:FeatureCollection>"; |
|
702 |
result = fcString.toUtf8(); |
|
703 |
request.endGetFeatureResponse( &result ); |
|
704 |
fcString = ""; |
|
705 |
} |
|
706 | ||
707 |
} |
|
708 |
else |
|
709 |
{ |
|
710 |
return 2; |
|
711 |
} |
|
712 |
return 0; |
|
713 |
} |
|
714 | ||
715 |
QDomElement QgsWFSServer::createGeometryElem( QgsGeometry* geom, QDomDocument& doc ) /*const*/ |
|
716 |
{ |
|
717 |
if ( !geom ) |
|
718 |
{ |
|
719 |
return QDomElement(); |
|
720 |
} |
|
721 | ||
722 | ||
723 |
QDomElement geomElement; |
|
724 |
QString geomTypeName; |
|
725 |
QGis::WkbType wkbType = geom->wkbType(); |
|
726 |
switch ( wkbType ) |
|
727 |
{ |
|
728 |
case QGis::WKBPoint: |
|
729 |
case QGis::WKBPoint25D: |
|
730 |
geomElement = createPointElem( geom, doc ); |
|
731 |
break; |
|
732 |
case QGis::WKBMultiPoint: |
|
733 |
case QGis::WKBMultiPoint25D: |
|
734 |
geomElement = createMultiPointElem( geom, doc ); |
|
735 |
break; |
|
736 |
case QGis::WKBLineString: |
|
737 |
case QGis::WKBLineString25D: |
|
738 |
geomElement = createLineStringElem( geom, doc ); |
|
739 |
break; |
|
740 |
case QGis::WKBMultiLineString: |
|
741 |
case QGis::WKBMultiLineString25D: |
|
742 |
geomElement = createMultiLineStringElem( geom, doc ); |
|
743 |
break; |
|
744 |
case QGis::WKBPolygon: |
|
745 |
case QGis::WKBPolygon25D: |
|
746 |
geomElement = createPolygonElem( geom, doc ); |
|
747 |
break; |
|
748 |
case QGis::WKBMultiPolygon: |
|
749 |
case QGis::WKBMultiPolygon25D: |
|
750 |
geomElement = createMultiPolygonElem( geom, doc ); |
|
751 |
break; |
|
752 |
default: |
|
753 |
return QDomElement(); |
|
754 |
} |
|
755 |
return geomElement; |
|
756 |
} |
|
757 | ||
758 |
QDomElement QgsWFSServer::createLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const |
|
759 |
{ |
|
760 |
if ( !geom ) |
|
761 |
{ |
|
762 |
return QDomElement(); |
|
763 |
} |
|
764 | ||
765 |
QDomElement lineStringElem = doc.createElement( "gml:LineString" ); |
|
766 |
QDomElement coordElem = createCoordinateElem( geom->asPolyline(), doc ); |
|
767 |
lineStringElem.appendChild( coordElem ); |
|
768 |
return lineStringElem; |
|
769 |
} |
|
770 | ||
771 |
QDomElement QgsWFSServer::createMultiLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const |
|
772 |
{ |
|
773 |
if ( !geom ) |
|
774 |
{ |
|
775 |
return QDomElement(); |
|
776 |
} |
|
777 | ||
778 |
QDomElement multiLineStringElem = doc.createElement( "gml:MultiLineString" ); |
|
779 |
QgsMultiPolyline multiline = geom->asMultiPolyline(); |
|
780 | ||
781 |
QgsMultiPolyline::const_iterator multiLineIt = multiline.constBegin(); |
|
782 |
for ( ; multiLineIt != multiline.constEnd(); ++multiLineIt ) |
|
783 |
{ |
|
784 |
QgsGeometry* lineGeom = QgsGeometry::fromPolyline( *multiLineIt ); |
|
785 |
if ( lineGeom ) |
|
786 |
{ |