diff --git a/web/client/utils/FilterUtils.jsx b/web/client/utils/FilterUtils.jsx index 54d0c05b13..88a33c30a2 100644 --- a/web/client/utils/FilterUtils.jsx +++ b/web/client/utils/FilterUtils.jsx @@ -49,7 +49,7 @@ const FilterUtils = { "ogc": {startTag: "", endTag: ""}, "fes": {startTag: "", endTag: ""} }, - toOGCFilter: function(ftName, json, version, sortOptions = null, hits = false, format = null) { + toOGCFilter: function(ftName, json, version, sortOptions = null, hits = false, format = null, propertyNames = null) { try { this.objFilter = (json instanceof Object) ? json : JSON.parse(json); } catch(e) { @@ -87,6 +87,14 @@ const FilterUtils = { spatialFilter = this.processOGCSpatialFilter(versionOGC); filters.push(spatialFilter); } + if (this.objFilter.crossLayerFilter) { + let crossLayerFilter = this.objFilter.crossLayerFilter; + if (Array.isArray()) { + crossLayerFilter.forEach( f => filters.push(this.processOGCCrossLayerFilter(f))); + } else { + filters.push(this.processOGCCrossLayerFilter(crossLayerFilter)); + } + } let filter = "<" + this.nsplaceholder + ":Filter>"; @@ -104,7 +112,12 @@ const FilterUtils = { ogcFilter += ''; ogcFilter += filter; - + if (propertyNames) { + ogcFilter += propertyNames.map( name => ( + this.propertyTagReference[this.nsplaceholder].startTag + + name + + this.propertyTagReference[this.nsplaceholder].endTag )).join(""); + } if (sortOptions && sortOptions.sortBy && sortOptions.sortOrder) { ogcFilter += "<" + this.nsplaceholder + ":SortBy>" + @@ -475,6 +488,54 @@ const FilterUtils = { ogc += this.ogcSpatialOperator[this.objFilter.spatialField.operation].endTag; return ogc; }, + /** + * processOGCCrossLayerFilter(object) + * object should be in this form : + * { + * operation: "FILTER_OPERATION_TO_DO_WITH_GEOMETRY", + * attribute: "GEOMETRY_NAME_OF_THE_FEATURE_TYPE_TO_FILTER", + * collectGeometries: {queryCollection: { + * typeName: "TYPE_NAME_TO_QUERY", + * geometryName: "GEOMETRY_NAME_OF_THE_FEATURE_TYPE_TO_QUERY", + * cqlFilter: "CQL_FITER_TO_APPLY_TO_THE_FEATURE_TYPE" + * } + * }} + * Example: if I want to filter the featureType "roads", with the geometryName = "roads_geom" + * that intersect the polygons from the featureType "regions, with geometryName "regions_geom" + * where the attribute "area" of the region is >= 10 You will have the following + * { + * operation: "INTERSECTS" + * attribute: "roads_geom", + * collectGeometries: {queryCollection: { + * typeName: "regions", + * geometryName: "regions_geom", + * cqlFilter: "area > 10" + * }} + * } + */ + processOGCCrossLayerFilter: function(crossLayerFilter) { + let ogc = this.ogcSpatialOperator[crossLayerFilter.operation].startTag; + ogc += + this.propertyTagReference[this.nsplaceholder].startTag + + crossLayerFilter.attribute + + this.propertyTagReference[this.nsplaceholder].endTag; + // only collectGeometries is supported now + if (crossLayerFilter.collectGeometries) { + ogc += `` + + `` + + `${crossLayerFilter.collectGeometries.queryCollection.typeName}` + + `${crossLayerFilter.collectGeometries.queryCollection.geometryName}` + + `${crossLayerFilter.collectGeometries.queryCollection.cqlFilter}` + + `` + + ``; + } + if (crossLayerFilter.operation === "DWITHIN") { + ogc += '<' + this.nsplaceholder + ':Distance units="m">' + (crossLayerFilter.distance || 0) + ''; + } + + ogc += this.ogcSpatialOperator[crossLayerFilter.operation].endTag; + return ogc; + }, getGmlPointElement: function(coordinates, srsName, version) { let gmlPoint = ' { let filter = FilterUtils.toCQLFilter(filterObj); expect(filter).toEqual(expected); }); + it('Check CrossLayerFilter segment generation', () => { + let crossLayerFilterObj = { + operation: "INTERSECTS", + attribute: "roads_geom", + collectGeometries: {queryCollection: { + typeName: "regions", + geometryName: "regions_geom", + cqlFilter: "area > 10" + }} + }; + let expected = "" + + 'roads_geom' + + '' + + '' + + 'regions' + + 'regions_geom' + + 'area > 10' + + '' + + ""; + + // this is a workarround for this issue : https://github.com/geosolutions-it/MapStore2/issues/1263 + // please remove when fixed + FilterUtils.nsplaceholder = "ogc"; + FilterUtils.setOperatorsPlaceholders("{namespace}", "ogc"); + + let filter = FilterUtils.processOGCCrossLayerFilter(crossLayerFilterObj); + expect(filter).toEqual(expected); + }); });