Browse Source

guard clauses, more tests, code cleanup

pull/850/head
Stephen Hess 8 years ago
parent
commit
8a14dcc48a
  1. 43
      controller/placeholder.js
  2. 1541
      test/unit/controller/placeholder.js

43
controller/placeholder.js

@ -1,27 +1,28 @@
'use strict';
const _ = require('lodash'); const _ = require('lodash');
const logger = require('pelias-logger').get('api'); const logger = require('pelias-logger').get('api');
const logging = require( '../helper/logging' );
const Document = require('pelias-model').Document; const Document = require('pelias-model').Document;
// composition of toNumber and isFinite, useful for single call to convert a value // composition of toNumber and isFinite, useful for single call to convert a value
// to a number, then checking to see if it's finite // to a number, then checking to see if it's finite
function isFiniteNumber() { const isFiniteNumber = _.flow(_.toNumber, _.isFinite);
return _.flow(_.toNumber, _.isFinite);
}
// returns true if all 4 ,-delimited (max) substrings are parseable as numbers // returns true if all 4 ,-delimited (max) substrings are parseable as finite numbers
// '12.12,21.21,13.13,31.31' returns true // '12.12,21.21,13.13,31.31' returns true
// '12.12,21.21,13.13,31.31,14.14' returns false
// '12.12,21.21,13.13,blah' returns false // '12.12,21.21,13.13,blah' returns false
// '12.12,21.21,13.13,31.31,blah' returns false // '12.12,21.21,13.13,31.31,blah' returns false
function validBoundingBox(bbox) { // '12.12,NaN,13.13,31.31' returns false
// '12.12,Infinity,13.13,31.31' returns false
function is4CommaDelimitedNumbers(bbox) {
return bbox. return bbox.
split(','). split(',').
filter(isFiniteNumber).length === 4; filter(isFiniteNumber).length === 4;
} }
function hasName(result) {
return !_.isEmpty(_.trim(result.name));
}
function synthesizeDocs(result) { function synthesizeDocs(result) {
const doc = new Document('whosonfirst', result.placetype, result.id.toString()); const doc = new Document('whosonfirst', result.placetype, result.id.toString());
doc.setName('default', result.name); doc.setName('default', result.name);
@ -30,11 +31,11 @@ function synthesizeDocs(result) {
if (_.conformsTo(result.geom, { 'lat': isFiniteNumber, 'lon': isFiniteNumber } )) { if (_.conformsTo(result.geom, { 'lat': isFiniteNumber, 'lon': isFiniteNumber } )) {
doc.setCentroid( { lat: result.geom.lat, lon: result.geom.lon } ); doc.setCentroid( { lat: result.geom.lat, lon: result.geom.lon } );
} else { } else {
console.error('what\'s up with ' + result.id); logger.error(`could not parse centroid for id ${result.id}`);
} }
// lodash conformsTo verifies that an object has a property with a certain format // lodash conformsTo verifies that an object has a property with a certain format
if (_.conformsTo(result.geom, { 'bbox': validBoundingBox } )) { if (_.conformsTo(result.geom, { 'bbox': is4CommaDelimitedNumbers } )) {
const parsedBoundingBox = result.geom.bbox.split(',').map(_.toNumber); const parsedBoundingBox = result.geom.bbox.split(',').map(_.toNumber);
doc.setBoundingBox({ doc.setBoundingBox({
upperLeft: { upperLeft: {
@ -46,12 +47,13 @@ function synthesizeDocs(result) {
lon: parsedBoundingBox[2] lon: parsedBoundingBox[2]
} }
}); });
} else {
logger.error(`could not parse bbox for id ${result.id}: ${result.geom.bbox}`);
} }
if (_.isEmpty(result.lineage)) { if (_.isEmpty(result.lineage)) {
// there are no hierarchies so just return what's been assembled so far // there are no hierarchies so just return what's been assembled so far
return buildESDoc(doc); return buildESDoc(doc);
} }
result.lineage.map((hierarchy) => { result.lineage.map((hierarchy) => {
@ -59,7 +61,9 @@ function synthesizeDocs(result) {
.filter(doc.isSupportedParent) .filter(doc.isSupportedParent)
.filter((placetype) => { return !_.isEmpty(_.trim(hierarchy[placetype].name)); } ) .filter((placetype) => { return !_.isEmpty(_.trim(hierarchy[placetype].name)); } )
.forEach((placetype) => { .forEach((placetype) => {
if (hierarchy[placetype].hasOwnProperty('abbr') && placetype === 'country') { if (placetype === 'country' &&
hierarchy[placetype].hasOwnProperty('abbr') &&
hierarchy[placetype].abbr.match(/^[a-zA-Z]{3}$/)) {
doc.setAlpha3(hierarchy[placetype].abbr); doc.setAlpha3(hierarchy[placetype].abbr);
} }
@ -78,9 +82,7 @@ function synthesizeDocs(result) {
function buildESDoc(doc) { function buildESDoc(doc) {
const esDoc = doc.toESDocument(); const esDoc = doc.toESDocument();
esDoc.data._id = esDoc._id; return _.extend(esDoc.data, { _id: esDoc._id, _type: esDoc._type });
esDoc.data._type = esDoc._type;
return esDoc.data;
} }
function setup(placeholderService, should_execute) { function setup(placeholderService, should_execute) {
@ -103,7 +105,7 @@ function setup(placeholderService, should_execute) {
// filter that passes only results that match on requested layers // filter that passes only results that match on requested layers
// passes everything if req.clean.layers is not found // passes everything if req.clean.layers is not found
const matchesLayers = (result) => { const matchesLayers = (result) => {
return req.clean.layers.indexOf(result.placetype) >= 0; return _.includes(req.clean.layers, result.placetype);
}; };
const layersFilter = _.get(req, 'clean.layers', []).length ? const layersFilter = _.get(req, 'clean.layers', []).length ?
matchesLayers : _.constant(true); matchesLayers : _.constant(true);
@ -111,8 +113,7 @@ function setup(placeholderService, should_execute) {
// filter that passes only documents that match on boundary.country // filter that passes only documents that match on boundary.country
// passed everything if req.clean['boundary.country'] is not found // passed everything if req.clean['boundary.country'] is not found
const matchesBoundaryCountry = (doc) => { const matchesBoundaryCountry = (doc) => {
return doc.parent.country_a && return _.includes(doc.parent.country_a, req.clean['boundary.country']);
doc.parent.country_a.indexOf(req.clean['boundary.country']) > -1;
}; };
const countryFilter = _.has(req, ['clean', 'boundary.country']) ? const countryFilter = _.has(req, ['clean', 'boundary.country']) ?
matchesBoundaryCountry : _.constant(true); matchesBoundaryCountry : _.constant(true);
@ -122,12 +123,12 @@ function setup(placeholderService, should_execute) {
// lineages may produce different country docs // lineages may produce different country docs
res.meta = {}; res.meta = {};
res.data = _.flatten( res.data = _.flatten(
results.filter(layersFilter).map(synthesizeDocs)) results.filter(hasName).filter(layersFilter).map(synthesizeDocs))
.filter(countryFilter); .filter(countryFilter);
const messageParts = [ const messageParts = [
'[controller:placeholder]', '[controller:placeholder]',
`[result_count:${_.get(res, 'data', []).length}]` `[result_count:${_.defaultTo(res.data, []).length}]`
]; ];
logger.info(messageParts.join(' ')); logger.info(messageParts.join(' '));

1541
test/unit/controller/placeholder.js

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save