Skip to content

Commit

Permalink
Merge pull request #14 from mborne/issue_11
Browse files Browse the repository at this point in the history
defaultGeomFieldName - ajout d'une option sur le client
  • Loading branch information
vinsag committed Apr 8, 2021
2 parents 9a8c5a6 + 131bc98 commit b3ec1d0
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 75 deletions.
22 changes: 15 additions & 7 deletions src/Client.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const httpClient = require('./internal/httpClient');

var getTypeNamesFromCapabilities = require('./internal/getTypeNamesFromCapabilities');
var clq_filter = require('./internal/cql_filter')
var buildCqlFilter = require('./internal/buildCqlFilter')

/**
* @classdesc
Expand All @@ -14,6 +14,8 @@ var Client = function (options) {
this.url = options.url || 'https://wxs.ign.fr/{apiKey}/geoportail/wfs';
this.apiKey = options.apiKey || null;
this.headers = options.headers || {};
/* allows to use WFS with different naming convention */
this.defaultGeomFieldName = options.defaultGeomFieldName || 'the_geom';
};

/**
Expand All @@ -39,7 +41,7 @@ Client.prototype.getDefaultParams = function () {
* @private
* @returns {Object}
*/
Client.prototype.getDefaultHeaders = function(){
Client.prototype.getDefaultHeaders = function () {
return this.headers;
}

Expand Down Expand Up @@ -67,8 +69,14 @@ Client.prototype.getTypeNames = function () {

/**
* Get features for a given type
*
* @param {string} typeName - name of type
* @param {Object} params - define cumulative filters (bbox, geom) and to manage the pagination
* @param {object} params - define cumulative filters (bbox, geom) and to manage the pagination
* @param {number} [params._start=0] index of the first result (STARTINDEX on the WFS)
* @param {number} [params._limit] maximum number of result (COUNT on the WFS)
* @param {object} [params.geom] search geometry intersecting the resulting features.
* @param {object} [params.bbox] search bbox intersecting the resulting features.
*
* @return {Promise}
*/
Client.prototype.getFeatures = function (typeName, params) {
Expand All @@ -78,10 +86,10 @@ Client.prototype.getFeatures = function (typeName, params) {
headers['Accept'] = 'application/json';

/*
* GetFeature params
* GetFeature params
*/
var queryParams = this.getDefaultParams();
queryParams['request'] = 'GetFeature';
queryParams['request'] = 'GetFeature';
queryParams['typename'] = typeName;
queryParams['outputFormat'] = 'application/json';
queryParams['srsName'] = 'CRS:84';
Expand All @@ -91,11 +99,11 @@ Client.prototype.getFeatures = function (typeName, params) {
if (typeof params._start !== 'undefined') {
queryParams['startIndex'] = params._start;
}

/*
* bbox and attribute filter as POST parameter
*/
var cql_filter = clq_filter(params);
var cql_filter = buildCqlFilter(params,this.defaultGeomFieldName);
var body = (cql_filter !== null) ? 'cql_filter=' + encodeURI(cql_filter) : '';
return httpClient.post(this.getUrl(), body, {
params: queryParams,
Expand Down
78 changes: 78 additions & 0 deletions src/internal/buildCqlFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

var WKT = require('terraformer-wkt-parser');
var flip = require('@turf/flip');

/*
* WARNING: Despite the use of WGS84, you need to do a flip on the coordinates
*/

/**
* Convert a bbox on array with 4 values (split string if required)
*
* @param {string|number[]} bbox
* @returns {number[]}
*/
function parseBoundingBox(bbox) {
if (typeof bbox !== 'string') {
return bbox;
}
return bbox.replace(/'/g, '').split(',');
}

/**
* Convert a bbox in cql_filter fragment.
*
* @param {string|number[]} bbox input bbox (CRS:84)
* @param {string} geomFieldName name of the geometry (ex : the_geom)
* @returns {string}
*/
function bboxToFilter(bbox, geomFieldName) {
bbox = parseBoundingBox(bbox);
var xmin = bbox[1];
var ymin = bbox[0];
var xmax = bbox[3];
var ymax = bbox[2];
return 'BBOX(' + geomFieldName + ',' + xmin + ',' + ymin + ',' + xmax + ',' + ymax + ')';
}

/**
* Build cql_filter parameter for GeoServer according to user params.
*
* @param {object} params
* @param {object} [params.geom] search geometry intersecting the resulting features.
* @param {object} [params.bbox] search bbox intersecting the resulting features.
* @param {string} [geomFieldName="the_geom"] name of the geometry column
* @returns {string}
*/
function buildCqlFilter(params, geomFieldName) {
geomFieldName = geomFieldName || 'the_geom';

var parts = [];
for (var name in params) {
// ignore _limit, _start, etc.
if (name.charAt(0) === '_') {
continue;
}

if (name == 'bbox') {
parts.push(bboxToFilter(params['bbox'], geomFieldName));
} else if (name == 'geom') {
var geom = params[name];
if (typeof geom !== 'object') {
geom = JSON.parse(geom);
}
var wkt = WKT.convert(flip(geom));
parts.push('INTERSECTS(' + geomFieldName + ',' + wkt + ')');
} else {
parts.push(name + '=\'' + params[name] + '\'');
}
}
if (parts.length === 0) {
return null;
}
return parts.join(' and ');
};


module.exports = buildCqlFilter;

56 changes: 0 additions & 56 deletions src/internal/cql_filter.js

This file was deleted.

32 changes: 32 additions & 0 deletions test/Client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const expect = require('chai').expect;

const Client = require('../src/Client');



describe('test Client', function () {

it('should replace apiKey in the generated URL', function () {
let client = new Client({
apiKey: 'my-api-key'
});
expect(client.getUrl()).to.equal('https://wxs.ign.fr/my-api-key/geoportail/wfs');
});

it('should use "the_geom" as default value for defaultGeomFieldName', function () {
let client = new Client({
apiKey: 'my-api-key'
});
expect(client.defaultGeomFieldName).to.equal('the_geom');
});

it('should use support user value for defaultGeomFieldName', function () {
let client = new Client({
apiKey: 'my-api-key',
defaultGeomFieldName: 'geom'
});
expect(client.defaultGeomFieldName).to.equal('geom');
});

});

56 changes: 44 additions & 12 deletions test/internal/cql_filter.js → test/internal/buildCqlFilter.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,62 @@
const expect = require('chai').expect;

const cql_filter = require('../../src/internal/cql_filter');
const buildCqlFilter = require('../../src/internal/buildCqlFilter');

describe('testcql_filter', function () {
describe('test buildCqlFilter', function () {

it('should return null for null filter', function () {
var input = null;
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.be.null;
});

it('should return null for empty filter', function () {
var input = {};
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.be.null;
});

it('should ignore _start', function () {
var input = {
_start: 10
};
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.be.null;
});

it('should ignore _limit', function () {
var input = {
_limit: 10
};
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.be.null;
});

it('should encode "bbox" string to filter with coordinate swapping', function () {
var input = {
'bbox': '0,1,2,3'
};
var expected = "BBOX(the_geom,1,0,3,2)";
var result = buildCqlFilter(input);
expect(result).to.equals(expected);
});

it('should encode bbox to filter with coordinate swapping', function () {
it('should encode "bbox" array to filter with coordinate swapping', function () {
var input = {
'bbox': [0, 1, 2, 3]
};
var expected = "BBOX(the_geom,1,0,3,2)";
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.equals(expected);
});

/* _geomFieldName support */
it('should encode "bbox" array to filter with coordinate swapping using geomFieldName', function () {
var input = {
'bbox': [0, 1, 2, 3]
};
var expected = "BBOX(geom,1,0,3,2)";
var result = buildCqlFilter(input,'geom');
expect(result).to.equals(expected);
});

Expand All @@ -50,7 +68,7 @@ describe('testcql_filter', function () {
}
};
var expected = "INTERSECTS(the_geom,POINT (4 3))";
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.equals(expected);
});

Expand All @@ -62,18 +80,32 @@ describe('testcql_filter', function () {
})
};
var expected = "INTERSECTS(the_geom,POINT (4 3))";
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.equals(expected);
});


it('should encode "geom" (GeoJSON) as "intersects" with coordinate swapping using geomFieldName', function () {
var input = {
'geom': {
'type': 'Point',
'coordinates': [3.0, 4.0]
}
};
var expected = "INTERSECTS(geom,POINT (4 3))";
var result = buildCqlFilter(input,'geom');
expect(result).to.equals(expected);
});


/* standard attributes */

it('should encode attribute filters with quotes', function () {
var input = {
'code_dept': 12
};
var expected = "code_dept='12'";
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.equals(expected);
});

Expand All @@ -84,7 +116,7 @@ describe('testcql_filter', function () {
'code_dept': '12'
};
var expected = "BBOX(the_geom,1,0,3,2) and code_dept='12'";
var result = cql_filter(input);
var result = buildCqlFilter(input);
expect(result).to.equals(expected);
});

Expand Down

0 comments on commit b3ec1d0

Please sign in to comment.