1 package net.systemeD.halcyon.connection {
5 import flash.events.EventDispatcher;
6 import flash.events.Event;
7 import net.systemeD.halcyon.Globals;
8 import net.systemeD.halcyon.connection.actions.*;
10 public class Connection extends EventDispatcher {
12 private static var connectionInstance:Connection = null;
14 protected static var policyURL:String;
15 protected static var apiBaseURL:String;
16 protected static var params:Object;
18 public static function getConnection(initparams:Object=null):Connection {
19 if ( connectionInstance == null ) {
21 params = initparams == null ? new Object() : initparams;
22 policyURL = getParam("policy", "http://127.0.0.1:3000/api/crossdomain.xml");
23 apiBaseURL = getParam("api", "http://127.0.0.1:3000/api/0.6/");
24 var connectType:String = getParam("connection", "XML");
26 if ( connectType == "XML" )
27 connectionInstance = new XMLConnection();
28 else if ( connectType == "OSM" )
29 connectionInstance = new OSMConnection();
31 connectionInstance = new AMFConnection();
33 return connectionInstance;
36 public static function getParam(name:String, defaultValue:String):String {
37 trace("Returning param "+name+" as "+(params[name] == null ? defaultValue : params[name]));
38 return params[name] == null ? defaultValue : params[name];
41 public static function get apiBase():String {
45 public static function get serverName():String {
46 return getParam("serverName", "Localhost");
49 public static function getConnectionInstance():Connection {
50 return connectionInstance;
53 public function getEnvironment(responder:Responder):void {}
56 public static var LOAD_STARTED:String = "load_started";
57 public static var LOAD_COMPLETED:String = "load_completed";
58 public static var SAVE_STARTED:String = "save_started";
59 public static var SAVE_COMPLETED:String = "save_completed";
60 public static var NEW_CHANGESET:String = "new_changeset";
61 public static var NEW_CHANGESET_ERROR:String = "new_changeset_error";
62 public static var NEW_NODE:String = "new_node";
63 public static var NEW_WAY:String = "new_way";
64 public static var NEW_RELATION:String = "new_relation";
65 public static var NEW_POI:String = "new_poi";
66 public static var NODE_RENUMBERED:String = "node_renumbered";
67 public static var WAY_RENUMBERED:String = "way_renumbered";
68 public static var RELATION_RENUMBERED:String = "relation_renumbered";
69 public static var TAG_CHANGED:String = "tag_change";
70 public static var NODE_MOVED:String = "node_moved";
71 public static var WAY_NODE_ADDED:String = "way_node_added";
72 public static var WAY_NODE_REMOVED:String = "way_node_removed";
73 public static var WAY_REORDERED:String = "way_reordered";
74 public static var WAY_DRAGGED:String = "way_dragged";
75 public static var NODE_DELETED:String = "node_deleted";
76 public static var WAY_DELETED:String = "way_deleted";
77 public static var RELATION_DELETED:String = "relation_deleted";
78 public static var RELATION_MEMBER_ADDED:String = "relation_member_added";
79 public static var RELATION_MEMBER_REMOVED:String = "relation_member_deleted";
80 public static var ADDED_TO_RELATION:String = "added_to_relation";
81 public static var REMOVED_FROM_RELATION:String = "removed_from_relation";
82 public static var SUSPEND_REDRAW:String = "suspend_redraw";
83 public static var RESUME_REDRAW:String = "resume_redraw";
85 // store the data we download
86 private var negativeID:Number = -1;
87 private var nodes:Object = {};
88 private var ways:Object = {};
89 private var relations:Object = {};
90 private var pois:Array = [];
91 private var changeset:Changeset = null;
92 public var nodecount:int=0;
93 public var waycount:int=0;
94 public var relationcount:int=0;
96 protected function get nextNegative():Number {
100 protected function setNode(node:Node, queue:Boolean):void {
101 if (!nodes[node.id]) { nodecount++; }
102 nodes[node.id] = node;
103 if (node.loaded) { sendEvent(new EntityEvent(NEW_NODE, node),queue); }
106 protected function setWay(way:Way, queue:Boolean):void {
107 if (!ways[way.id]) { waycount++; }
109 if (way.loaded) { sendEvent(new EntityEvent(NEW_WAY, way),queue); }
112 protected function setRelation(relation:Relation, queue:Boolean):void {
113 if (!relations[relation.id]) { relationcount++; }
114 relations[relation.id] = relation;
115 if (relation.loaded) { sendEvent(new EntityEvent(NEW_RELATION, relation),queue); }
118 protected function renumberNode(oldID:Number, node:Node, queue:Boolean):void {
119 nodes[node.id] = node;
120 if (node.loaded) { sendEvent(new EntityRenumberedEvent(NODE_RENUMBERED, node, oldID),queue); }
124 protected function renumberWay(oldID:Number, way:Way, queue:Boolean):void {
126 if (way.loaded) { sendEvent(new EntityRenumberedEvent(WAY_RENUMBERED, way, oldID),queue); }
130 protected function renumberRelation(oldID:Number, relation:Relation, queue:Boolean):void {
131 relations[relation.id] = relation;
132 if (relation.loaded) { sendEvent(new EntityRenumberedEvent(RELATION_RENUMBERED, relation, oldID),queue); }
133 delete relations[oldID];
137 public function sendEvent(e:*,queue:Boolean):void {
138 // queue is only used for AMFConnection
142 public function registerPOI(node:Node):void {
143 if ( pois.indexOf(node) < 0 ) {
145 sendEvent(new EntityEvent(NEW_POI, node),false);
149 public function unregisterPOI(node:Node):void {
150 var index:uint = pois.indexOf(node);
152 pois.splice(index,1);
156 protected function setActiveChangeset(changeset:Changeset):void {
157 this.changeset = changeset;
158 sendEvent(new EntityEvent(NEW_CHANGESET, changeset),false);
161 public function getNode(id:Number):Node {
165 public function getWay(id:Number):Way {
169 public function getRelation(id:Number):Relation {
170 return relations[id];
173 // Remove data from Connection
174 // These functions are used only internally to stop redundant data hanging around
175 // (either because it's been deleted on the server, or because we have panned away
176 // and need to reduce memory usage)
178 protected function killNode(id:Number):void {
179 if (!nodes[id]) return;
180 nodes[id].dispatchEvent(new EntityEvent(Connection.NODE_DELETED, nodes[id]));
181 if (nodes[id].parentRelations.length>0) {
182 nodes[id]=new Node(id,0,{},false,0,0);
189 protected function killWay(id:Number):void {
190 if (!ways[id]) return;
191 ways[id].dispatchEvent(new EntityEvent(Connection.WAY_DELETED, ways[id]));
192 if (ways[id].parentRelations.length>0) {
193 ways[id]=new Way(id,0,{},false,[]);
200 protected function killRelation(id:Number):void {
201 if (!relations[id]) return;
202 relations[id].dispatchEvent(new EntityEvent(Connection.RELATION_DELETED, relations[id]));
203 if (relations[id].parentRelations.length>0) {
204 relations[id]=new Relation(id,0,{},false,[]);
206 delete relations[id];
211 protected function killWayWithNodes(id:Number):void {
212 var way:Way=ways[id];
214 for (var i:uint=0; i<way.length; i++) {
216 if (node.isDirty) { continue; }
217 if (node.parentWays.length>1) {
218 node.removeParent(way);
228 public function createNode(tags:Object, lat:Number, lon:Number, performCreate:Function):Node {
229 var node:Node = new Node(nextNegative, 0, tags, true, lat, lon);
230 performCreate(new CreateEntityAction(node, setNode));
234 public function createWay(tags:Object, nodes:Array, performCreate:Function):Way {
235 var way:Way = new Way(nextNegative, 0, tags, true, nodes.concat());
236 performCreate(new CreateEntityAction(way, setWay));
240 public function createRelation(tags:Object, members:Array, performCreate:Function):Relation {
241 var relation:Relation = new Relation(nextNegative, 0, tags, true, members.concat());
242 performCreate(new CreateEntityAction(relation, setRelation));
246 public function getAllNodeIDs():Array {
248 for each (var node:Node in nodes)
253 public function getAllWayIDs():Array {
255 for each (var way:Way in ways)
260 public function getAllRelationIDs():Array {
262 for each (var relation:Relation in relations)
263 list.push(relation.id);
267 public function getObjectsByBbox(left:Number, right:Number, top:Number, bottom:Number):Object {
268 var o:Object = { poisInside: [], poisOutside: [], waysInside: [], waysOutside: [] };
269 for each (var way:Way in ways) {
270 if (way.within(left,right,top,bottom)) { o.waysInside.push(way); }
271 else { o.waysOutside.push(way); }
273 for each (var node:Node in nodes) {
274 if (!node.hasParentWays) {
275 if (node.within(left,right,top,bottom)) { o.poisInside.push(node); }
276 else { o.poisOutside.push(node); }
282 public function getActiveChangeset():Changeset {
286 public function purgeOutside(left:Number, right:Number, top:Number, bottom:Number):void {
287 for each (var way:Way in ways) {
288 if (!way.within(left,right,top,bottom) && !way.isDirty) {
289 killWayWithNodes(way.id);
292 // ** should purge POIs and relations too
295 // these are functions that the Connection implementation is expected to
296 // provide. This class has some generic helpers for the implementation.
297 public function loadBbox(left:Number, right:Number,
298 top:Number, bottom:Number):void {
301 public function setAppID(id:Object):void {}
302 public function setAuthToken(id:Object):void {}
303 public function createChangeset(tags:Object):void {}
304 public function uploadChanges():void {}