Skip to content

Commit

Permalink
feat(must_not_follow_filter): do not allow locality to follow region (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
missinglink authored May 16, 2019
1 parent 93cd613 commit 8780796
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 1 deletion.
3 changes: 3 additions & 0 deletions parser/AddressParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const MultiStreetSolver = require('../solver/MultiStreetSolver')
const InvalidSolutionFilter = require('../solver/InvalidSolutionFilter')
const TokenDistanceFilter = require('../solver/TokenDistanceFilter')
const MustNotPreceedFilter = require('../solver/MustNotPreceedFilter')
const MustNotFollowFilter = require('../solver/MustNotFollowFilter')
const SubsetFilter = require('../solver/SubsetFilter')

class AddressParser extends Parser {
Expand Down Expand Up @@ -95,6 +96,8 @@ class AddressParser extends Parser {
new MustNotPreceedFilter('CountryClassification', 'PostcodeClassification'),
new MustNotPreceedFilter('CountryClassification', 'StreetClassification'),
new MustNotPreceedFilter('CountryClassification', 'HouseNumberClassification'),
new MustNotFollowFilter('LocalityClassification', 'RegionClassification'),
new MustNotFollowFilter('LocalityClassification', 'CountryClassification'),
new TokenDistanceFilter(),
new SubsetFilter()
],
Expand Down
31 changes: 31 additions & 0 deletions solver/MustNotFollowFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// enforce that a object classification cannot follow subject classification
// @todo: handle case of multiple object classifications matching

class MustNotFollowFilter {
constructor (objectClassification, subjectClassification) {
this.classification = {
object: objectClassification,
subject: subjectClassification
}
}
solve (tokenizer) {
tokenizer.solution = tokenizer.solution.filter(s => {
let object = s.pair.filter(p => p.classification.constructor.name === this.classification.object)
let subject = s.pair.filter(p => p.classification.constructor.name === this.classification.subject)

// solution contains both object & subject classifications
if (object.length > 0 && subject.length > 0) {
// the object comes before the subject(s)
if (subject.some(p => p.span.start < object[0].span.end)) {
// remove the object classification from this solution
s.pair = s.pair.filter(p => p.classification.constructor.name !== this.classification.object)
return s.pair.length > 0
}
}

return true
})
}
}

module.exports = MustNotFollowFilter
46 changes: 46 additions & 0 deletions solver/MustNotFollowFilter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const Tokenizer = require('../tokenization/Tokenizer')
const Span = require('../tokenization/Span')
const PostcodeClassification = require('../classification/PostcodeClassification')
const StreetClassification = require('../classification/StreetClassification')
const Solution = require('./Solution')
const SolutionPair = require('./SolutionPair')
const MustNotFollowFilter = require('./MustNotFollowFilter')

module.exports.tests = {}

module.exports.tests.postcode_preceeds_street = (test) => {
test('postcode_preceeds_street: remove postcode', (t) => {
let tok = new Tokenizer()

let s1 = new Span('A')
s1.start = 0
s1.end = 1

let s2 = new Span('B')
s2.start = 3
s2.end = 4

let sp1 = new SolutionPair(s1, new PostcodeClassification(1.0))
let sp2 = new SolutionPair(s2, new StreetClassification(1.0))

tok.solution = [new Solution([sp1, sp2])]

let c = new MustNotFollowFilter('StreetClassification', 'PostcodeClassification')
c.solve(tok)

t.deepEquals(tok.solution.length, 1)
t.deepEquals(tok.solution[0].pair.length, 1)
t.deepEquals(tok.solution[0].pair[0], sp1)
t.end()
})
}

module.exports.all = (tape, common) => {
function test (name, testFunction) {
return tape(`MustNotFollowFilter: ${name}`, testFunction)
}

for (var testCase in module.exports.tests) {
module.exports.tests[testCase](test, common)
}
}
8 changes: 7 additions & 1 deletion test/functional.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const testcase = (test, common) => {
// street with directional, ordinal & admin info
assert('West 26th Street, New York, NYC, 10010', [
{ street: 'West 26th Street' },
{ region: 'New York' }, { locality: 'NYC' },
{ locality: 'New York' },
{ postcode: '10010' }
], true)

Expand Down Expand Up @@ -79,6 +79,12 @@ const testcase = (test, common) => {
assert('1 San Francisco California USA', [])
assert('1 California USA', [])
assert('1 90210', [])

// do not parse 'aus' as a locality if it follows a region
assert('new south wales aus', [
[{ region: 'new south wales' }],
[{ locality: 'south wales' }]]
)
}

module.exports.all = (tape, common) => {
Expand Down

0 comments on commit 8780796

Please sign in to comment.