Shift-R: paste relations from previously selected object, as per #3596.
[potlatch2.git] / net / systemeD / halcyon / connection / Relation.as
1 package net.systemeD.halcyon.connection {
2
3         import net.systemeD.halcyon.connection.actions.*;
4
5     public class Relation extends Entity {
6         private var members:Array;
7                 public static var entity_type:String = 'relation';
8
9         public function Relation(connection:Connection, id:Number, version:uint, tags:Object, loaded:Boolean, members:Array, uid:Number = NaN, timestamp:String = null) {
10             super(connection, id, version, tags, loaded, uid, timestamp);
11             this.members = members;
12                         for each (var member:RelationMember in members)
13                             member.entity.addParent(this);
14         }
15
16         public function update(version:uint, tags:Object, loaded:Boolean, parentsLoaded:Boolean, members:Array, uid:Number = NaN, timestamp:String = null):void {
17                         var member:RelationMember;
18                         for each (member in this.members)
19                             member.entity.removeParent(this);
20
21                         updateEntityProperties(version,tags,loaded,parentsLoaded,uid,timestamp);
22                         this.members=members;
23                         for each (member in members)
24                             member.entity.addParent(this);
25                 }
26                 
27         public function get length():uint {
28             return members.length;
29         }
30
31                 public function get memberEntities():Array {
32                         var list:Array=[];
33                         for (var index:uint = 0; index < members.length; index++) {
34                                 var e:Entity=members[index].entity;
35                                 if (list.indexOf(e)==-1) list.push(e);
36                         }
37                         return list;
38                 }
39
40         public function findEntityMemberIndex(entity:Entity):int {
41             for (var index:uint = 0; index < members.length; index++) {
42                 var member:RelationMember = members[index];
43                 if ( member.entity == entity )
44                     return index;
45             }
46             return -1;
47         }
48
49         public function findEntityMemberIndexes(entity:Entity):Array {
50             var indexes:Array = [];
51             for (var index:uint = 0; index < members.length; index++) {
52                 var member:RelationMember = members[index];
53                 if ( member.entity == entity )
54                     indexes.push(index);
55             }
56             return indexes;
57         }
58         
59         public function getMember(index:uint):RelationMember {
60             return members[index];
61         }
62
63                 public function getFirstMember():RelationMember {
64                         return members[0];
65                 }
66
67                 public function getLastMember():RelationMember {
68                         return members[members.length-1];
69                 }
70
71         public function setMember(index:uint, member:RelationMember, performAction:Function):void {
72             var composite:CompositeUndoableAction = new CompositeUndoableAction("Set Member at index "+index);
73             composite.push(new RemoveMemberByIndexAction(this, members, index));
74             composite.push(new AddMemberToRelationAction(this, index, member, members));
75             performAction(composite);
76         }
77
78                 public function findMembersByRole(role:String, entityType:Class=null):Array {
79                         var a:Array=[];
80             for (var index:uint = 0; index < members.length; index++) {
81                 if (members[index].role==role && (!entityType || members[index].entity is entityType)) { a.push(members[index].entity); }
82             }
83                         return a;
84                 }
85
86                 /** Is there an entity member in this specific role. (role=null for any role) */
87                 public function hasMemberInRole(entity:Entity,role:String=null):Boolean {
88             for (var index:uint = 0; index < members.length; index++) {
89                                 if (members[index].entity == entity &&
90                                     (members[index].role==role || role == null)) { return true; }
91                         }
92                         return false;
93                 }
94                 
95         public function insertMember(index:uint, member:RelationMember, performAction:Function):void {
96             performAction(new AddMemberToRelationAction(this, index, member, members));
97         }
98
99         public function appendMember(member:RelationMember, performAction:Function):uint {
100             performAction(new AddMemberToRelationAction(this, -1, member, members));
101             return members.length + 1;
102         }
103
104                 public function removeMember(entity:Entity, performAction:Function):void {
105                         if (length>1) {
106                                 performAction(new RemoveEntityFromRelationAction(this, entity, members));
107                         } else {
108                                 performAction(new DeleteRelationAction(this, setDeletedState, members));
109                         }
110                 }
111
112         public function removeMemberByIndex(index:uint, performAction:Function):void {
113                         if (length>1) {
114                                 performAction(new RemoveMemberByIndexAction(this, members, index));
115                         } else {
116                                 performAction(new DeleteRelationAction(this, setDeletedState, members));
117                         }
118         }
119
120                 public override function remove(performAction:Function):void {
121                         performAction(new DeleteRelationAction(this, setDeletedState, members));
122                 }
123
124                 public override function nullify():void {
125                         nullifyEntity();
126                         members=[];
127                 }
128                 
129                 internal override function isEmpty():Boolean {
130                         return (deleted || (members.length==0));
131                 }
132
133                 public override function getDescription():String {
134                         var desc:String = "";
135                         var relTags:Object = getTagsHash();
136                         var named:Boolean = false;
137                         if ( relTags["type"] ) {
138                                 // type=route                           --> "route"
139                                 desc = relTags["type"];
140                                 // type=route, route=bicycle--> "route bicycle"
141                                 if (relTags[desc]) { desc += " " + relTags[desc]; }
142                         }
143                         // type=route, route=bicycle, network=ncn, ref=54 -> "route bicycle ncn 54"
144                         if ( relTags["network"]) { desc += " " + relTags["network"]; }
145                         if ( relTags["ref"]    ) { desc += " " + relTags["ref"];  named=true; }
146                         if ( relTags["name"]   ) { desc += " " + relTags["name"]; named=true; }
147                         // handle node->node routes
148                         if ( !named && relTags["type"] && relTags["type"]=="route" ) {
149                                 var firstName:String=getSignificantName(getFirstMember().entity);
150                                 var lastName:String=getSignificantName(getLastMember().entity);
151                                 if ((firstName+lastName)!='') desc+=" "+firstName+"-"+lastName;
152                         }
153                         return desc;
154                 }
155                 
156                 public function getRelationType():String {
157                         var relTags:Object = getTagsHash();
158                         return relTags["type"] ? relTags["type"] : getType();
159                 }
160                 
161                 private function getSignificantName(entity:Entity):String {
162                         if (!entity.loaded || (entity is Relation)) return '';
163
164                         var t:String;
165                         if (entity is Way) {
166                                 t=getSignificantName(Way(entity).getFirstNode());
167                                 if (t=='') t=getSignificantName(Way(entity).getLastNode());
168                                 return t;
169                         }
170                         t=Node(entity).getTag('name');
171                         if (!t) t=Node(entity).getTagByRegex(/ref$/);
172                         return t ? t : '';
173                 }
174
175                 public override function getType():String {
176                         return 'relation';
177                 }
178                 
179                 public override function toString():String {
180             return "Relation("+id+"@"+version+"): "+members.length+" members "+getTagList();
181         }
182
183     }
184
185 }