Permalink
Browse files

WFS: make WFS 2.0 GetFeature on multiple layers compliant with 11.3.3…

….5 (one FeatureCollection for each layer as a wfs:member of the main FeatureCollection)
  • Loading branch information...
rouault committed Nov 20, 2013
1 parent a95dc04 commit 9edae04816a68303482d7a8f92a271f7aae7dc53
Showing with 134 additions and 38 deletions.
  1. +46 −30 mapgml.c
  2. +4 −0 mapows.h
  3. +83 −7 mapwfs.c
  4. +1 −1 msautotest
View
@@ -1407,43 +1407,21 @@ int msGMLWriteQuery(mapObj *map, char *filename, const char *namespaces)
#endif
}
/*
** msGMLWriteWFSQuery()
**
** Similar to msGMLWriteQuery() but tuned for use with WFS
*/
int msGMLWriteWFSQuery(mapObj *map, FILE *stream, const char *default_namespace_prefix,
OWSGMLVersion outputformat, int nWFSVersion, int bUseURN,
int bGetPropertyValueRequest)
{
#ifdef USE_WFS_SVR
int status;
int i,j,k;
layerObj *lp=NULL;
shapeObj shape;
void msGMLWriteWFSBounds(mapObj *map, FILE *stream, const char *tab,
OWSGMLVersion outputformat, int nWFSVersion, int bUseURN)
{
rectObj resultBounds = {-1.0,-1.0,-1.0,-1.0};
gmlGroupListObj *groupList=NULL;
gmlItemListObj *itemList=NULL;
gmlConstantListObj *constantList=NULL;
gmlGeometryListObj *geometryList=NULL;
gmlItemObj *item=NULL;
gmlConstantObj *constant=NULL;
const char *namespace_prefix=NULL;
int bSwapAxis = 0;
double tmp;
msInitShape(&shape);
/*add a check to see if the map projection is set to be north-east*/
bSwapAxis = msIsAxisInvertedProj(&(map->projection));
int bSwapAxis = msIsAxisInvertedProj(&(map->projection));
/* Need to start with BBOX of the whole resultset */
if (!bGetPropertyValueRequest &&
msGetQueryResultBounds(map, &resultBounds) > 0) {
if (msGetQueryResultBounds(map, &resultBounds) > 0) {
char* srs = NULL;
if (bSwapAxis) {
double tmp;
tmp = resultBounds.minx;
resultBounds.minx = resultBounds.miny;
resultBounds.miny = tmp;
@@ -1469,10 +1447,48 @@ int msGMLWriteWFSQuery(mapObj *map, FILE *stream, const char *default_namespace_
srs = msStrdup(constsrs);
}
gmlWriteBounds(stream, outputformat, &resultBounds, srs, " ",
gmlWriteBounds(stream, outputformat, &resultBounds, srs, tab,
(nWFSVersion == OWS_2_0_0) ? "wfs" : "gml");
msFree(srs);
}
}
#endif
/*
** msGMLWriteWFSQuery()
**
** Similar to msGMLWriteQuery() but tuned for use with WFS
*/
int msGMLWriteWFSQuery(mapObj *map, FILE *stream, const char *default_namespace_prefix,
OWSGMLVersion outputformat, int nWFSVersion, int bUseURN,
int bGetPropertyValueRequest)
{
#ifdef USE_WFS_SVR
int status;
int i,j,k;
layerObj *lp=NULL;
shapeObj shape;
gmlGroupListObj *groupList=NULL;
gmlItemListObj *itemList=NULL;
gmlConstantListObj *constantList=NULL;
gmlGeometryListObj *geometryList=NULL;
gmlItemObj *item=NULL;
gmlConstantObj *constant=NULL;
const char *namespace_prefix=NULL;
int bSwapAxis;
msInitShape(&shape);
/*add a check to see if the map projection is set to be north-east*/
bSwapAxis = msIsAxisInvertedProj(&(map->projection));
/* Need to start with BBOX of the whole resultset */
if (!bGetPropertyValueRequest) {
msGMLWriteWFSBounds(map, stream, " ", outputformat, nWFSVersion, bUseURN);
}
/* step through the layers looking for query results */
for(i=0; i<map->numlayers; i++) {
View
@@ -407,6 +407,10 @@ MS_DLL_EXPORT int msGMLWriteQuery(mapObj *map, char *filename, const char *names
#ifdef USE_WFS_SVR
void msGMLWriteWFSBounds(mapObj *map, FILE *stream, const char *tab,
OWSGMLVersion outputformat, int nWFSVersion, int bUseURN);
MS_DLL_EXPORT int msGMLWriteWFSQuery(mapObj *map, FILE *stream, const char *wfs_namespace,
OWSGMLVersion outputformat, int nWFSVersion, int bUseURN,
int bGetPropertyValueRequest);
View
@@ -3726,7 +3726,9 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req,
if( psFormat == NULL ) {
if(maxfeatures != 0 && iResultTypeHits == 0)
{
layerObj* lp;
int i;
int bWFS2MultipleFeatureCollection = MS_FALSE;
/* Would make sense for WFS 1.1.0 too ! See #3576 */
int bUseURN = (nWFSVersion == OWS_2_0_0);
@@ -3738,7 +3740,7 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req,
for(i=0;i<map->numlayers;i++)
{
layerObj* lp = GET_LAYER(map, i);
lp = GET_LAYER(map, i);
if( papszGMLGroups[i] )
msInsertHashTable(&(lp->metadata), "GML_GROUPS", papszGMLGroups[i]);
if( papszGMLIncludeItems[i] )
@@ -3747,12 +3749,86 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req,
msInsertHashTable(&(lp->metadata), "GML_GEOMETRIES", papszGMLGeometries[i]);
}
status = msGMLWriteWFSQuery(map, stdout,
gmlinfo.user_namespace_prefix,
outputformat,
nWFSVersion,
bUseURN,
MS_FALSE);
/* For WFS 2.0, when we request several types, we must present each type */
/* in its own FeatureCollection (§ 11.3.3.5 ) */
if( nWFSVersion >= OWS_2_0_0 && iResultTypeHits != 1 )
{
int nLayersWithFeatures = 0;
for(i=0; i<map->numlayers; i++) {
lp = GET_LAYER(map, i);
if(lp->resultcache && lp->resultcache->numresults > 0)
nLayersWithFeatures ++;
}
if( nLayersWithFeatures > 1 )
{
char timestring[100];
resultCacheObj** saveResultCache = (resultCacheObj** )
msSmallMalloc( map->numlayers * sizeof(resultCacheObj*));
int iLastNonEmptyLayer = -1;
msWFSGetFeature_GetTimeStamp(timestring, sizeof(timestring));
/* Emit global bounds */
msGMLWriteWFSBounds(map, stdout, " ", outputformat, nWFSVersion, bUseURN);
/* Save the result cache that contains the features that we want to */
/* emit in the response */
for(i=0; i<map->numlayers; i++) {
lp = GET_LAYER(map, i);
saveResultCache[i] = lp->resultcache;
if( lp->resultcache && lp->resultcache->numresults > 0) {
iLastNonEmptyLayer = i;
}
lp->resultcache = NULL;
}
/* Just dump one layer at a time */
for(i=0;i<map->numlayers;i++) {
lp = GET_LAYER(map, i);
lp->resultcache = saveResultCache[i];
if( lp->resultcache && lp->resultcache->numresults > 0) {
msIO_fprintf(stdout, " <wfs:member>\n");
msIO_fprintf(stdout, " <wfs:FeatureCollection timeStamp=\"%s\" numberMatched=\"", timestring);
if( i < iLastNonEmptyLayer || nMatchingFeatures >= 0 )
msIO_fprintf(stdout, "%d", lp->resultcache->numresults );
else
msIO_fprintf(stdout, "unknown" );
msIO_fprintf(stdout, "\" numberReturned=\"%d\">\n", lp->resultcache->numresults );
msGMLWriteWFSQuery(map, stdout,
gmlinfo.user_namespace_prefix,
outputformat,
nWFSVersion,
bUseURN,
MS_FALSE);
msIO_fprintf(stdout, " </wfs:FeatureCollection>\n");
msIO_fprintf(stdout, " </wfs:member>\n");
}
lp->resultcache = NULL;
}
/* Restore for later cleanup */
for(i=0; i<map->numlayers; i++) {
lp = GET_LAYER(map, i);
lp->resultcache = saveResultCache[i];
}
msFree(saveResultCache);
bWFS2MultipleFeatureCollection = MS_TRUE;
}
}
if( !bWFS2MultipleFeatureCollection )
{
msGMLWriteWFSQuery(map, stdout,
gmlinfo.user_namespace_prefix,
outputformat,
nWFSVersion,
bUseURN,
MS_FALSE);
}
status = MS_SUCCESS;
}
} else {
mapservObj *mapserv = msAllocMapServObj();
Submodule msautotest updated from 3207dc to f45268

0 comments on commit 9edae04

Please sign in to comment.