Update dupes when node is moved / deleted. Needs further refactoring
[potlatch2.git] / net / systemeD / halcyon / connection / Entity.as
index 66f0ff0167a3ebe8902b77d4c06bc5b7310bf765..392a890a16d622ac5d7a67b6637ed2953436220c 100644 (file)
@@ -2,20 +2,26 @@ package net.systemeD.halcyon.connection {
 
     import flash.events.EventDispatcher;
     import flash.utils.Dictionary;
+    
+    import net.systemeD.halcyon.connection.actions.*;
 
     public class Entity extends EventDispatcher {
         private var _id:Number;
         private var _version:uint;
+        private var _uid:Number;
+        private var _timestamp:String;
         private var tags:Object = {};
         private var modified:Boolean = false;
                private var _loaded:Boolean = true;
                private var parents:Dictionary = new Dictionary();
                private var locked:Boolean = false;
-               protected var deleted:Boolean = false;
+               public var deleted:Boolean = false;
 
-        public function Entity(id:Number, version:uint, tags:Object, loaded:Boolean) {
+        public function Entity(id:Number, version:uint, tags:Object, loaded:Boolean, uid:Number, timestamp:String) {
             this._id = id;
             this._version = version;
+            this._uid = uid;
+            this._timestamp = timestamp;
             this.tags = tags;
                        this._loaded = loaded;
             modified = id < 0;
@@ -29,12 +35,16 @@ package net.systemeD.halcyon.connection {
             return _version;
         }
 
+        public function get uid():Number {
+            return _uid;
+        }
+
         public function get loaded():Boolean {
             return _loaded;
         }
 
-               public function updateEntityProperties(version:uint, tags:Object, loaded:Boolean):void {
-                       _version=version; this.tags=tags; _loaded=loaded;
+               public function updateEntityProperties(version:uint, tags:Object, loaded:Boolean, uid:Number, timestamp:String):void {
+                       _version=version; this.tags=tags; _loaded=loaded; _uid = uid; _timestamp = timestamp;
                }
 
                // Tag-handling methods
@@ -45,32 +55,40 @@ package net.systemeD.halcyon.connection {
             return false;
         }
 
-               // ** we could do with hasInterestingTags - don't bother with source, created_by, any TIGER tags, etc.
+        public function hasInterestingTags():Boolean {
+            for (var key:String in tags) {
+              if (key != "attribution" && key != "created_by" && key != "source" && key.indexOf('tiger:') != 0) {
+                //trace(key);
+                return true;
+              }
+            }
+            return false;
+        }
+
+        public function isUneditedTiger():Boolean {
+            // todo: make this match the rules from the tiger edited map
+            // http://github.com/MapQuest/TIGER-Edited-map/blob/master/inc/layer-tiger.xml.inc
+            if (this is Way && (uid == 7168 || uid == 15169 || uid == 20587)) {//todo fixme etc
+              return true;
+            }
+            return false;
+        }
 
         public function getTag(key:String):String {
             return tags[key];
         }
 
-        public function setTag(key:String, value:String):void {
-            var old:String = tags[key];
-            if ( old != value ) {
-                if ( value == null || value == "" )
-                    delete tags[key];
-                else
-                    tags[key] = value;
-                markDirty();
-                dispatchEvent(new TagEvent(Connection.TAG_CHANGE, this, key, key, old, value));
-            }
+               public function tagIs(key:String,value:String):Boolean {
+                       if (!tags[key]) { return false; }
+                       return tags[key]==value;
+               }
+        
+        public function setTag(key:String, value:String, performAction:Function):void {
+            performAction(new SetTagAction(this, key, value));
         }
 
-        public function renameTag(oldKey:String, newKey:String):void {
-            var value:String = tags[oldKey];
-            if ( oldKey != newKey ) {
-                delete tags[oldKey];
-                tags[newKey] = value;
-                markDirty();
-                dispatchEvent(new TagEvent(Connection.TAG_CHANGE, this, oldKey, newKey, value, value));
-            }
+        public function renameTag(oldKey:String, newKey:String, performAction:Function):void {
+            performAction(new SetTagKeyAction(this, oldKey, newKey));
         }
 
         public function getTagList():TagList {
@@ -109,25 +127,43 @@ package net.systemeD.halcyon.connection {
             modified = false;
         }
 
-        protected function markDirty():void {
+        internal function markDirty():void {
             modified = true;
         }
 
                // Delete entity
                
-               public function remove():void {
+               public function remove(performAction:Function):void {
                        // to be overridden
                }
                
+               public function isDeleted():Boolean {
+                   return deleted;
+               }
+               
+               public function setDeletedState(isDeleted:Boolean):void {
+                   deleted = isDeleted;
+            if (this is Node) {
+              var n:Node = Node(this);
+              Connection.getConnection().removeDupe(n);
+            } else if (this is Node) {
+              Connection.getConnection().addDupe(n.id, n.lat, n.lon);
+            }
+               }
+               
                internal function isEmpty():Boolean {
                        return false;   // to be overridden
                }
+               
+               public function within(left:Number,right:Number,top:Number,bottom:Number):Boolean {
+                       return true;    // to be overridden
+               }
 
-               protected function removeFromParents():void {
+               public function removeFromParents(performAction:Function):void {
                        for (var o:Object in parents) {
-                               if (o is Relation) { Relation(o).removeMember(this); }
-                               else if (o is Way) { Way(o).removeNode(Node(this)); }
-                               if (o.isEmpty()) { o.remove(); }
+                               if (o is Relation) { Relation(o).removeMember(this, performAction); }
+                               else if (o is Way) { Way(o).removeNode(Node(this), performAction); }
+                               if (o.isEmpty()) { o.remove(performAction); }
                        }
                }
 
@@ -135,10 +171,16 @@ package net.systemeD.halcyon.connection {
                
                public function addParent(parent:Entity):void {
                        parents[parent]=true;
+                       
+                       if ( parent is Relation )
+                           dispatchEvent(new RelationMemberEvent(Connection.ADDED_TO_RELATION, this, parent as Relation, -1));
                }
 
                public function removeParent(parent:Entity):void {
                        delete parents[parent];
+
+                       if ( parent is Relation )
+                           dispatchEvent(new RelationMemberEvent(Connection.REMOVED_FROM_RELATION, this, parent as Relation, -1));
                }
                
                public function get parentWays():Array {
@@ -177,6 +219,28 @@ package net.systemeD.halcyon.connection {
                        return a;
                }
                
+               public function findParentRelationsOfType(type:String, role:String=null):Array {
+                       var a:Array=[];
+                       for (var o:Object in parents) {
+                               if (o is Relation && Relation(o).tagIs('type',type) && (role==null || Relation(o).hasMemberInRole(this,role))) { 
+                                       a.push(o);
+                               }
+                       }
+                       return a;
+               }
+               
+               public function countParentObjects(within:Object):uint {
+                       var count:uint=0;
+                       for (var o:Object in parents) {
+                               if (o.getType()==within.entity && o.getTag(within.k)) {
+                                       if (within.v && within.v!=o.getTag(within.k)) { break; }
+                                       if (within.role && !Relation(o).hasMemberInRole(this,within.role)) { break; }
+                                       count++;
+                               }
+                       }
+                       return count;
+               }
+               
                public function get parentObjects():Array {
                        var a:Array=[];
                        for (var o:Object in parents) { a.push(o); }
@@ -186,9 +250,43 @@ package net.systemeD.halcyon.connection {
                public function hasParent(entity:Entity):Boolean {
             return parents[entity] == true;
         }
-        
+
+               public function get memberships():Array {
+                       var list:Array=[];
+                       for (var o:Object in parents) {
+                               if (o is Relation) {
+                                       for (var i:uint=0; i<o.length; i++) {
+                                               if (o.getMember(i).entity==this) {
+                                                       list.push( { relation:o, position:i, role: o.getMember(i).role } );
+                                               }
+                                       }
+                               }
+                       }
+            // it's useful to return in a sorted order, even if the relations are interleaved
+            // e.g. [{r0 p1},{r1 p1},{r0 p4}]
+                       return list.sortOn("position"); 
+               }
+
+               // Resume/suspend redraw
+               
+               public function suspend():void {
+                       dispatchEvent(new EntityEvent(Connection.SUSPEND_REDRAW, this));
+               }
+               
+               public function resume():void {
+                       dispatchEvent(new EntityEvent(Connection.RESUME_REDRAW, this));
+               }
+
                // To be overridden
 
+               public function getDescription():String {
+                       var basic:String=this.getType()+" "+_id;
+                       if (tags['ref'] && tags['name']) { return tags['ref']+' '+tags['name']+' ('+basic+')'; }
+                       if (tags['ref']) { return tags['ref']+' ('+basic+')'; }
+                       if (tags['name']) { return tags['name']+' ('+basic+')'; }
+                       return basic;
+               }
+
         public function getType():String {
             return '';
         }
@@ -196,3 +294,4 @@ package net.systemeD.halcyon.connection {
     }
 
 }
+