Skip to content

Commit e8c4642

Browse files
authored
split osmEntity.id into a new class osmIdManager (#12186)
1 parent 2bafc90 commit e8c4642

11 files changed

Lines changed: 88 additions & 70 deletions

File tree

modules/core/history.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
utilArrayDifference, utilArrayGroupBy, utilArrayUnion,
1313
utilObjectOmit, utilRebind, utilSessionMutex
1414
} from '../util';
15+
import { osmIdManager } from '../osm';
1516

1617

1718
export function coreHistory(context) {
@@ -505,7 +506,7 @@ export function coreHistory(context) {
505506
entities: Object.values(allEntities),
506507
baseEntities: Object.values(baseEntities),
507508
stack: s,
508-
nextIDs: osmEntity.id.next,
509+
nextIDs: osmIdManager.next,
509510
index: _index,
510511
// note the time the changes were saved
511512
timestamp: (new Date()).getTime()
@@ -516,7 +517,7 @@ export function coreHistory(context) {
516517
fromJSON: function(h, loadChildNodes) {
517518
var loadComplete = true;
518519

519-
osmEntity.id.next = h.nextIDs;
520+
osmIdManager.next = h.nextIDs;
520521
_index = h.index;
521522

522523
if (h.version === 2 || h.version === 3) {

modules/osm/entity.js

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { debug } from '../index';
1+
import { debug, osmIdManager } from '../index';
22
import { osmIsInterestingTag } from './tags';
33
import { utilArrayUnion } from '../util/array';
44
import { utilUnicodeCharsTruncated } from '../util/util';
@@ -12,43 +12,14 @@ export function osmEntity(attrs) {
1212
if (attrs && attrs.type) {
1313
return new osmEntity[attrs.type](...arguments);
1414
} else if (attrs && attrs.id) {
15-
return new osmEntity[osmEntity.id.type(attrs.id)](...arguments);
15+
return new osmEntity[osmIdManager.type(attrs.id)](...arguments);
1616
}
1717

1818
// Initialize a generic Entity (used only in tests).
1919
return (new osmEntity()).initialize(arguments);
2020
}
2121

2222

23-
osmEntity.id = function(type) {
24-
return osmEntity.id.fromOSM(type, osmEntity.id.next[type]--);
25-
};
26-
27-
28-
osmEntity.id.next = {
29-
changeset: -1, node: -1, way: -1, relation: -1
30-
};
31-
32-
33-
osmEntity.id.fromOSM = function(type, id) {
34-
return type[0] + id;
35-
};
36-
37-
38-
osmEntity.id.toOSM = function(id) {
39-
var match = id.match(/^[cnwr](-?\d+)$/);
40-
if (match) {
41-
return match[1];
42-
}
43-
return '';
44-
};
45-
46-
47-
osmEntity.id.type = function(id) {
48-
return { 'c': 'changeset', 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
49-
};
50-
51-
5223
// A function suitable for use as the second argument to d3.selection#data().
5324
osmEntity.key = function(entity) {
5425
return entity.id + 'v' + (entity.v || 0);
@@ -84,7 +55,7 @@ osmEntity.prototype = {
8455
}
8556

8657
if (!this.id && this.type) {
87-
this.id = osmEntity.id(this.type);
58+
this.id = osmIdManager.newId(this.type);
8859
}
8960
if (!this.hasOwnProperty('visible')) {
9061
this.visible = true;
@@ -114,12 +85,12 @@ osmEntity.prototype = {
11485

11586

11687
osmId: function() {
117-
return osmEntity.id.toOSM(this.id);
88+
return osmIdManager.toOSM(this.id);
11889
},
11990

12091

12192
isNew: function() {
122-
var osmId = osmEntity.id.toOSM(this.id);
93+
var osmId = osmIdManager.toOSM(this.id);
12394
return osmId.length === 0 || osmId[0] === '-';
12495
},
12596

modules/osm/id_manager.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
export type FeatureType = 'node' | 'way' | 'relation';
2+
3+
/**
4+
* All newly created features need an ID, so this singleton
5+
* class allocates the next available ID, starting from -1
6+
* and decrementing.
7+
*/
8+
class OsmIdManager {
9+
next = {
10+
changeset: -1,
11+
node: -1,
12+
way: -1,
13+
relation: -1,
14+
};
15+
16+
fromOSM(type: FeatureType, id: number) {
17+
return type[0] + id;
18+
}
19+
20+
toOSM(id: string) {
21+
var match = id.match(/^[cnwr](-?\d+)$/);
22+
if (match) {
23+
return match[1];
24+
}
25+
return '';
26+
}
27+
28+
type(id: string) {
29+
return <FeatureType>(
30+
{ c: 'changeset', n: 'node', w: 'way', r: 'relation' }[id[0]]
31+
);
32+
}
33+
34+
key(entity: iD.OsmEntity) {
35+
return entity.id + 'v' + (entity.v || 0);
36+
}
37+
38+
newId(type: FeatureType) {
39+
return this.fromOSM(type, this.next[type]--);
40+
}
41+
}
42+
43+
export const osmIdManager = new OsmIdManager();

modules/osm/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { osmChangeset } from './changeset';
22
export { osmEntity } from './entity';
3+
export * from './id_manager';
34
export { osmNode } from './node';
45
export { osmNote } from './note';
56
export { osmRelation } from './relation';

modules/osm/intersection.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { actionReverse } from '../actions/reverse';
33
import { actionSplit } from '../actions/split';
44
import { coreGraph } from '../core/graph';
55
import { geoAngle, geoSphericalDistance } from '../geo';
6-
import { osmEntity } from './entity';
6+
import { osmIdManager } from './id_manager';
77
import { utilArrayDifference, utilArrayUniq } from '../util';
88

99

@@ -155,7 +155,7 @@ export function osmIntersection(graph, startVertexId, maxDistance) {
155155

156156

157157
// STEP 4: Split ways on key vertices
158-
var origCount = osmEntity.id.next.way;
158+
var origCount = osmIdManager.next.way;
159159
vertices.forEach(function(v) {
160160
// This is an odd way to do it, but we need to find all the ways that
161161
// will be split here, then split them one at a time to ensure that these
@@ -182,7 +182,7 @@ export function osmIntersection(graph, startVertexId, maxDistance) {
182182
// these actions later if the user decides to create a turn restriction
183183
// 2. Avoids churning way ids just by hovering over a vertex
184184
// and displaying the turn restriction editor
185-
osmEntity.id.next.way = origCount;
185+
osmIdManager.next.way = origCount;
186186

187187

188188
// STEP 5: Update arrays to point to vgraph entities

modules/osm/relation.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { geoArea as d3_geoArea } from 'd3-geo';
33
import { osmEntity } from './entity';
44
import { osmJoinWays } from './multipolygon';
55
import { geoExtent, geoPolygonContainsPolygon, geoPolygonIntersectsPolygon } from '../geo';
6+
import { osmIdManager } from './id_manager';
67

78
/**
8-
* @typedef {'node' | 'way' | 'relation'} FeatureType
9-
* @typedef {{ type: FeatureType; id: string; role: string }} RelationMember
9+
* @typedef {{ type: import('./id_manager').FeatureType; id: string; role: string }} RelationMember
1010
*/
1111

1212
/**
@@ -27,8 +27,8 @@ osmRelation.prototype = Object.create(osmEntity.prototype);
2727

2828

2929
osmRelation.creationOrder = function(a, b) {
30-
var aId = parseInt(osmEntity.id.toOSM(a.id), 10);
31-
var bId = parseInt(osmEntity.id.toOSM(b.id), 10);
30+
var aId = parseInt(osmIdManager.toOSM(a.id), 10);
31+
var bId = parseInt(osmIdManager.toOSM(b.id), 10);
3232

3333
if (aId < 0 || bId < 0) return aId - bId;
3434
return bId - aId;
@@ -205,7 +205,7 @@ const prototype = {
205205
keyAttributes: {
206206
type: member.type,
207207
role: member.role,
208-
ref: osmEntity.id.toOSM(member.id)
208+
ref: osmIdManager.toOSM(member.id)
209209
}
210210
};
211211
}, this),

modules/osm/way.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { osmEntity } from './entity';
55
import { osmLanes } from './lanes';
66
import { osmTagSuggestingArea, osmRightSideIsInsideTags, osmRemoveLifecyclePrefix, osmOneWayBiDirectionalTags, osmOneWayBackwardTags, osmOneWayForwardTags, osmOneWayTags } from './tags';
77
import { utilArrayUniq, utilCheckTagDictionary } from '../util';
8+
import { osmIdManager } from './id_manager';
89

910
/**
1011
* @typedef {typeof prototype & iD.AbstractEntity} OsmWay
@@ -478,7 +479,7 @@ const prototype = {
478479
'@id': this.osmId(),
479480
'@version': this.version || 0,
480481
nd: this.nodes.map(function(id) {
481-
return { keyAttributes: { ref: osmEntity.id.toOSM(id) } };
482+
return { keyAttributes: { ref: osmIdManager.toOSM(id) } };
482483
}, this),
483484
tag: Object.keys(this.tags).map(function(k) {
484485
return { keyAttributes: { k: k, v: this.tags[k] } };

modules/services/osm.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import RBush from 'rbush';
77

88
import { JXON } from '../util/jxon';
99
import { geoExtent, geoRawMercator, geoVecAdd, geoZoomToScale } from '../geo';
10-
import { osmEntity, osmNode, osmNote, osmRelation, osmWay } from '../osm';
10+
import { osmIdManager, osmNode, osmNote, osmRelation, osmWay } from '../osm';
1111
import { utilArrayChunk, utilArrayGroupBy, utilArrayUniq, utilObjectOmit, utilRebind, utilTiler, utilQsString } from '../util';
1212
import { localizer } from '../core/localizer.js';
1313
import { utilGzip } from '../util/util';
@@ -206,7 +206,7 @@ function parseJSON(payload, callback, options) {
206206

207207
var uid;
208208

209-
uid = osmEntity.id.fromOSM(child.type, child.id);
209+
uid = osmIdManager.fromOSM(child.type, child.id);
210210
if (options.skipSeen) {
211211
if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
212212
_tileCache.seen[uid] = true;
@@ -484,8 +484,8 @@ export default {
484484
// GET /api/0.6/node/#id
485485
// GET /api/0.6/[way|relation]/#id/full
486486
loadEntity: function(id, callback) {
487-
var type = osmEntity.id.type(id);
488-
var osmID = osmEntity.id.toOSM(id);
487+
var type = osmIdManager.type(id);
488+
var osmID = osmIdManager.toOSM(id);
489489
var options = { skipSeen: false };
490490

491491
this.loadFromAPI(
@@ -514,8 +514,8 @@ export default {
514514
// Load a single entity with a specific version
515515
// GET /api/0.6/[node|way|relation]/#id/#version
516516
loadEntityVersion: function(id, version, callback) {
517-
var type = osmEntity.id.type(id);
518-
var osmID = osmEntity.id.toOSM(id);
517+
var type = osmIdManager.type(id);
518+
var osmID = osmIdManager.toOSM(id);
519519
var options = { skipSeen: false };
520520

521521
this.loadFromAPI(
@@ -531,8 +531,8 @@ export default {
531531
// Load the relations of a single entity with the given.
532532
// GET /api/0.6/[node|way|relation]/#id/relations
533533
loadEntityRelations: function(id, callback) {
534-
var type = osmEntity.id.type(id);
535-
var osmID = osmEntity.id.toOSM(id);
534+
var type = osmIdManager.type(id);
535+
var osmID = osmIdManager.toOSM(id);
536536
var options = { skipSeen: false };
537537

538538
this.loadFromAPI(
@@ -551,11 +551,11 @@ export default {
551551
// GET /api/0.6/[nodes|ways|relations]?#parameters
552552
loadMultiple: function(ids, callback) {
553553
var that = this;
554-
var groups = utilArrayGroupBy(utilArrayUniq(ids), osmEntity.id.type);
554+
var groups = utilArrayGroupBy(utilArrayUniq(ids), osmIdManager.type);
555555

556556
Object.keys(groups).forEach(function(k) {
557557
var type = k + 's'; // nodes, ways, relations
558-
var osmIDs = groups[k].map(function(id) { return osmEntity.id.toOSM(id); });
558+
var osmIDs = groups[k].map(function(id) { return osmIdManager.toOSM(id); });
559559
var options = { skipSeen: false };
560560

561561
utilArrayChunk(osmIDs, 150).forEach(function(arr) {

modules/ui/feature_list.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
utilHighlightEntities,
2323
utilNoAuto
2424
} from '../util';
25+
import { osmIdManager } from '../osm';
2526

2627

2728
export const idMatch = q => {
@@ -214,7 +215,7 @@ export function uiFeatureList(context) {
214215

215216
// Make a temporary osmEntity so we can preset match
216217
// and better localize the search result - #4725
217-
var id = osmEntity.id.fromOSM(d.osm_type, d.osm_id);
218+
var id = osmIdManager.fromOSM(d.osm_type, d.osm_id);
218219
var tags = {};
219220
tags[d.class] = d.type;
220221

test/spec/core/history.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ describe('iD.coreHistory', function () {
403403
expect(history.graph().entity('n-1')).to.eql(new iD.osmNode({id: 'n-1', loc: [1, 2]}));
404404
expect(history.undoAnnotation()).to.eql('Added a point.');
405405
expect(history.imageryUsed()).to.eql(['Bing']);
406-
expect(iD.osmEntity.id.next).to.eql({node: -2, way: -1, relation: -1});
406+
expect(iD.osmIdManager.next).to.eql({node: -2, way: -1, relation: -1});
407407
});
408408

409409
it('restores from v1 JSON (modification)', function() {
@@ -420,7 +420,7 @@ describe('iD.coreHistory', function () {
420420
expect(history.graph().entity('n-1')).to.eql(new iD.osmNode({id: 'n-1', loc: [2, 3], v: 1}));
421421
expect(history.undoAnnotation()).to.eql('Moved a point.');
422422
expect(history.imageryUsed()).to.eql(['Bing']);
423-
expect(iD.osmEntity.id.next).to.eql({node: -2, way: -1, relation: -1});
423+
expect(iD.osmIdManager.next).to.eql({node: -2, way: -1, relation: -1});
424424
});
425425

426426
it('restores from v1 JSON (deletion)', function() {
@@ -437,7 +437,7 @@ describe('iD.coreHistory', function () {
437437
expect(history.graph().hasEntity('n1')).to.be.undefined;
438438
expect(history.undoAnnotation()).to.eql('Deleted a point.');
439439
expect(history.imageryUsed()).to.eql(['Bing']);
440-
expect(iD.osmEntity.id.next).to.eql({node: -1, way: -2, relation: -3});
440+
expect(iD.osmIdManager.next).to.eql({node: -1, way: -2, relation: -3});
441441
});
442442

443443
it('restores from v2 JSON (creation)', function() {
@@ -457,7 +457,7 @@ describe('iD.coreHistory', function () {
457457
expect(history.graph().entity('n-1')).to.eql(new iD.osmNode({id: 'n-1', loc: [1, 2]}));
458458
expect(history.undoAnnotation()).to.eql('Added a point.');
459459
expect(history.imageryUsed()).to.eql(['Bing']);
460-
expect(iD.osmEntity.id.next).to.eql({node: -2, way: -1, relation: -1});
460+
expect(iD.osmIdManager.next).to.eql({node: -2, way: -1, relation: -1});
461461
expect(history.difference().created().length).to.eql(1);
462462
});
463463

@@ -479,7 +479,7 @@ describe('iD.coreHistory', function () {
479479
expect(history.graph().entity('n1')).to.eql(new iD.osmNode({id: 'n1', loc: [2, 3], v: 1}));
480480
expect(history.undoAnnotation()).to.eql('Moved a point.');
481481
expect(history.imageryUsed()).to.eql(['Bing']);
482-
expect(iD.osmEntity.id.next).to.eql({node: -2, way: -1, relation: -1});
482+
expect(iD.osmIdManager.next).to.eql({node: -2, way: -1, relation: -1});
483483
expect(history.difference().modified().length).to.eql(1);
484484
});
485485

@@ -499,7 +499,7 @@ describe('iD.coreHistory', function () {
499499
expect(history.graph().hasEntity('n1')).to.be.undefined;
500500
expect(history.undoAnnotation()).to.eql('Deleted a point.');
501501
expect(history.imageryUsed()).to.eql(['Bing']);
502-
expect(iD.osmEntity.id.next).to.eql({node: -1, way: -2, relation: -3});
502+
expect(iD.osmIdManager.next).to.eql({node: -1, way: -2, relation: -3});
503503
expect(history.difference().deleted().length).to.eql(1);
504504
});
505505

@@ -521,7 +521,7 @@ describe('iD.coreHistory', function () {
521521
expect(history.graph().entity('n-1')).to.eql(new iD.osmNode({id: 'n-1', loc: [1, 2]}));
522522
expect(history.undoAnnotation()).to.eql('Added a point.');
523523
expect(history.imageryUsed()).to.eql(['Bing']);
524-
expect(iD.osmEntity.id.next).to.eql({node: -2, way: -1, relation: -1});
524+
expect(iD.osmIdManager.next).to.eql({node: -2, way: -1, relation: -1});
525525
expect(history.difference().created().length).to.eql(1);
526526
});
527527

@@ -543,7 +543,7 @@ describe('iD.coreHistory', function () {
543543
expect(history.graph().entity('n1')).to.eql(new iD.osmNode({id: 'n1', loc: [2, 3], v: 1}));
544544
expect(history.undoAnnotation()).to.eql('Moved a point.');
545545
expect(history.imageryUsed()).to.eql(['Bing']);
546-
expect(iD.osmEntity.id.next).to.eql({node: -2, way: -1, relation: -1});
546+
expect(iD.osmIdManager.next).to.eql({node: -2, way: -1, relation: -1});
547547
expect(history.difference().modified().length).to.eql(1);
548548
});
549549

@@ -563,7 +563,7 @@ describe('iD.coreHistory', function () {
563563
expect(history.graph().hasEntity('n1')).to.be.undefined;
564564
expect(history.undoAnnotation()).to.eql('Deleted a point.');
565565
expect(history.imageryUsed()).to.eql(['Bing']);
566-
expect(iD.osmEntity.id.next).to.eql({node: -1, way: -2, relation: -3});
566+
expect(iD.osmIdManager.next).to.eql({node: -1, way: -2, relation: -3});
567567
expect(history.difference().deleted().length).to.eql(1);
568568
});
569569
});

0 commit comments

Comments
 (0)