basic multipolygon rendering
[potlatch2.git] / net / systemeD / halcyon / connection / Entity.as
1 package net.systemeD.halcyon.connection {
2
3     import flash.events.EventDispatcher;
4     import flash.utils.Dictionary;
5     
6     import net.systemeD.halcyon.connection.actions.*;
7
8     public class Entity extends EventDispatcher {
9         private var _id:Number;
10         private var _version:uint;
11         private var tags:Object = {};
12         private var modified:Boolean = false;
13                 private var _loaded:Boolean = true;
14                 private var parents:Dictionary = new Dictionary();
15                 private var locked:Boolean = false;
16                 public var deleted:Boolean = false;
17
18         public function Entity(id:Number, version:uint, tags:Object, loaded:Boolean) {
19             this._id = id;
20             this._version = version;
21             this.tags = tags;
22                         this._loaded = loaded;
23             modified = id < 0;
24         }
25
26         public function get id():Number {
27             return _id;
28         }
29
30         public function get version():uint {
31             return _version;
32         }
33
34         public function get loaded():Boolean {
35             return _loaded;
36         }
37
38                 public function updateEntityProperties(version:uint, tags:Object, loaded:Boolean):void {
39                         _version=version; this.tags=tags; _loaded=loaded;
40                 }
41
42                 // Tag-handling methods
43
44         public function hasTags():Boolean {
45             for (var key:String in tags)
46                 return true;
47             return false;
48         }
49
50                 // ** we could do with hasInterestingTags - don't bother with source, created_by, any TIGER tags, etc.
51
52         public function getTag(key:String):String {
53             return tags[key];
54         }
55
56                 public function tagIs(key:String,value:String):Boolean {
57                         if (!tags[key]) { return false; }
58                         return tags[key]==value;
59                 }
60         
61         public function setTag(key:String, value:String, performAction:Function):void {
62             performAction(new SetTagAction(this, key, value));
63         }
64
65         public function renameTag(oldKey:String, newKey:String, performAction:Function):void {
66             performAction(new SetTagKeyAction(this, oldKey, newKey));
67         }
68
69         public function getTagList():TagList {
70             return new TagList(tags);
71         }
72
73         public function getTagsCopy():Object {
74             var copy:Object = {};
75             for (var key:String in tags )
76                 copy[key] = tags[key];
77             return copy;
78         }
79
80                 public function getTagsHash():Object {
81                         // hm, not sure we should be doing this, but for read-only purposes
82                         // it's faster than using getTagsCopy
83                         return tags;
84                 }
85
86         public function getTagArray():Array {
87             var copy:Array = [];
88             for (var key:String in tags )
89                 copy.push(new Tag(this, key, tags[key]));
90             return copy;
91         }
92
93                 // Clean/dirty methods
94
95         public function get isDirty():Boolean {
96             return modified;
97         }
98
99         public function markClean(newID:Number, newVersion:uint):void {
100             this._id = newID;
101             this._version = newVersion;
102             modified = false;
103         }
104
105         internal function markDirty():void {
106             modified = true;
107         }
108
109                 // Delete entity
110                 
111                 public function remove(performAction:Function):void {
112                         // to be overridden
113                 }
114                 
115                 public function isDeleted():Boolean {
116                     return deleted;
117                 }
118                 
119                 public function setDeletedState(isDeleted:Boolean):void {
120                     deleted = isDeleted;
121                 }
122                 
123                 internal function isEmpty():Boolean {
124                         return false;   // to be overridden
125                 }
126                 
127                 public function within(left:Number,right:Number,top:Number,bottom:Number):Boolean {
128                         return true;    // to be overridden
129                 }
130
131                 public function removeFromParents(performAction:Function):void {
132                         for (var o:Object in parents) {
133                                 if (o is Relation) { Relation(o).removeMember(this, performAction); }
134                                 else if (o is Way) { Way(o).removeNode(Node(this), performAction); }
135                                 if (o.isEmpty()) { o.remove(performAction); }
136                         }
137                 }
138
139                 // Parent handling
140                 
141                 public function addParent(parent:Entity):void {
142                         parents[parent]=true;
143                         
144                         if ( parent is Relation )
145                             dispatchEvent(new RelationMemberEvent(Connection.ADDED_TO_RELATION, this, parent as Relation, -1));
146                 }
147
148                 public function removeParent(parent:Entity):void {
149                         delete parents[parent];
150
151                         if ( parent is Relation )
152                             dispatchEvent(new RelationMemberEvent(Connection.REMOVED_FROM_RELATION, this, parent as Relation, -1));
153                 }
154                 
155                 public function get parentWays():Array {
156                         var a:Array=[];
157                         for (var o:Object in parents) {
158                                 if (o is Way) { a.push(o); }
159                         }
160                         return a;
161                 }
162
163                 public function get hasParents():Boolean {
164                         for (var o:Object in parents) { return true; }
165                         return false;
166                 }
167                 
168                 public function get hasParentWays():Boolean {
169                         for (var o:Object in parents) {
170                                 if (o is Way) { return true; }
171                         }
172                         return false;
173                 }
174                 
175                 public function get numParentWays():uint {
176                         var i:uint=0;
177                         for (var o:Object in parents) {
178                                 if (o is Way) { i++; }
179                         }
180                         return i;
181                 }
182                 
183                 public function get parentRelations():Array {
184                         var a:Array=[];
185                         for (var o:Object in parents) {
186                                 if (o is Relation) { a.push(o); }
187                         }
188                         return a;
189                 }
190                 
191                 public function findParentRelationsOfType(type:String, role:String=""):Array {
192                         var a:Array=[];
193                         for (var o:Object in parents) {
194                                 if (o is Relation && Relation(o).tagIs('type',type)) { 
195                                         for (var i:uint=0; i<o.length; i++) {
196                                                 if (o.getMember(i).entity==this && o.getMember(i).role==role) {
197                                                         a.push(o);
198                                                 }
199                                         }
200                                 }
201                         }
202                         return a;
203                 }
204                 
205                 public function get parentObjects():Array {
206                         var a:Array=[];
207                         for (var o:Object in parents) { a.push(o); }
208                         return a;
209                 }
210                 
211                 public function hasParent(entity:Entity):Boolean {
212             return parents[entity] == true;
213         }
214
215                 public function get memberships():Array {
216                         var list:Array=[];
217                         for (var o:Object in parents) {
218                                 if (o is Relation) {
219                                         for (var i:uint=0; i<o.length; i++) {
220                                                 if (o.getMember(i).entity==this) {
221                                                         list.push( { relation:o, position:i, role: o.getMember(i).role } );
222                                                 }
223                                         }
224                                 }
225                         }
226             // it's useful to return in a sorted order, even if the relations are interleaved
227             // e.g. [{r0 p1},{r1 p1},{r0 p4}]
228                         return list.sortOn("position"); 
229                 }
230
231                 // Resume/suspend redraw
232                 
233                 public function suspend():void {
234                         dispatchEvent(new EntityEvent(Connection.SUSPEND_REDRAW, this));
235                 }
236                 
237                 public function resume():void {
238                         dispatchEvent(new EntityEvent(Connection.RESUME_REDRAW, this));
239                 }
240
241                 // To be overridden
242
243         public function getType():String {
244             return '';
245         }
246
247     }
248
249 }
250