Skip to content

Commit

Permalink
Add search options from the catalog (#1104) (#1385)
Browse files Browse the repository at this point in the history
* Add search options from the catalog

When adding a WMS layer from the catalog, MapStore will try to get a describeLayer for it, to find out if the layer can be searched via WFS.
If possible, the search object is added to the layer.

 * DescribeLayers is implemented to avoid ogc-schemas lib (old functionality has been mantained for backward compatibility, as describeLayer with require-ensure pattern.
 * Add tests for the JavaScript WMS API.
  • Loading branch information
offtherailz authored Jan 16, 2017
1 parent 5f75fae commit 357e2e7
Show file tree
Hide file tree
Showing 13 changed files with 706 additions and 6 deletions.
28 changes: 26 additions & 2 deletions web/client/actions/__tests__/catalog-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
*/

const expect = require('expect');
const {getRecords, addLayerError, ADD_LAYER_ERROR} = require('../catalog');
const LayersUtils = require('../../utils/LayersUtils');
const {getRecords, addLayerError, addLayer, ADD_LAYER_ERROR} = require('../catalog');
const {CHANGE_LAYER_PROPERTIES, ADD_LAYER} = require('../layers');
describe('Test correctness of the catalog actions', () => {

it('getRecords ISO Metadata Profile', (done) => {
Expand Down Expand Up @@ -55,7 +57,29 @@ describe('Test correctness of the catalog actions', () => {
}
});
});

it('add layer and describe it', (done) => {
const verify = (action) => {
if (action.type === ADD_LAYER) {
expect(action.layer).toExist();
const layer = action.layer;
expect(layer.id).toExist();
expect(layer.id).toBe(LayersUtils.getLayerId(action.layer, []));
} else if (action.type === CHANGE_LAYER_PROPERTIES) {
expect(action.layer).toExist();
expect(action.newProperties).toExist();
expect(action.newProperties.search).toExist();
expect(action.newProperties.search.type ).toBe('wfs');
expect(action.newProperties.search.url).toBe("http://some.geoserver.org:80/geoserver/wfs?");
done();
}
};
const callback = addLayer({
url: 'base/web/client/test-resources/wms/DescribeLayers.xml',
type: 'wms',
name: 'workspace:vector_layer'
});
callback(verify, () => ({ layers: []}));
});
it('sets an error on addLayerError action', () => {
const action = addLayerError('myerror');

Expand Down
31 changes: 31 additions & 0 deletions web/client/actions/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ var API = {
wms: require('../api/WMS')
};

const {addLayer, changeLayerProperties} = require('./layers');

const LayersUtils = require('../utils/LayersUtils');
const {find} = require('lodash');

const RECORD_LIST_LOADED = 'RECORD_LIST_LOADED';
const RECORD_LIST_LOAD_ERROR = 'RECORD_LIST_LOAD_ERROR';
const CHANGE_CATALOG_FORMAT = 'CHANGE_CATALOG_FORMAT';
Expand Down Expand Up @@ -75,7 +80,32 @@ function textSearch(format, url, startPosition, maxRecords, text, options) {
});
};
}
function addLayerAndDescribe(layer) {
return (dispatch, getState) => {
const state = getState();
const layers = state && state.layers;
const id = LayersUtils.getLayerId(layer, layers || []);
dispatch(addLayer({...layer, id}));
if (layer.type === 'wms') {
// try to describe layer
return API.wms.describeLayers(layer.url, layer.name).then((results) => {
if (results) {
let description = find(results, (desc) => desc.name === layer.name );
if (description && description.owsType === 'WFS') {
dispatch(changeLayerProperties(id, {
search: {
url: description.owsURL,
type: 'wfs'
}
}));
}
}

});
}

};
}
function addLayerError(error) {
return {
type: ADD_LAYER_ERROR,
Expand All @@ -98,6 +128,7 @@ module.exports = {
getRecords,
textSearch,
changeCatalogFormat,
addLayer: addLayerAndDescribe,
addLayerError,
catalogReset
};
26 changes: 26 additions & 0 deletions web/client/api/WMS.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,32 @@ const Api = {
return searchAndPaginate(json, startPosition, maxRecords, text);
});
},
describeLayers: function(url, layers) {
const parsed = urlUtil.parse(url, true);
const describeLayerUrl = urlUtil.format(assign({}, parsed, {
query: assign({
service: "WMS",
version: "1.1.1",
layers: layers,
request: "DescribeLayer"
}, parsed.query)
}));
return axios.get(parseUrl(describeLayerUrl)).then((response) => {
let decriptions;
xml2js.parseString(response.data, {explicitArray: false}, (ignore, result) => {
decriptions = result && result.WMS_DescribeLayerResponse && result.WMS_DescribeLayerResponse.LayerDescription;
});
decriptions = Array.isArray(decriptions) ? decriptions : [decriptions];
// make it compatible with json format of describe layer
return decriptions.map(desc => ({
...(desc && desc.$ || {}),
layerName: desc.$ && desc.$.name,
query: {
...(desc && desc.query && desc.query.$ || {})
}
}));
});
},
textSearch: function(url, startPosition, maxRecords, text) {
return Api.getRecords(url, startPosition, maxRecords, text);
}
Expand Down
73 changes: 73 additions & 0 deletions web/client/api/__tests__/WMS-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const expect = require('expect');
const API = require('../WMS');

describe('Test correctness of the WMS APIs', () => {
it('describeLayers', (done) => {
API.describeLayers('base/web/client/test-resources/wms/DescribeLayers.xml', "workspace:vector_layer").then((result) => {
try {
expect(result).toExist();
expect(result.length).toBe(2);
expect(result[0].owsType).toBe("WFS");
done();
} catch(ex) {
done(ex);
}
});
});
it('describeLayer with OGC-SCHEMAS', (done) => {
API.describeLayer('base/web/client/test-resources/wms/DescribeLayers.xml', "workspace:vector_layer").then((result) => {
try {
expect(result).toExist();
expect(result.owsType).toBe("WFS");
done();
} catch(ex) {
done(ex);
}
});
});
it('GetCapabilities 1.3.0', (done) => {
API.getCapabilities('base/web/client/test-resources/wms/GetCapabilities-1.3.0.xml').then((result) => {
try {
expect(result).toExist();
expect(result.capability).toExist();
expect(result.version).toBe("1.3.0");
expect(result.capability.layer).toExist();
done();
} catch(ex) {
done(ex);
}
});
});
it('GetCapabilities 1.1.1', (done) => {
API.getCapabilities('base/web/client/test-resources/wms/GetCapabilities-1.1.1.xml').then((result) => {
try {
expect(result).toExist();
expect(result.capability).toExist();
expect(result.version).toBe("1.1.1");
expect(result.capability.layer).toExist();
done();
} catch(ex) {
done(ex);
}
});
});
it('GetRecords', (done) => {
API.getRecords('base/web/client/test-resources/wms/GetCapabilities-1.3.0.xml', 0, 1, '').then((result) => {
try {
expect(result).toExist();
expect(result.numberOfRecordsMatched).toBe(5);
done();
} catch(ex) {
done(ex);
}
});
});
});
3 changes: 1 addition & 2 deletions web/client/plugins/MetadataExplorer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ const {connect} = require('react-redux');
const assign = require('object-assign');
const {createSelector} = require("reselect");
const {Glyphicon, Panel} = require('react-bootstrap');
const {textSearch, changeCatalogFormat, addLayerError, catalogReset} = require("../actions/catalog");
const {addLayer} = require("../actions/layers");
const {textSearch, changeCatalogFormat, addLayer, addLayerError, catalogReset} = require("../actions/catalog");
const {zoomToExtent} = require("../actions/map");
const {toggleControl} = require("../actions/controls");
const Message = require("../components/I18N/Message");
Expand Down
1 change: 1 addition & 0 deletions web/client/plugins/Save.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const Save = React.createClass({
features: layer.features,
format: layer.format,
group: layer.group,
search: layer.search,
source: layer.source,
name: layer.name,
opacity: layer.opacity,
Expand Down
1 change: 1 addition & 0 deletions web/client/plugins/SaveAs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const SaveAs = React.createClass({
features: layer.features,
format: layer.format,
group: layer.group,
search: layer.search,
source: layer.source,
name: layer.name,
opacity: layer.opacity,
Expand Down
2 changes: 1 addition & 1 deletion web/client/reducers/layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ function layers(state = [], action) {
case ADD_LAYER: {
let newLayers = (state.flat || []).concat();
let newGroups = (state.groups || []).concat();
const newLayer = (action.layer.id) ? action.layer : assign({}, action.layer, {id: action.layer.name + "__" + newLayers.length});
const newLayer = (action.layer.id) ? action.layer : assign({}, action.layer, {id: LayersUtils.getLayerId(action.layer, newLayers)});
newLayers.push(newLayer);
const groupName = newLayer.group || 'Default';
if (groupName !== "background") {
Expand Down
3 changes: 2 additions & 1 deletion web/client/reducers/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const assign = require('object-assign');
const types = {
'xsd:string': 'string',
'xsd:dateTime': 'date',
'xsd:number': 'number'
'xsd:number': 'number',
'xsd:int': 'number'
};
const fieldConfig = {};
const extractInfo = (featureType) => {
Expand Down
10 changes: 10 additions & 0 deletions web/client/test-resources/wms/DescribeLayers.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE WMS_DescribeLayerResponse SYSTEM "http://some.geoserver.org:80/geoserver/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd">
<WMS_DescribeLayerResponse version="1.1.1">
<LayerDescription name="workspace:vector_layer" wfs="http://some.geoserver.org:80/geoserver/wfs?" owsURL="http://some.geoserver.org:80/geoserver/wfs?" owsType="WFS">
<Query typeName="workspace:vector_layer"/>
</LayerDescription>
<LayerDescription name="workspace:raster_layer" owsURL="http://demo.geo-solutions.it:80/geoserver/wcs?" owsType="WCS">
<Query typeName="workspace:raster_layer"/>
</LayerDescription>
</WMS_DescribeLayerResponse>
Loading

0 comments on commit 357e2e7

Please sign in to comment.