change relation.appendMember to use the undo system, and update various places as...
[potlatch2.git] / net / systemeD / halcyon / connection / AMFConnection.as
1 package net.systemeD.halcyon.connection {
2
3     import flash.events.Event;
4     import flash.net.URLLoader;
5     import flash.net.URLRequest;
6
7         import flash.system.Security;
8         import flash.net.*;
9
10     /**
11     * AMFConnection provides read-write access to an AMF server. The read/write
12     * methods bear little resemblance to the standard OSM server XML API methods,
13     * but are similar (the same?) as that used by Potlatch 1.
14     * For a lightweight AMF server see resources/tinyamf.cgi
15     */
16         public class AMFConnection extends Connection {
17
18                 public var readConnection:NetConnection;
19                 public var writeConnection:NetConnection;
20                 private var mapLoader:URLLoader;
21
22                 private var eventTarget:AMFCounter;
23                 private var bboxrequests:Array=new Array();
24
25                 // ------------------------------------------------------------
26                 // Constructor for new AMFConnection
27
28                 public function AMFConnection() {
29
30                         if (Connection.policyURL!='')
31                 Security.loadPolicyFile(Connection.policyURL);
32
33                         readConnection=new NetConnection();
34                         readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
35                         readConnection.connect(Connection.apiBaseURL+"amf/read");
36                         
37                         writeConnection=new NetConnection();
38                         writeConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
39                         writeConnection.connect(Connection.apiBaseURL+"amf/write");
40                         
41                 }
42
43                 override public function getEnvironment(responder:Responder):void {
44                         readConnection.call("getpresets",responder,null,"en");
45                 }
46                 
47                 override public function loadBbox(left:Number,right:Number,
48                                                                 top:Number,bottom:Number):void {
49                         readConnection.call("whichways",new Responder(gotBbox, error),left,bottom,right,top);
50                 }
51                 
52                 override public function sendEvent(e:*,queue:Boolean):void {
53                         if (queue) { eventTarget.addEvent(e); }
54                               else { dispatchEvent(e); }
55                 }
56
57         private function gotBbox(r:Object):void {
58                         var code:uint=r.shift();
59             if (code) {
60                 error(new Array(r.shift()));
61                 return;
62             }
63
64                         var message:String    =r.shift();
65                         var waylist:Array     =r[0];
66                         var pointlist:Array   =r[1];
67                         var relationlist:Array=r[2];
68                         var id:Number, version:uint;
69                         var requests:AMFCounter=new AMFCounter(this);
70                         eventTarget=requests;
71
72                         // Load relations
73
74                         for each (var a:Array in relationlist) {
75                                 id=Number(a[0]);
76                 version=uint(a[1]);
77
78                 var relation:Relation = getRelation(id);
79                 if ( relation == null || !relation.loaded  ) {
80                     loadRelation(id);
81                                         requests.addRelationRequest(id);
82                 }
83                         }
84
85                         // Load ways
86
87                         for each (var w:Array in waylist) {
88                                 id=Number(w[0]);
89                 version=uint(w[1]);
90
91                 var way:Way = getWay(id);
92                 if ( way == null || !way.loaded ) {
93                     loadWay(id);
94                                         requests.addWayRequest(id);
95                 }
96                         }
97
98                         // Create POIs
99
100                         for each (var p:Array in pointlist) {
101                                 id = Number(p[0]);
102                 version = uint(p[4]);
103
104                 var node:Node = getNode(id);
105                 if ( node == null || !node.loaded ) {
106                     var lat:Number = Number(p[2]);
107                     var lon:Number = Number(p[1]);
108                     var tags:Object = p[3];
109                     node = new Node(id, version, tags, true, lat, lon);
110                     setNode(node,true);
111                 }
112                 registerPOI(node);
113                         }
114
115                         bboxrequests.push(requests);
116         }
117
118         private function error(r:Object):void {}
119
120                 private function loadWay(id:Number):void {
121                         readConnection.call("getway",new Responder(gotWay, error),id);
122                 }
123
124                 private function gotWay(r:Object):void {
125                         var code:uint = r.shift();
126             if (code) {
127                 error(new Array(r.shift()));
128                 return;
129             }
130
131                         var message:String=r.shift();
132             var id:Number = Number(r[0]);
133                         var version:uint = uint(r[3]);
134
135             var way:Way = getWay(id);
136             if ( way != null && way.loaded ) {
137                                 gotRequest(id+"way");
138                 return;
139                         }
140
141             var nodesAMF:Array = r[1];
142                         var tags:Object = r[2];
143                         
144             var nodes:Array = [];
145                         for each (var p:Array in nodesAMF) {
146                 var nodeID:Number = Number(p[2]);
147                 var nodeVersion:uint = uint(p[4]);
148                 var lon:Number = Number(p[0]);
149                 var lat:Number = Number(p[1]);
150
151                 var node:Node = getNode(nodeID);
152                 if ( node == null ) {
153                     var nodeTags:Object = p[3];
154                     node = new Node(nodeID, nodeVersion, nodeTags, true, lat, lon);
155                 } else if (!node.loaded) {
156                                         node.update(nodeVersion, nodeTags, true, lat, lon);
157                                 }
158                 setNode(node,true);
159                 nodes.push(node);
160                         }
161
162                         if (way==null) {
163                 way = new Way(id, version, tags, true, nodes);
164                         } else {
165                                 way.update(version, tags, true, nodes);
166                         }
167                 setWay(way,true);
168                         gotRequest(id+"way");
169                 }
170
171
172                 private function loadRelation(id:Number):void {
173                         readConnection.call("getrelation",new Responder(gotRelation, error),id);
174                 }
175
176                 private function gotRelation(r:Object):void {
177                         var code:uint = r.shift();
178             if (code) { error(new Array(r.shift())); return; }
179                         var message:String=r.shift();
180
181             var id:Number = Number(r[0]);
182                         var version:uint = uint(r[3]);
183
184             var relation:Relation = getRelation(id);
185             if ( relation != null && relation.loaded ) {
186                                 gotRequest(id+"rel");
187                                 return;
188                         }
189
190                         var tags:Object = r[1];
191             var membersAMF:Array = r[2];
192                         var members:Array = [];
193                         for each (var p:Array in membersAMF) {
194                                 var type:String=p[0];
195                                 var memid:Number=p[1];
196                                 var role:String=p[2];
197                                 var e:Entity;
198                                 switch (type) {
199                                         case 'Node':
200                                                 e=getNode(memid);
201                                                 if (e==null) { e=new Node(memid,0,{},false,0,0); setNode(Node(e),true); }
202                                                 break;
203                                         case 'Way':
204                                                 e=getWay(memid);
205                                                 if (e==null) { e=new Way(memid,0,{},false,[]); setWay(Way(e),true); }
206                                                 break;
207                                         case 'Relation':
208                                                 e=getRelation(memid);
209                                                 if (e==null) { e=new Relation(memid,0,{},false,[]); setRelation(Relation(e),true); }
210                                                 break;
211                                 }
212                                 members.push(new RelationMember(e,role));
213                         }
214                         if (relation==null) {
215                     relation = new Relation(id, version, tags, true, members);
216                         } else {
217                                 relation.update(version,tags,true,members);
218                         }
219             setRelation(relation,true);
220                         gotRequest(id+"rel");
221                 }
222                 
223                 private function gotRequest(n:String):void {
224                         for each (var c:AMFCounter in bboxrequests) {
225                                 if (c.removeRequest(n)) { break; }
226                         }
227                         while (bboxrequests.length>0 && bboxrequests[0].count==0) {
228                                 bboxrequests.shift();
229                         }
230                 }
231         }
232 }