Files
iD/js/id/core/entity.js
Bryan Housel cb0e8ab66c Initial support for Multi Fetch GET
It will also be much faster to fetch the remote entities in batches
rather than one at a time through LoadEntity.

One bonus/hazard with Multi Fetch GET is that it will get deleted entities
with `visible=false`, rather than returning a HTTP Status Code 410 (Gone).

This will be the only way that we can really do proper undeletion
(Incrementing the current version by 1 is not guaranteed to work.  And
if a way is moved, fetching way/full will tell us whether the childnodes
are part of the way, but not necessarily whether they exist or not.)

We must be careful never to merge deleted entities into the real graph.
e.g, a deleted node will not have a 'loc' attribute, so code that assumes
every node must have a `loc` will be broken.

So because deleted entities are very special, the output from `loadMultiple`
should only be used for conflict resolution for now.
2015-03-03 20:54:09 -05:00

149 lines
4.1 KiB
JavaScript

iD.Entity = function(attrs) {
// For prototypal inheritance.
if (this instanceof iD.Entity) return;
// Create the appropriate subtype.
if (attrs && attrs.type) {
return iD.Entity[attrs.type].apply(this, arguments);
} else if (attrs && attrs.id) {
return iD.Entity[iD.Entity.id.type(attrs.id)].apply(this, arguments);
}
// Initialize a generic Entity (used only in tests).
return (new iD.Entity()).initialize(arguments);
};
iD.Entity.id = function(type) {
return iD.Entity.id.fromOSM(type, iD.Entity.id.next[type]--);
};
iD.Entity.id.next = {node: -1, way: -1, relation: -1};
iD.Entity.id.fromOSM = function(type, id) {
return type[0] + id;
};
iD.Entity.id.toOSM = function(id) {
return id.slice(1);
};
iD.Entity.id.type = function(id) {
return {'n': 'node', 'w': 'way', 'r': 'relation'}[id[0]];
};
// A function suitable for use as the second argument to d3.selection#data().
iD.Entity.key = function(entity) {
return entity.id + 'v' + (entity.v || 0);
};
iD.Entity.prototype = {
tags: {},
initialize: function(sources) {
for (var i = 0; i < sources.length; ++i) {
var source = sources[i];
for (var prop in source) {
if (Object.prototype.hasOwnProperty.call(source, prop)) {
if (source[prop] === undefined) {
delete this[prop];
} else {
this[prop] = source[prop];
}
}
}
}
if (!this.id && this.type) {
this.id = iD.Entity.id(this.type);
}
if (!this.hasOwnProperty('visible')) {
this.visible = true;
}
if (iD.debug) {
Object.freeze(this);
Object.freeze(this.tags);
if (this.loc) Object.freeze(this.loc);
if (this.nodes) Object.freeze(this.nodes);
if (this.members) Object.freeze(this.members);
}
return this;
},
copy: function() {
// Returns an array so that we can support deep copying ways and relations.
// The first array element will contain this.copy, followed by any descendants.
return [iD.Entity(this, {id: undefined, user: undefined, version: undefined})];
},
osmId: function() {
return iD.Entity.id.toOSM(this.id);
},
isNew: function() {
return this.osmId() < 0;
},
update: function(attrs) {
return iD.Entity(this, attrs, {v: 1 + (this.v || 0)});
},
mergeTags: function(tags) {
var merged = _.clone(this.tags), changed = false;
for (var k in tags) {
var t1 = merged[k],
t2 = tags[k];
if (!t1) {
changed = true;
merged[k] = t2;
} else if (t1 !== t2) {
changed = true;
merged[k] = _.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
}
}
return changed ? this.update({tags: merged}) : this;
},
intersects: function(extent, resolver) {
return this.extent(resolver).intersects(extent);
},
isUsed: function(resolver) {
return _.without(Object.keys(this.tags), 'area').length > 0 ||
resolver.parentRelations(this).length > 0;
},
hasInterestingTags: function() {
return _.keys(this.tags).some(function(key) {
return key !== 'attribution' &&
key !== 'created_by' &&
key !== 'source' &&
key !== 'odbl' &&
key.indexOf('tiger:') !== 0;
});
},
isHighwayIntersection: function() {
return false;
},
deprecatedTags: function() {
var tags = _.pairs(this.tags);
var deprecated = {};
iD.data.deprecated.forEach(function(d) {
var match = _.pairs(d.old)[0];
tags.forEach(function(t) {
if (t[0] === match[0] &&
(t[1] === match[1] || match[1] === '*')) {
deprecated[t[0]] = t[1];
}
});
});
return deprecated;
}
};