Support inline status, where the status field is part of e.g. map calls
[potlatch2.git] / net / systemeD / halcyon / connection / XMLBaseConnection.as
1 package net.systemeD.halcyon.connection {
2
3     import flash.events.*;
4
5         import flash.system.Security;
6         import flash.net.*;
7     import org.iotashan.oauth.*;
8
9     /**
10     * XMLBaseConnection is the common code between connecting to an OSM server
11     * (i.e. XMLConnection) and connecting to a standalone .osm file (i.e. OSMConnection)
12     * and so mainly concerns itself with /map -call-ish related matters
13     */
14         public class XMLBaseConnection extends Connection {
15
16                 public function XMLBaseConnection(name:String,api:String,policy:String,initparams:Object) {
17                         super(name,api,policy,initparams);
18                 }
19                 
20         protected function loadedMap(event:Event):void {
21             var map:XML = new XML(URLLoader(event.target).data);
22             var id:Number;
23             var version:uint;
24             var uid:Number;
25             var timestamp:String;
26             var tags:Object;
27             var node:Node, newNode:Node;
28             var unusedNodes:Object={};
29                         var createdEntities:Array=[];
30
31                         var minlon:Number, maxlon:Number, minlat:Number, maxlat:Number;
32                         var singleEntityRequest:Boolean=true;
33                         if (map.bounds.@minlon.length()) {
34                                 minlon=map.bounds.@minlon;
35                                 maxlon=map.bounds.@maxlon;
36                                 minlat=map.bounds.@minlat;
37                                 maxlat=map.bounds.@maxlat;
38                                 singleEntityRequest=false;
39                         }
40
41             for each(var relData:XML in map.relation) {
42                 id = Number(relData.@id);
43                 version = uint(relData.@version);
44                 uid = Number(relData.@uid);
45                 timestamp = relData.@timestamp;
46                 
47                 var rel:Relation = getRelation(id);
48                 if ( rel == null || !rel.loaded ) {
49                     tags = parseTags(relData.tag);
50                     var members:Array = [];
51                     for each(var memberXML:XML in relData.member) {
52                         var type:String = memberXML.@type.toLowerCase();
53                         var role:String = memberXML.@role;
54                         var memberID:Number = Number(memberXML.@ref);
55                         var member:Entity = null;
56                         if ( type == "node" ) {
57                             member = getNode(memberID);
58                             if ( member == null ) {
59                                 member = new Node(this,memberID,0,{},false,0,0);
60                                 setNode(Node(member),true);
61                             } else if (member.isDeleted()) {
62                                 member.setDeletedState(false);
63                             }
64                         } else if ( type == "way" ) {
65                             member = getWay(memberID);
66                             if (member == null) {
67                                 member = new Way(this,memberID,0,{},false,[]);
68                                 setWay(Way(member),true);
69                             }
70                         } else if ( type == "relation" ) {
71                             member = getRelation(memberID);
72                             if (member == null) {
73                                 member = new Relation(this,memberID,0,{},false,[]);
74                                 setRelation(Relation(member),true);
75                             }
76                         }
77                         
78                         if ( member != null )
79                             members.push(new RelationMember(member, role));
80                     }
81                     
82                     if ( rel == null ) {
83                         rel=new Relation(this, id, version, tags, true, members, uid, timestamp);
84                         setRelation(rel, false);
85                         createdEntities.push(rel);
86                     } else {
87                         rel.update(version, tags, true, false, members, uid, timestamp);
88                         sendEvent(new EntityEvent(NEW_RELATION, rel), false);
89                     }
90                 }
91             }
92
93             for each(var nodeData:XML in map.node) {
94                                 id = Number(nodeData.@id);
95                                 node = getNode(id);
96                                 newNode = new Node(this,
97                                                    id, 
98                                                    uint(nodeData.@version), 
99                                                    parseTags(nodeData.tag),
100                                                    true, 
101                                                    Number(nodeData.@lat),
102                                                    Number(nodeData.@lon),
103                                                    Number(nodeData.@uid),
104                                                    nodeData.@timestamp);
105                 if ( inlineStatus ) { newNode.status = nodeData.@status; trace(newNode.status)}
106                                 
107                                 if ( singleEntityRequest ) {
108                                         // it's a revert request, so create/update the node
109                                         setOrUpdateNode(newNode, true);
110                                 } else if ( node == null || !node.loaded) {
111                                         // the node didn't exist before, so create/update it
112                                         newNode.parentsLoaded=newNode.within(minlon,maxlon,minlat,maxlat);
113                                         setOrUpdateNode(newNode, true);
114                                         createdEntities.push(newNode);
115                                 } else {
116                                         // the node's already in memory, but store it in case one of the new ways needs it
117                                         if (newNode.within(minlon,maxlon,minlat,maxlat)) newNode.parentsLoaded=true;
118                                         unusedNodes[id]=newNode;
119                                 }
120                         }
121             
122             for each(var data:XML in map.way) {
123                 id = Number(data.@id);
124                 version = uint(data.@version);
125                 uid = Number(data.@uid);
126                 timestamp = data.@timestamp;
127
128                 var way:Way = getWay(id);
129                 if ( way == null || !way.loaded || singleEntityRequest) {
130                     var nodelist:Array = [];
131                     for each(var nd:XML in data.nd) {
132                                                 var nodeid:Number=Number(nd.@ref)
133                                                 if (getNode(nodeid).isDeleted() && unusedNodes[nodeid]) { 
134                                                         setOrUpdateNode(unusedNodes[nodeid], true); 
135                                                 }
136                         nodelist.push(getNode(nodeid));
137                                         }
138                     tags = parseTags(data.tag);
139                     if ( way == null ) {
140                         way=new Way(this, id, version, tags, true, nodelist, uid, timestamp)
141                         if ( inlineStatus ) { way.status = data.@status; trace(way.status); }
142                         setWay(way,false);
143                         createdEntities.push(way);
144                     } else {
145                                                 waycount++;
146                         way.update(version, tags, true, true, nodelist, uid, timestamp);
147                         sendEvent(new EntityEvent(NEW_WAY, way), false);
148                     }
149                 }
150
151
152             }
153             
154             markBboxLoaded(minlon,maxlon,maxlat,minlat);
155             registerPOINodes();
156             dispatchEvent(new Event(LOAD_COMPLETED));
157
158             if (statusFetcher) statusFetcher.fetch(createdEntities); 
159         }
160         
161         protected function registerPOINodes():void {
162             for each (var nodeID:Number in getAllNodeIDs()) {
163                 var node:Node = getNode(nodeID);
164                 if (!node.hasParentWays)
165                     registerPOI(node);
166             }
167         }
168
169         private function parseTags(tagElements:XMLList):Object {
170             var tags:Object = {};
171             for each (var tagEl:XML in tagElements)
172                 tags[tagEl.@k] = tagEl.@v;
173             return tags;
174         }
175
176         }
177 }