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