'use strict'; module.exports = function aggregationValidator (mapconfig) { return function validateProperty (key, validator) { for (let index = 0; index < mapconfig.getLayers().length; index++) { const aggregation = mapconfig.getAggregation(index); if (aggregation === undefined || aggregation[key] === undefined) { continue; } validator(aggregation[key], key, index); } }; }; module.exports.createIncludesValueValidator = function (mapconfig, validValues) { return function validateIncludesValue (value, key, index) { if (!validValues.includes(value)) { const message = `Invalid ${key}. Valid values: ${validValues.join(', ')}`; throw createLayerError(message, mapconfig, index); } }; }; module.exports.createPositiveNumberValidator = function (mapconfig) { return function validatePositiveNumber (value, key, index) { if (!Number.isFinite(value) || value <= 0) { const message = `Invalid ${key}, should be a number greather than 0`; throw createLayerError(message, mapconfig, index); } }; }; module.exports.createAggregationColumnsValidator = function (mapconfig, validAggregatedFunctions) { const validateAggregationColumnNames = createAggregationColumnNamesValidator(mapconfig); const validateAggregateFunction = createAggregateFunctionValidator(mapconfig, validAggregatedFunctions); const validateAggregatedColumn = createAggregatedColumnValidator(mapconfig); return function validateAggregationColumns (value, key, index) { validateAggregationColumnNames(value, key, index); validateAggregateFunction(value, key, index); validateAggregatedColumn(value, key, index); }; }; module.exports.createAggregationFiltersValidator = function (mapconfig, validParameters) { return function validateAggregationFilters (value, key, index) { const dims = mapconfig.getAggregation(index).dimensions || {}; const cols = mapconfig.getAggregation(index).columns || {}; const validKeys = Object.keys(dims).concat(Object.keys(cols)); Object.keys(value).forEach((filteredName) => { // filteredName must be the name of either an aggregated column or a dimension in the same layer if (!validKeys.includes(filteredName)) { const message = `Invalid filtered column: ${filteredName}`; throw createLayerError(message, mapconfig, index); } // The filter parameters must be valid let filters = value[filteredName]; // a single filter or an array of filters (to be OR-combined) are accepted if (!Array.isArray(filters)) { filters = [filters]; } filters.forEach(params => { Object.keys(params).forEach(paramName => { if (!validParameters.includes(paramName)) { const message = `Invalid filter parameter name: ${paramName}`; throw createLayerError(message, mapconfig, index); } }); // TODO: check parameter value (params[paramName]) to be of the correct type }); // TODO: if multiple parameters within params check the combination is valid, // i.e. one of the *less* parameters and one of the *greater* parameters. }); }; }; function createAggregationColumnNamesValidator (mapconfig) { return function validateAggregationColumnNames (value, key, index) { Object.keys(value).forEach((columnName) => { if (columnName.length <= 0) { const message = 'Invalid column name, should be a non empty string'; throw createLayerError(message, mapconfig, index); } }); }; } function createAggregateFunctionValidator (mapconfig, validAggregatedFunctions) { return function validateAggregateFunction (value, key, index) { Object.keys(value).forEach((columnName) => { const { aggregate_function } = value[columnName]; if (!validAggregatedFunctions.includes(aggregate_function)) { const message = `Unsupported aggregation function ${aggregate_function},` + ` valid ones: ${validAggregatedFunctions.join(', ')}`; throw createLayerError(message, mapconfig, index); } }); }; } function createAggregatedColumnValidator (mapconfig) { return function validateAggregatedColumn (value, key, index) { Object.keys(value).forEach((columnName) => { const { aggregated_column } = value[columnName]; if (typeof aggregated_column !== 'string' || aggregated_column <= 0) { const message = 'Invalid aggregated column, should be a non empty string'; throw createLayerError(message, mapconfig, index); } }); }; } function createLayerError (message, mapconfig, index) { const error = new Error(message); error.type = 'layer'; error.layer = { id: mapconfig.getLayerId(index), index: index, type: mapconfig.layerType(index) }; return error; }