1 package net.systemeD.halcyon.connection {
3 import flash.events.EventDispatcher;
4 import flash.utils.Dictionary;
6 import net.systemeD.halcyon.connection.actions.*;
8 public class Entity extends EventDispatcher {
9 private var _id:Number;
10 private var _version:uint;
11 private var _uid:Number;
12 private var _timestamp:String;
13 private var tags:Object = {};
14 private var modified:Boolean = false;
15 private var _loaded:Boolean = true;
16 private var parents:Dictionary = new Dictionary();
17 private var locked:Boolean = false;
18 public var deleted:Boolean = false;
20 public function Entity(id:Number, version:uint, tags:Object, loaded:Boolean, uid:Number, timestamp:String) {
22 this._version = version;
24 this._timestamp = timestamp;
26 this._loaded = loaded;
30 public function get id():Number {
34 public function get version():uint {
38 public function get uid():Number {
42 public function get loaded():Boolean {
46 public function updateEntityProperties(version:uint, tags:Object, loaded:Boolean, uid:Number, timestamp:String):void {
47 _version=version; this.tags=tags; _loaded=loaded; _uid = uid; _timestamp = timestamp;
50 // Tag-handling methods
52 public function hasTags():Boolean {
53 for (var key:String in tags)
58 public function hasInterestingTags():Boolean {
59 for (var key:String in tags) {
60 if (key != "attribution" && key != "created_by" && key != "source" && key.indexOf('tiger:') != 0) {
68 public function isUneditedTiger():Boolean {
69 // todo: make this match the rules from the tiger edited map
70 // http://github.com/MapQuest/TIGER-Edited-map/blob/master/inc/layer-tiger.xml.inc
71 if (this is Way && (uid == 7168 || uid == 15169 || uid == 20587)) {//todo fixme etc
77 public function getTag(key:String):String {
81 public function tagIs(key:String,value:String):Boolean {
82 if (!tags[key]) { return false; }
83 return tags[key]==value;
86 public function setTag(key:String, value:String, performAction:Function):void {
87 performAction(new SetTagAction(this, key, value));
90 public function renameTag(oldKey:String, newKey:String, performAction:Function):void {
91 performAction(new SetTagKeyAction(this, oldKey, newKey));
94 public function getTagList():TagList {
95 return new TagList(tags);
98 public function getTagsCopy():Object {
100 for (var key:String in tags )
101 copy[key] = tags[key];
105 public function getTagsHash():Object {
106 // hm, not sure we should be doing this, but for read-only purposes
107 // it's faster than using getTagsCopy
111 public function getTagArray():Array {
113 for (var key:String in tags )
114 copy.push(new Tag(this, key, tags[key]));
118 // Clean/dirty methods
120 public function get isDirty():Boolean {
124 public function markClean(newID:Number, newVersion:uint):void {
126 this._version = newVersion;
130 internal function markDirty():void {
136 public function remove(performAction:Function):void {
140 public function isDeleted():Boolean {
144 public function setDeletedState(isDeleted:Boolean):void {
147 var n:Node = Node(this);
148 Connection.getConnection().removeDupe(n);
149 } else if (this is Node) {
150 Connection.getConnection().addDupe(n.id, n.lat, n.lon);
154 internal function isEmpty():Boolean {
155 return false; // to be overridden
158 public function within(left:Number,right:Number,top:Number,bottom:Number):Boolean {
159 return true; // to be overridden
162 public function removeFromParents(performAction:Function):void {
163 for (var o:Object in parents) {
164 if (o is Relation) { Relation(o).removeMember(this, performAction); }
165 else if (o is Way) { Way(o).removeNode(Node(this), performAction); }
166 if (o.isEmpty()) { o.remove(performAction); }
172 public function addParent(parent:Entity):void {
173 parents[parent]=true;
175 if ( parent is Relation )
176 dispatchEvent(new RelationMemberEvent(Connection.ADDED_TO_RELATION, this, parent as Relation, -1));
179 public function removeParent(parent:Entity):void {
180 delete parents[parent];
182 if ( parent is Relation )
183 dispatchEvent(new RelationMemberEvent(Connection.REMOVED_FROM_RELATION, this, parent as Relation, -1));
186 public function get parentWays():Array {
188 for (var o:Object in parents) {
189 if (o is Way) { a.push(o); }
194 public function get hasParents():Boolean {
195 for (var o:Object in parents) { return true; }
199 public function get hasParentWays():Boolean {
200 for (var o:Object in parents) {
201 if (o is Way) { return true; }
206 public function get numParentWays():uint {
208 for (var o:Object in parents) {
209 if (o is Way) { i++; }
214 public function get parentRelations():Array {
216 for (var o:Object in parents) {
217 if (o is Relation) { a.push(o); }
222 public function findParentRelationsOfType(type:String, role:String=null):Array {
224 for (var o:Object in parents) {
225 if (o is Relation && Relation(o).tagIs('type',type) && (role==null || Relation(o).hasMemberInRole(this,role))) {
232 public function countParentObjects(within:Object):uint {
234 for (var o:Object in parents) {
235 if (o.getType()==within.entity && o.getTag(within.k)) {
236 if (within.v && within.v!=o.getTag(within.k)) { break; }
237 if (within.role && !Relation(o).hasMemberInRole(this,within.role)) { break; }
244 public function get parentObjects():Array {
246 for (var o:Object in parents) { a.push(o); }
250 public function hasParent(entity:Entity):Boolean {
251 return parents[entity] == true;
254 public function get memberships():Array {
256 for (var o:Object in parents) {
258 for (var i:uint=0; i<o.length; i++) {
259 if (o.getMember(i).entity==this) {
260 list.push( { relation:o, position:i, role: o.getMember(i).role } );
265 // it's useful to return in a sorted order, even if the relations are interleaved
266 // e.g. [{r0 p1},{r1 p1},{r0 p4}]
267 return list.sortOn("position");
270 // Resume/suspend redraw
272 public function suspend():void {
273 dispatchEvent(new EntityEvent(Connection.SUSPEND_REDRAW, this));
276 public function resume():void {
277 dispatchEvent(new EntityEvent(Connection.RESUME_REDRAW, this));
282 public function getDescription():String {
283 var basic:String=this.getType()+" "+_id;
284 if (tags['ref'] && tags['name']) { return tags['ref']+' '+tags['name']+' ('+basic+')'; }
285 if (tags['ref']) { return tags['ref']+' ('+basic+')'; }
286 if (tags['name']) { return tags['name']+' ('+basic+')'; }
290 public function getType():String {