1 package net.systemeD.halcyon.connection {
5 import flash.system.Security;
7 import org.iotashan.oauth.*;
10 public class XMLConnection extends Connection {
12 //public var readConnection:NetConnection;
14 public function XMLConnection() {
16 if (Connection.policyURL!='')
17 Security.loadPolicyFile(Connection.policyURL);
18 var oauthPolicy:String = Connection.getParam("oauth_policy", "");
19 if ( oauthPolicy != "" ) {
21 Security.loadPolicyFile(oauthPolicy);
25 override public function loadBbox(left:Number,right:Number,
26 top:Number,bottom:Number):void {
27 var mapVars:URLVariables = new URLVariables();
28 mapVars.bbox= left+","+bottom+","+right+","+top;
30 var mapRequest:URLRequest = new URLRequest(Connection.apiBaseURL+"map");
31 mapRequest.data = mapVars;
33 var mapLoader:URLLoader = new URLLoader();
34 mapLoader.addEventListener(Event.COMPLETE, loadedMap);
35 mapLoader.load(mapRequest);
36 dispatchEvent(new Event(LOAD_STARTED));
39 private function parseTags(tagElements:XMLList):Object {
41 for each (var tagEl:XML in tagElements)
42 tags[tagEl.@k] = tagEl.@v;
46 private function loadedMap(event:Event):void {
47 dispatchEvent(new Event(LOAD_COMPLETED));
49 var map:XML = new XML(URLLoader(event.target).data);
54 for each(var nodeData:XML in map.node) {
55 id = Number(nodeData.@id);
56 version = uint(nodeData.@version);
58 var node:Node = getNode(id);
60 var lat:Number = Number(nodeData.@lat);
61 var lon:Number = Number(nodeData.@lon);
62 tags = parseTags(nodeData.tag);
63 setNode(new Node(id, version, tags, true, lat, lon));
67 for each(var data:XML in map.way) {
68 id = Number(data.@id);
69 version = uint(data.@version);
71 var way:Way = getWay(id);
74 for each(var nd:XML in data.nd)
75 nodes.push(getNode(Number(nd.@ref)));
76 tags = parseTags(data.tag);
77 setWay(new Way(id, version, tags,true, nodes));
84 protected function registerPOINodes():void {
85 for each (var nodeID:Number in getAllNodeIDs()) {
86 var node:Node = getNode(nodeID);
87 if ( node.parentWays.length == 0 )
92 protected var appID:OAuthConsumer;
93 protected var authToken:OAuthToken;
95 override public function setAppID(id:Object):void {
96 appID = OAuthConsumer(id);
99 override public function setAuthToken(id:Object):void {
100 authToken = OAuthToken(id);
103 private var httpStatus:int = 0;
105 private function recordStatus(event:HTTPStatusEvent):void {
106 httpStatus = event.status;
109 private var lastUploadedChangesetTags:Object;
111 override public function createChangeset(tags:Object):void {
112 lastUploadedChangesetTags = tags;
114 var changesetXML:XML = <osm version="0.6"><changeset /></osm>;
115 var changeset:XML = <changeset />;
116 for (var tagKey:Object in tags) {
117 var tagXML:XML = <tag/>;
119 tagXML.@v = tags[tagKey];
120 changesetXML.changeset.appendChild(tagXML);
123 // make an OAuth query
124 var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1();
125 var url:String = Connection.apiBaseURL+"changeset/create";
126 //var params:Object = { _method: "PUT" };
127 var oauthRequest:OAuthRequest = new OAuthRequest("PUT", url, null, appID, authToken);
128 var urlStr:Object = oauthRequest.buildRequest(sig, OAuthRequest.RESULT_TYPE_URL_STRING)
130 // build the actual request
131 var urlReq:URLRequest = new URLRequest(String(urlStr));
132 urlReq.method = "POST";
133 urlReq.data = changesetXML.toXMLString();
134 urlReq.contentType = "application/xml";
135 urlReq.requestHeaders = new Array(new URLRequestHeader("X_HTTP_METHOD_OVERRIDE", "PUT"));
136 var loader:URLLoader = new URLLoader();
137 loader.addEventListener(Event.COMPLETE, changesetCreateComplete);
138 loader.addEventListener(IOErrorEvent.IO_ERROR, changesetCreateError);
139 loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, recordStatus);
143 private function changesetCreateComplete(event:Event):void {
144 // response should be a Number changeset id
145 var id:Number = Number(URLLoader(event.target).data);
147 // which means we now have a new changeset!
148 setActiveChangeset(new Changeset(id, lastUploadedChangesetTags));
151 private function changesetCreateError(event:IOErrorEvent):void {
152 dispatchEvent(new Event(NEW_CHANGESET_ERROR));
155 override public function uploadChanges():void {
156 var changeset:Changeset = getActiveChangeset();
157 var upload:XML = <osmChange version="0.6"/>
158 upload.appendChild(addCreated(changeset, getAllNodeIDs, getNode, serialiseNode));
159 upload.appendChild(addCreated(changeset, getAllWayIDs, getWay, serialiseWay));
160 upload.appendChild(addCreated(changeset, getAllRelationIDs, getRelation, serialiseRelation));
161 upload.appendChild(addModified(changeset, getAllNodeIDs, getNode, serialiseNode));
162 upload.appendChild(addModified(changeset, getAllWayIDs, getWay, serialiseWay));
163 upload.appendChild(addModified(changeset, getAllRelationIDs, getRelation, serialiseRelation));
165 // *** TODO *** deleting items
167 // now actually upload them
168 // make an OAuth query
169 var sig:IOAuthSignatureMethod = new OAuthSignatureMethod_HMAC_SHA1();
170 var url:String = Connection.apiBaseURL+"changeset/" + changeset.id + "/upload";
171 var oauthRequest:OAuthRequest = new OAuthRequest("POST", url, null, appID, authToken);
172 var urlStr:Object = oauthRequest.buildRequest(sig, OAuthRequest.RESULT_TYPE_URL_STRING)
174 // build the actual request
175 var urlReq:URLRequest = new URLRequest(String(urlStr));
176 urlReq.method = "POST";
177 urlReq.data = upload.toXMLString();
178 urlReq.contentType = "text/xml";
179 var loader:URLLoader = new URLLoader();
180 loader.addEventListener(Event.COMPLETE, diffUploadComplete);
181 loader.addEventListener(IOErrorEvent.IO_ERROR, diffUploadError);
182 loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, recordStatus);
185 dispatchEvent(new Event(SAVE_STARTED));
188 private function diffUploadComplete(event:Event):void {
189 // response should be XML describing the progress
190 var results:XML = new XML((URLLoader(event.target).data));
192 for each( var update:XML in results.child("*") ) {
193 var oldID:Number = Number(update.@old_id);
194 var newID:Number = Number(update.@new_id);
195 var version:uint = uint(update.@new_version);
196 var type:String = update.name();
199 if ( type == "node" ) entity = getNode(oldID);
200 else if ( type == "way" ) entity = getWay(oldID);
201 else if ( type == "relation" ) entity = getRelation(oldID);
202 entity.markClean(newID, version);
204 if ( oldID != newID ) {
205 if ( type == "node" ) renumberNode(oldID, entity as Node);
206 else if ( type == "way" ) renumberWay(oldID, entity as Way);
207 else if ( type == "relation" ) renumberRelation(oldID, entity as Relation);
209 // *** TODO *** handle deleting
212 dispatchEvent(new SaveCompleteEvent(SAVE_COMPLETED, true));
215 private function diffUploadError(event:IOErrorEvent):void {
216 trace("error "+URLLoader(event.target).data + " "+httpStatus+ " " + event.text);
218 dispatchEvent(new SaveCompleteEvent(SAVE_COMPLETED, false));
221 private function addCreated(changeset:Changeset, getIDs:Function, get:Function, serialise:Function):XML {
222 var create:XML = <create version="0.6"/>
223 for each( var id:Number in getIDs() ) {
227 var entity:Object = get(id);
228 var xml:XML = serialise(entity);
229 xml.@changeset = changeset.id;
230 create.appendChild(xml);
232 return create.hasComplexContent() ? create : <!-- blank create section -->;
235 private function addModified(changeset:Changeset, getIDs:Function, get:Function, serialise:Function):XML {
236 var modify:XML = <modify version="0.6"/>
237 for each( var id:Number in getIDs() ) {
238 var entity:Entity = get(id);
239 // creates are already included
240 if ( id < 0 || !entity.isDirty )
243 var xml:XML = serialise(entity);
244 xml.@changeset = changeset.id;
245 modify.appendChild(xml);
247 return modify.hasComplexContent() ? modify : <!-- blank modify section -->;
250 private function serialiseNode(node:Node):XML {
251 var xml:XML = <node/>
252 serialiseEntity(node, xml);
258 private function serialiseWay(way:Way):XML {
260 serialiseEntity(way, xml);
261 for ( var i:uint = 0; i < way.length; i++ ) {
263 nd.@ref = way.getNode(i).id;
269 private function serialiseRelation(relation:Relation):XML {
270 var xml:XML = <relation/>
271 serialiseEntity(relation, xml);
272 for ( var i:uint = 0; i < relation.length; i++ ) {
273 var relMember:RelationMember = relation.getMember(i);
274 var member:XML = <member/>
275 member.@ref = relMember.entity.id;
276 member.@type = relMember.entity.getType();
277 member.@role = relMember.role;
278 xml.appendChild(member);
283 private function serialiseEntity(entity:Entity, xml:XML):void {
285 xml.@version = entity.version;
286 for each( var tag:Tag in entity.getTagArray() ) {
287 var tagXML:XML = <tag/>
289 tagXML.@v = tag.value;
290 xml.appendChild(tagXML);