Merge remote branch 'gravitystorm/relationrevert'
[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() {
19                 }
20                 
21         protected function loadedMap(event:Event):void {
22             var map:XML = new XML(URLLoader(event.target).data);
23             
24                         if (map.localName=="osmError") {
25                 dispatchEvent(new MapEvent(MapEvent.ERROR, { message: "Couldn't load the map: " + map.message } ));
26                         } else {
27                 var id:Number;
28                 var version:uint;
29                 var uid:Number;
30                 var timestamp:String;
31                 var tags:Object;
32                 var node:Node, newNode:Node;
33                 var unusedNodes:Object={};
34
35                         var minlon:Number, maxlon:Number, minlat:Number, maxlat:Number;
36                         var singleEntityRequest:Boolean=true;
37                         if (map.bounds.@minlon.length()) {
38                                 minlon=map.bounds.@minlon;
39                                 maxlon=map.bounds.@maxlon;
40                                 minlat=map.bounds.@minlat;
41                                 maxlat=map.bounds.@maxlat;
42                                 singleEntityRequest=false;
43                         }
44
45                 for each(var relData:XML in map.relation) {
46                     id = Number(relData.@id);
47                     version = uint(relData.@version);
48                     uid = Number(relData.@uid);
49                     timestamp = relData.@timestamp;
50                 
51                     var rel:Relation = getRelation(id);
52                     if ( rel == null || !rel.loaded || singleEntityRequest ) {
53                         tags = parseTags(relData.tag);
54                         var members:Array = [];
55                         for each(var memberXML:XML in relData.member) {
56                             var type:String = memberXML.@type.toLowerCase();
57                             var role:String = memberXML.@role;
58                             var memberID:Number = Number(memberXML.@ref);
59                             var member:Entity = null;
60                             if ( type == "node" ) {
61                                 member = getNode(memberID);
62                                 if ( member == null ) {
63                                     member = new Node(memberID,0,{},false,0,0);
64                                     setNode(Node(member),true);
65                                 } else if (member.isDeleted()) {
66                                     member.setDeletedState(false);
67                                 }
68                             } else if ( type == "way" ) {
69                                 member = getWay(memberID);
70                                 if (member == null) {
71                                     member = new Way(memberID,0,{},false,[]);
72                                     setWay(Way(member),true);
73                                 }
74                             } else if ( type == "relation" ) {
75                                 member = getRelation(memberID);
76                                 if (member == null) {
77                                     member = new Relation(memberID,0,{},false,[]);
78                                     setRelation(Relation(member),true);
79                                 }
80                             }
81                         
82                             if ( member != null )
83                                 members.push(new RelationMember(member, role));
84                         }
85                     
86                         if ( rel == null )
87                             setRelation(new Relation(id, version, tags, true, members, uid, timestamp), false);
88                         else {
89                             rel.update(version, tags, true, false, members, uid, timestamp);
90                             sendEvent(new EntityEvent(NEW_RELATION, rel), false);
91                         }
92                     }
93                 }
94
95                 for each(var nodeData:XML in map.node) {
96                                 id = Number(nodeData.@id);
97                                 node = getNode(id);
98                                 newNode = new Node(id, 
99                                                    uint(nodeData.@version), 
100                                                    parseTags(nodeData.tag),
101                                                    true, 
102                                                    Number(nodeData.@lat),
103                                                    Number(nodeData.@lon),
104                                                    Number(nodeData.@uid),
105                                                    nodeData.@timestamp);
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                                 } else {
115                                         // the node's already in memory, but store it in case one of the new ways needs it
116                                         if (newNode.within(minlon,maxlon,minlat,maxlat)) newNode.parentsLoaded=true;
117                                         unusedNodes[id]=newNode;
118                                 }
119                         }
120             
121                 for each(var data:XML in map.way) {
122                     id = Number(data.@id);
123                     version = uint(data.@version);
124                     uid = Number(data.@uid);
125                     timestamp = data.@timestamp;
126
127                     var way:Way = getWay(id);
128                     if ( way == null || !way.loaded || singleEntityRequest) {
129                         var nodes:Array = [];
130                         for each(var nd:XML in data.nd) {
131                                                 var nodeid:Number=Number(nd.@ref)
132                                                 if (getNode(nodeid).isDeleted() && unusedNodes[nodeid]) { 
133                                                         setOrUpdateNode(unusedNodes[nodeid], true); 
134                                                 }
135                             nodes.push(getNode(nodeid));
136                                         }
137                         tags = parseTags(data.tag);
138                         if ( way == null ) {
139                             setWay(new Way(id, version, tags, true, nodes, uid, timestamp),false);
140                         } else {
141                                                 waycount++;
142                             way.update(version, tags, true, true, nodes, uid, timestamp);
143                             sendEvent(new EntityEvent(NEW_WAY, way), false);
144                         }
145                     }
146                 }
147             
148                 markBboxLoaded(minlon,maxlon,maxlat,minlat);
149                 registerPOINodes();
150             }
151
152             dispatchEvent(new Event(LOAD_COMPLETED));
153         }
154         
155         protected function registerPOINodes():void {
156             for each (var nodeID:Number in getAllNodeIDs()) {
157                 var node:Node = getNode(nodeID);
158                 if (!node.hasParentWays)
159                     registerPOI(node);
160             }
161         }
162
163         private function parseTags(tagElements:XMLList):Object {
164             var tags:Object = {};
165             for each (var tagEl:XML in tagElements)
166                 tags[tagEl.@k] = tagEl.@v;
167             return tags;
168         }
169
170         }
171 }