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