order to-be-created relations by dependencies in a changeset

This commit is contained in:
mstn
2017-03-02 09:17:08 +01:00
parent 8d0c49d8d7
commit 3205650798
2 changed files with 76 additions and 1 deletions
+47 -1
View File
@@ -314,6 +314,52 @@ export default {
});
return ordered;
}
// sort relations in a changeset by dependencies
function sort(changes) {
// find a referenced relation in the current changeset
function resolve(item){
return _.find(relations, function(relation) {
return item.keyAttributes.ref === relation['@id'];
});
}
// a new item is an item that has not been already processed
function isNew(item) {
return !sorted[ item['@id'] ] && !_.find(processing, function(proc){
return proc['@id'] === item['@id'];
});
}
var processing = [],
sorted = {},
relations = changes.relation;
if (!relations) return changes;
for (var i = 0; i < relations.length; i++) {
var relation = relations[i];
// skip relation if already sorted
if ( !sorted[relation['@id']] ) {
processing.push( relation );
}
while ( processing.length > 0 ){
var next = processing[0],
deps = _.filter( _.compact(next.member.map(resolve)), isNew);
if ( deps.length === 0 ){
sorted[ next['@id'] ] = next;
processing.shift();
} else {
processing = deps.concat( processing );
}
}
}
changes.relation = _.values(sorted);
return changes;
}
function rep(entity) {
return entity.asJXON(changeset_id);
@@ -323,7 +369,7 @@ export default {
osmChange: {
'@version': 0.6,
'@generator': 'iD',
'create': nest(changes.created.map(rep), ['node', 'way', 'relation']),
'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
}
+29
View File
@@ -362,6 +362,35 @@ describe('iD.serviceOsm', function () {
]);
});
it('includes creations ordered by dependencies', function() {
var n = iD.Node({loc: [0, 0]}),
w = iD.Way({nodes: [n.id]}),
r1 = iD.Relation({members: [{id: w.id}]}),
r2 = iD.Relation({members: [{id: r1.id}]}),
changes = {created: [r2, r1, w, n], modified: [], deleted: []},
jxon = connection.osmChangeJXON('1234', changes);
expect(d3.entries(jxon.osmChange.create)).to.eql([
{key: 'node', value: [n.asJXON('1234').node]},
{key: 'way', value: [w.asJXON('1234').way]},
{key: 'relation', value: [r1.asJXON('1234').relation, r2.asJXON('1234').relation]},
]);
});
it('includes creations ignoring circular dependencies', function() {
var r1 = iD.Relation(),
r2 = iD.Relation(),
changes, jxon;
r1.addMember({id: r2.id});
r2.addMember({id: r1.id});
changes = {created: [r1,r2], modified: [], deleted: []};
jxon = connection.osmChangeJXON('1234', changes);
expect(d3.entries(jxon.osmChange.create)).to.eql([
{key: 'relation', value: [r1.asJXON('1234').relation, r2.asJXON('1234').relation]},
]);
});
it('includes modifications', function() {
var n = iD.Node({loc: [0, 0]}),
w = iD.Way(),