package data { import events.ConfigChangeEvent; import events.LoginEvent; import flash.display.DisplayObject; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IOErrorEvent; import flash.net.URLLoader; import flash.net.URLRequest; import flash.net.URLRequestHeader; import flash.net.URLRequestMethod; import mx.binding.utils.BindingUtils; import mx.collections.XMLListCollection; import mx.controls.Alert; import mx.core.Application; import mx.events.CollectionEvent; import mx.events.PropertyChangeEvent; import mx.managers.PopUpManager; import mx.resources.IResourceManager; import mx.resources.ResourceManager; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.http.HTTPService; import panels.ServerLoginPanel; [Event(name="ready")] [Event(name="serverCacheDropped")] public class DataSource extends EventDispatcher { [Bindable] public var contextTree:XMLListCollection = new XMLListCollection(); [Bindable] public var serverTree:XMLListCollection = new XMLListCollection(); [Bindable] public var guiTree:XMLListCollection = new XMLListCollection(); [Bindable] public var defaultConfig:XML; [Bindable] public var properties:XML; [Bindable] public var resourceManager:IResourceManager = ResourceManager.getInstance(); private var serverProps:XMLListCollection = new XMLListCollection(); private var layerProps:XMLListCollection = new XMLListCollection(); private var contextProps:XMLListCollection = new XMLListCollection(); private var mapProps:XMLListCollection = new XMLListCollection(); private var queryAspectProps:XMLListCollection = new XMLListCollection(); private var templateProps:XMLListCollection = new XMLListCollection(); private var reportProps:XMLListCollection = new XMLListCollection(); private var guiConfigProps:XMLListCollection = new XMLListCollection(); private var fullPropsLoading:Object = new Object(); private var lastId:Number = 0; private var _serverUrl:String; private var _proxyServerUrl:String; private var _login:String; private var _defaultConfigUrl:String; private var _propertiesUrl:String; namespace wfs = "http://www.opengis.net/wfs"; namespace xsd = "http://www.w3.org/2001/XMLSchema"; use namespace wfs; use namespace xsd; private var entityNames:Array = ["Context", "Layer", "Map", "QueryAspect", "Report", "Server", "Template"]; private function reloadProxy():void { var proxyReload:URLLoader = new URLLoader(); proxyReload.addEventListener(Event.COMPLETE, function():void { var resp:Object = XML(proxyReload.data).localName(); }); proxyReload.load(new URLRequest(this._proxyServerUrl + "/?service=reload")); } public function logout(callback:Function):void { var logoutLoader:URLLoader = new URLLoader(); logoutLoader.addEventListener(Event.COMPLETE, function():void { callback(); }); logoutLoader.load(new URLRequest(_serverUrl + "request=Logout")); } private function createContextTree():XML { var contexts:XML = ; for(var i:int = 0; i < contextProps.length; i++) { var context:XML = XML(contextProps.getItemAt(i)); var contextRef:XML = newRef(context); contexts.appendChild(contextRef); } return contexts; } private function updateStatusAttributes(list:XMLList):void { for each(var item:XML in list) { var props:XML = getProps(item); if(props.@status != item.@status) { item.@status = props.@status; } } } private function updateContextTree():void { updateStatusAttributes(contextTree.source..Context); updateStatusAttributes(contextTree.source..Context); updateStatusAttributes(contextTree.source..Layer); updateStatusAttributes(contextTree.source..Map); updateStatusAttributes(contextTree.source..QueryAspect); updateStatusAttributes(contextTree.source..Report); updateStatusAttributes(contextTree.source..Template); } private function buildServerTree():void { var servers:XML = ; for each(var server:XML in serverProps) { servers.appendChild(newRef(server)); } serverTree.removeAll(); serverTree.addItem(servers); } private function buildContextTree():void { contextTree.removeAll(); contextTree.addItem(createContextTree()); } private function buildGUIDataSource():void{ var newConfigList:XMLList = new XMLList(); for each(var config:XML in guiConfigProps) { newConfigList += refactorGuiConfig(config); } guiConfigProps.source = newConfigList; buildConfigTree(); } public function buildConfigTree():void{ var tree:XML = ; for each(var config:XML in guiConfigProps) { tree.appendChild(deleteConfigTagsToHide(config.copy())); } var treeList:XMLList = XMLList(tree); guiTree.source = treeList; guiTree.source = treeList; } private function refactorGuiConfig(guiConfig:XML):XML{ var newConfig:XML = new XML(defaultConfig); newConfig.@name = guiConfig.@name; newConfig.Description = guiConfig.Description; var colorNodes:XMLList = newConfig.Colors.children(); for(var i:Number=0;i 0){ colorNodes[i] = guiConfig.Colors.child(colorName)[0]; } } newConfig.ButtonBars = guiConfig.ButtonBars; var buttonsOnBars:XMLList = newConfig.ButtonBars.ButtonBar.Buttons.children(); var buttonNodes:XMLList = newConfig.ActionButtons.children(); buttonNodes += newConfig.PaneButtons.children(); buttonNodes += newConfig.MapViewerButtons.children(); for each(var buttonNode:XML in buttonNodes){ buttonNode.@used="false"; for each (var buttonOnBar:XML in buttonsOnBars){ if(buttonOnBar.@name==buttonNode.Name){ buttonOnBar.@datatip = buttonNode.ToolTipText.child(String(resourceManager.localeChain[0]).substr(0, 2))[0]; } } } var orgButtonNodes:XMLList = guiConfig.ActionButtons.children(); orgButtonNodes += guiConfig.PaneButtons.children(); orgButtonNodes += guiConfig.MapViewerButtons.children(); for(var j:Number=0;j 0) { return props.Owner == _login; } return false; } private function isClientId(item:XML):Boolean { return item.child("@clientId").length() > 0 && item.@clientId; } public function duplicateItem(item:XML, parentNode:XML):void { item = getProps(item).copy(); while(!isUnique(item.localName(), item.Name, true)) { item.Name += "_copy"; } item.@clientId = true; item.@status = "new"; item.@id = lastId++; item.Owner = _login; addItem(item, parentNode); } public function newRef(item:XML, subRef:Boolean = true):XML { var language:String = resourceManager.localeChain[0].toString().substr(0, 2); item = getProps(item); var localName:String = item.localName(); var itemRef:XML = <{localName}/>; itemRef.@status = item.@status; itemRef.@id = item.@id; itemRef.@clientId = item.@clientId; if(subRef) { switch(localName) { case "Map": var layersNode:XML = ; for each(var currentLayer:XML in item.Layers.Layer) { var layerRef:XML = newRef(currentLayer); layerRef.@status = currentLayer.@status; layersNode.appendChild(layerRef); } itemRef.appendChild(layersNode); var queryAspectsNode:XML = ; var queryAspectsCollection:XMLListCollection = new XMLListCollection(item.QueryAspects.QueryAspect); /*var queryAspectsSort:Sort = new Sort(); var queryAspectsField:SortField = new SortField(); var defaultCompareFunction:Function = queryAspectsField.compareFunction; queryAspectsField.compareFunction = function(a:Object, b:Object):int { return defaultCompareFunction(getProps(XML(a)).Titles.Title.(Language == language).Title, getProps(XML(b)).Titles.Title.(Language == language).Title); } queryAspectsSort.fields = [queryAspectsField]; queryAspectsCollection.sort = queryAspectsSort; queryAspectsCollection.refresh();*/ for each(var currentQueryAspect:XML in queryAspectsCollection) { var queryAspectRef:XML = newRef(currentQueryAspect); // Use the same status as the reference in the entity (for deleted references) queryAspectRef.@status = currentQueryAspect.@status; queryAspectsNode.appendChild(queryAspectRef); } itemRef.appendChild(queryAspectsNode); var templatesNode:XML = ; for each(var currentTemplate:XML in item.Templates.Template) { var templateRef:XML = newRef(currentTemplate); templateRef.@status = currentTemplate.@status; templatesNode.appendChild(templateRef); } itemRef.appendChild(templatesNode); var reports:XML = ; for each(var report:XML in reportProps) { if(report.Map_id == item.@id && report.Map_id.@clientId == item.@clientId) { var reportRef:XML = newRef(report); reportRef.@status = report.@status; reports.appendChild(reportRef); } } itemRef.appendChild(reports); break; case "Context": var maps:XML = ; var mapsCollection:XMLlistCollection = new XMLListCollection(item.Maps.Map); /*var mapsSort:Sort = new Sort(); var mapsField:SortField = new SortField(); defaultCompareFunction = mapsField.compareFunction; mapsField.compareFunction = function(a:Object, b:Object):int { return defaultCompareFunction(getProps(XML(a)).Titles.Title.(Language == language).Title, getProps(XML(b)).Titles.Title.(Language == language).Title); } mapsSort.fields = [mapsField]; mapsCollection.sort = mapsSort; mapsCollection.refresh();*/ for each(var map:XML in mapsCollection) { var mapRef:XML = newRef(map); mapRef.@status = map.@status; maps.appendChild(mapRef); } itemRef.appendChild(maps); break; case "Layer": var layerProps:XML = getProps(item); if(layerProps.Type == "Group") { for each(var subLayer:XML in layerProps.Layers.Layer) { var subLayerRef:XML = newRef(subLayer); // Use the same status as the reference in the entity (for deleted references) subLayerRef.@status = subLayer.@status; itemRef.appendChild(subLayerRef); } } break; } } return itemRef; } public function newLayer():XML { var newItem:XML = Layer <Language>en</Language> <Title> <Language>nl</Language> <Title> <Language>de</Language> <Title> ; newItem.@id = lastId++; newItem.Owner = _login; //newItem.Server.@id = serverProps.source.Server[0].@id; return newItem; } public function newGroupLayer():XML { var newItem:XML = Group <Language>en</Language> <Title> <Language>nl</Language> <Title> <Language>de</Language> <Title> ; newItem.@id = lastId++; newItem.Owner = _login; return newItem; } public function newMap():XML { var newItem:XML = <Language>en</Language> <Title> <Language>nl</Language> <Title> <Language>de</Language> <Title> ; newItem.@id = lastId++; newItem.Owner = _login; return newItem; } public function newServer():XML { var newItem:XML = ; newItem.@id = lastId++; newItem.Owner = _login; return newItem; } public function newQueryAspect():XML { var newItem:XML = <Language>en</Language> <Title> <Language>nl</Language> <Title> <Language>de</Language> <Title> ; newItem.@id = lastId++; newItem.Owner = _login; return newItem; } public function newTemplate():XML { var newItem:XML = ; newItem.@id = lastId++; newItem.Owner = _login; return newItem; } public function newReport(map:XML):XML { var newItem:XML = <Language>en</Language> <Title> <Language>nl</Language> <Title> <Language>de</Language> <Title> {map.@id} newItem.@id = lastId++; return newItem; } public function newContext():XML { var newItem:XML = newItem.@id = lastId++; newItem.Owner = _login; return newItem; } public function newButtonBar(buttonBars:XML):XML { var newItem:XML = New ButtonBar True 27 return newItem; } public function newConfig(configs:XML):XML { var newItem:XML = new XML(this.defaultConfig); newItem.@name = ''; newItem.@id = lastId++; newItem.@status = 'new'; newItem.@clientId = 'true'; newItem.Description = ''; return newItem; } private function getParentEntity(parentNode:XML):XML { if(parentNode == null) { return null; } while(entityNames.indexOf(parentNode.localName()) == -1) { parentNode = parentNode.parent(); if(parentNode == null) { return null; } } return getProps(parentNode); } public function addRef(item:XML, parentNode:XML):void { if(item.localName() == "Context" || item.localName() == "Server") { parentNode = null; getProps(item).@status = "deleted"; } else { parentNode = getParentEntity(parentNode); } if(parentNode != null) { XML(parentNode.child(item.localName() + "s")[0]).appendChild(newRef(item, false)); } } public function removeRef(item:XML, parentNode:XML):void { if(item.localName() == "Context" || item.localName() == "Server") { parentNode = null; getProps(item).@status = "deleted"; } else { parentNode = getParentEntity(parentNode); } if(parentNode != null) { var items:XMLList = parentNode.descendants(item.localName()); for each(var currentItem:XML in items) { if(currentItem.@id == item.@id && currentItem.@clientId == item.@clientId) { currentItem.@status = "deleted"; } } } } public function addItem(newItem:XML, parentNode:XML):void { switch(newItem.localName()) { case 'Geoide_Client_Config': parentNode.appendChild(deleteConfigTagsToHide(newItem.copy())); guiConfigProps.addItem(newItem); return; case 'ButtonBar': getProps(parentNode.parent()).ButtonBars.appendChild(newItem); parentNode.appendChild(newItem); return; } if(newItem.localName() == "Context") { parentNode = null; } else { parentNode = getParentEntity(parentNode); } switch(newItem.localName()) { case 'Layer': layerProps.addItem(newItem); parentNode.Layers.Layer += newRef(newItem, false); break; case 'Map': mapProps.addItem(newItem); parentNode.Maps.Map += newRef(newItem, false); break; case 'Server': serverProps.addItem(newItem); break; case 'Context': contextProps.addItem(newItem); break; case 'QueryAspect': queryAspectProps.addItem(newItem); parentNode.QueryAspects.QueryAspect += newRef(newItem, false); break; case 'Template': templateProps.addItem(newItem); parentNode.Templates.Template += newRef(newItem, false); break; case 'Report': reportProps.addItem(newItem); parentNode.Reports.Report += newRef(newItem, false); } } private function replaceClientId(clientId:Number, serverId:Number, items:XMLList, recursive:Boolean = true):void { var newItems:XMLList = items.(@status == "new").(@id == clientId); for each(var item:XML in newItems) { delete item.@clientId; item.@id = serverId; item.@status = "existing"; } if(recursive) { for each(item in items) { replaceClientId(clientId, serverId, item.children()); } } } private function setLayerId(list:XMLList, clientId:String, serverId:String):void { for each(var layerRef:XML in list..Layer. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { layerRef.@id = serverId; delete layerRef.@clientId; layerRef.@status = "existing"; } } private function setMapId(list:XMLList, clientId:String, serverId:String):void { for each(var mapRef:XML in list..Map. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { mapRef.@id = serverId; delete mapRef.@clientId; mapRef.@status = "existing"; } } private function setContextId(list:XMLList, clientId:String, serverId:String):void { for each(var contextRef:XML in list..Context. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { contextRef.@id = serverId; delete contextRef.@clientId; contextRef.@status = "existing"; } } private function setTemplateId(list:XMLList, clientId:String, templateId:String):void { for each(var templateRef:XML in list..Template. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { templateRef.@id = templateId; delete templateRef.@clientId; templateRef.@status = "existing"; } } private function setReportId(list:XMLList, clientId:String, reportId:String):void { for each(var reportRef:XML in list..Report. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { reportRef.@id = reportId; delete reportRef.@clientId; reportRef.@status = "existing"; } } private function setQueryAspectId(list:XMLList, clientId:String, serverId:String):void { for each(var queryAspectRef:XML in list..QueryAspect. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { queryAspectRef.@id = serverId; delete queryAspectRef.@clientId; queryAspectRef.@status = "existing"; } } private function setServerId(list:XMLList, clientId:String, serverId:String):void { for each(var server:XML in list..Server. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { server.@id = serverId; delete server.@clientId; server.@status = 'existing'; } for each(server in list..Featureserver. (attribute("clientId").length() > 0 && @clientId.toString().toLowerCase() == "true" && @id == clientId)) { server.@id = serverId; delete server.@clientId; server.@status = 'existing'; } } private var transaction:XML; public function save():void { transaction = {contextProps.source.copy().(@status == 'new')} {layerProps.source.copy().(@status == 'new')} {mapProps.source.copy().(@status == 'new')} {queryAspectProps.source.copy().(@status == 'new')} {templateProps.source.copy().(@status == 'new')} {reportProps.source.copy().(@status == 'new')} {serverProps.source.copy().(@status == 'new')} {guiConfigProps.source.copy().(@status == 'new')} {contextProps.source.copy().(@status == 'changed')} {layerProps.source.copy().(@status == 'changed')} {mapProps.source.copy().(@status == 'changed')} {queryAspectProps.source.copy().(@status == 'changed')} {templateProps.source.copy().(@status == 'changed')} {reportProps.source.copy().(@status == 'changed')} {serverProps.source.copy().(@status == 'changed')} {guiConfigProps.source.copy().(@status == 'changed')} {contextProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {layerProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {mapProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {queryAspectProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {templateProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {reportProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {serverProps.source.copy().(@status == 'deleted' && @clientId == 'false')} {guiConfigProps.source.copy().(@status == 'deleted' && @clientId == 'false')} ; var contextsUpdated:Boolean = transaction..Contexts.children().length() > 0; var guiConfigsUpdated:Boolean = transaction..Geoide_Client_Configs.children().length() > 0; var item:XML; // remove deleted references for each(item in transaction.Insert.descendants().(attribute("status").length() > 0 && @status == "deleted")) { delete transaction.Insert.descendants().(copy() == item)[0]; } for each(item in transaction.Update.descendants().(attribute("status").length() > 0 && @status == "deleted")) { delete transaction.Update.descendants().(copy() == item)[0]; } // remove status attributes for each(item in transaction.descendants()) { delete item.@status; } // Send transaction to server var doTransactionRequest:URLLoader = new URLLoader(); doTransactionRequest.addEventListener(IOErrorEvent.IO_ERROR, function():void { dispatchEvent(new Event("ioError")); }); doTransactionRequest.addEventListener(Event.COMPLETE, function(event:Event):void { var response:XML = XML(doTransactionRequest.data); if(response.localName() == "Exception") { Alert.show(response.Message.toString()); } else if(response.localName() == "TransactionResult") { // Disable listeners removeListeners(); // Update id's for each(var insertNode:XML in response.Inserted.children()) { var id:String = insertNode.@id; var clientId:String = insertNode.@clientId; var localName:String = insertNode.localName(); var list:XMLList = (serverProps.descendants(localName) + layerProps.descendants(localName) + queryAspectProps.descendants(localName) + templateProps.descendants(localName) + reportProps.descendants(localName) + mapProps.descendants(localName) + guiConfigProps.descendants(localName) + contextProps.descendants(localName)).(@clientId == "true" && @id == clientId) + getProps(<{localName} clientId="true" id={clientId}/>); for each(var item:XML in list) { item.@id = id; item.@clientId = "false"; item.@status = "existing"; } } // Reset status attributes list = (serverProps.descendants() + layerProps.descendants() + queryAspectProps.descendants() + templateProps.descendants() + reportProps.descendants() + mapProps.descendants() + contextProps.descendants() + serverProps.source + layerProps.source + queryAspectProps.source + templateProps.source + reportProps.source + mapProps.source + contextProps.source + guiConfigProps.source).(attribute("status").length() > 0 && @status == "changed"); for each(item in list) { item.@status = "existing"; } // Remove deleted entities var collections:Array = [serverProps, layerProps, queryAspectProps, templateProps, reportProps, mapProps, contextProps, guiConfigProps]; for each(var collection:XMLListCollection in collections) { for each(item in collection) { if(item.@status == "deleted") { collection.removeItemAt(collection.getItemIndex(item)); } } } // Remove deleted references for each(item in layerProps.source.descendants().(attribute("status").length() > 0 && @status == "deleted")) { delete layerProps.source.descendants().(copy() == item)[0]; } for each(item in mapProps.source.descendants().(attribute("status").length() > 0 && @status == "deleted")) { delete mapProps.source.descendants().(copy() == item)[0]; } for each(item in contextProps.source.descendants().(attribute("status").length() > 0 && @status == "deleted")) { delete contextProps.source.descendants().(copy() == item)[0]; } for each(item in guiConfigProps.source.descendants().(attribute("status").length() > 0 && @status == "deleted")) { delete guiConfigProps.source.descendants().(copy() == item)[0]; } // Rebuild trees buildContextTree(); buildServerTree(); buildConfigTree(); // Re enable listeners addListeners(); if(contextsUpdated) { var contexts:Array = new Array(); for each(item in contextProps) { contexts.push(item.Name.toString()); } Application.application.dispatchEvent(new ConfigChangeEvent(ConfigChangeEvent.CONTEXTS_CHANGE, contexts)); } if(guiConfigsUpdated) { var guiConfigs:Array = new Array(); for each(item in guiConfigProps) { guiConfigs.push(item.@name.toString()); } Application.application.dispatchEvent(new ConfigChangeEvent(ConfigChangeEvent.GUI_CONFIGS_CHANGE, guiConfigs)); } // Show alert Alert.show("Inserted : " + response.Inserted.@count + "\n" + "Updated : " + response.Updated.@count + "\n" + "Deleted : " + response.Deleted.@count); } }); var request:URLRequest = new URLRequest(_serverUrl + "request=DoTransaction"); request.data = "" + transaction.toXMLString(); request.method = URLRequestMethod.POST; request.contentType = "text/xml; charset=utf-8" request.requestHeaders.push(new URLRequestHeader("Content-Encoding", "UTF-8")); doTransactionRequest.load(request); var doGUIConfigRequest:URLLoader = new URLLoader(); doGUIConfigRequest.addEventListener(IOErrorEvent.IO_ERROR, function():void { dispatchEvent(new Event("ioError")); }); } public function hasChanges():Boolean { return (XMLList(contextProps.source.Context.(@status != "existing")) .length() > 0 || XMLList(serverProps.source.Server.(@status != "existing")) .length() > 0 || XMLList(layerProps.source.Layer.(@status != "existing")) .length() > 0 || XMLList(mapProps.source.Map.(@status != "existing")) .length() > 0 || XMLList(templateProps.source.Template.(@status != "existing")) .length() > 0 || XMLList(reportProps.source.Report.(@status != "existing")) .length() > 0); } /*public function addCollectionsEventListener(listener:Function):void { }*/ private var clientCapabilities:Object = new Object(); private var serverCapabilities:Object = new Object(); private function doGetCapabilitiesRequest(server:XML, retServer:Server):void { var serverProps:XML = getProps(server)[0]; var service:HTTPService = new HTTPService(); service.url = getCapabilitiesUrl(serverProps, retServer); service.resultFormat = "e4x"; service.addEventListener(FaultEvent.FAULT, function(event:FaultEvent):void { Alert.show(event.toString()); }); service.addEventListener(ResultEvent.RESULT, function():void { var result:XMLList = XMLList(service.lastResult); var serviceType:String = serverProps.Service.toString(); retServer.capabilities.source = result; retServer.layers.source = getServerLayersFromResponse( result, serviceType); if(serviceType == "OGC:WFS") { retServer.featureTypes.source = result.FeatureTypeList.FeatureType.copy(); for each(var type:XML in result.FeatureTypeList.FeatureType) { var name:String = type.Name; var uri:String = null; if(name.indexOf(":") != -1) { var prefix:String = name.split(":")[0]; name = name.split(":")[1]; uri = type.namespace(prefix); } var list:XMLListCollection = retServer.getFeatureTypeAttributes(new QName(uri, name)); doDescribeFeatureRequest(serverProps, uri, name, list); } } else if(serviceType == "GI") { retServer.featureTypes.source = result.FeatureTypesLocalWFSClient.FeatureType.copy(); for each(type in result.FeatureTypesLocalWFSClient.FeatureType) { name = type.toString(); uri = null; if(name.indexOf(":") != -1) { prefix = name.split(":")[0]; name = name.split(":")[1]; uri = type.namespace(prefix); } list = retServer.getFeatureTypeAttributes(new QName(uri, name)); doDescribeFeatureRequest(serverProps, uri, name, list); } } retServer.featureTypesEmptyItem.source = + retServer.featureTypes.source.copy(); if(serviceType == "GI") { for each(var layer:XML in retServer.capabilities.source.Layer) { name = layer.FeatureType; uri = null; if(name.indexOf(":") != -1) { prefix = name.split(":")[0]; name = name.split(":")[1]; uri = layer.FeatureType.namespace(prefix); } list = retServer.getLayerFeatureTypeAttributes(layer.Name.toString()); doDescribeFeatureRequest(serverProps, uri, name, list); retServer.layerFeatureTypes[layer.Name] = layer.FeatureType[0]; } } }); service.send(); } private function getCapabilities(server:XML, forceLoad:Boolean = false):Server { if(server == null || server.attribute("id").length() == 0 || server.attribute("clientId").length() == 0) { return new Server(); } var serverProps:XML = getProps(server); if(serverProps.@brief == 'true') { return new Server(); } var clientId:Boolean = server.@clientId == "true"; var retServer:Server; if(!forceLoad) { retServer = clientId ? clientCapabilities["" + server.@id] : serverCapabilities["" + server.@id]; if(retServer != null) { return retServer; } } retServer = new Server(); if(clientId) { clientCapabilities["" + server.@id] = retServer; } else { serverCapabilities["" + server.@id] = retServer; } if(serverProps.child("Security").length() > 0 && serverProps.Security != "none" && XML(serverProps.Security[0]).children().length() != 0) { var serverLoginPanel:ServerLoginPanel = new ServerLoginPanel(); PopUpManager.addPopUp(serverLoginPanel, DisplayObject(Application.application), true); BindingUtils.bindProperty(serverLoginPanel, "maxHeight", Application.application, "height"); BindingUtils.bindProperty(serverLoginPanel, "maxWidth", Application.application, "width"); BindingUtils.bindSetter(function():void { PopUpManager.centerPopUp(serverLoginPanel); }, mx.core.Application.application, "height"); BindingUtils.bindSetter(function():void { PopUpManager.centerPopUp(serverLoginPanel); }, mx.core.Application.application, "width"); PopUpManager.centerPopUp(serverLoginPanel); serverLoginPanel.loginHeading = serverProps.Title; serverLoginPanel.addEventListener(LoginEvent.LOGIN, function(event:LoginEvent):void { PopUpManager.removePopUp(serverLoginPanel); retServer.user = event.login; retServer.password = event.password; doGetCapabilitiesRequest(serverProps, retServer); }); } else { doGetCapabilitiesRequest(serverProps, retServer); } return retServer; } public function getServerLayers(server:XML, forceLoad:Boolean = false):XMLListCollection { return getCapabilities(server, forceLoad).layers; } public function getFeatureTypes(server:XML, forceLoad:Boolean = false, emptyItem:Boolean = true):XMLListCollection { if(emptyItem) { return getCapabilities(server, forceLoad).featureTypesEmptyItem; } else { return getCapabilities(server, forceLoad).featureTypes; } } public function getFeatureTypeAttributes(server:XML, featureType:XML, forceLoad:Boolean = false):XMLListCollection { if(featureType == null || server == null) { return null; } var serverProps:XML = getProps(server)[0]; var name:String = null; if(serverProps.Service == "OGC:WFS") { name = featureType.Name; } else if(serverProps.Service == "GI") { name = featureType.children()[0]; } var uri:String = null; if(name.indexOf(":") != -1) { uri = featureType.namespace(name.split(":")[0]); name = name.split(":")[1]; } var serverObj:Server = getCapabilities(server, forceLoad); return serverObj.getFeatureTypeAttributes(new QName(uri, name), forceLoad); } private function getCapabilitiesUrl(server:XML, retServer:Server):String { var url:String = ""; switch(server.Service.toString()) { case "GI": url = server.Onlineresource.toString() + "request=GetCapabilities"; break; case "OGC:WMS": url = server.Onlineresource.toString() + "service=WMS&request=GetCapabilities&version=" + server.Version.toString(); break; case "OGC:WFS": url = server.Onlineresource.toString() + "service=WFS&request=GetCapabilities&version=" + server.Version.toString(); } if(server.child("Proxy").length() > 0 && server.Proxy.toString() == "t") { url = this._proxyServerUrl + "/" + url.split("//")[1]; } if(server.child("Security").length() > 0) { switch(server.Security.toString()) { case "ows": url += "&user=" + retServer.user + "&password=" + retServer.password; } } return url; } private function removeNameless(layers:XMLList):XMLList { return layers.(child("Name").length() > 0); } private function flattenLayerList(rootLayer:XML):XMLList { var list:XMLList = new XMLList(); XML(list[0]).appendChild(rootLayer.copy()[0]); var subLayers:XMLList = rootLayer.Layer.copy(); delete list.Layer.Layer; for each(var layer:XML in subLayers) { for each(var subLayer:XML in flattenLayerList(layer)) { XML(list[0]).appendChild(subLayer); } } return list.children(); } private function getServerLayersFromResponse(serverResponse:XMLList, service:String):XMLList { switch(service) { case "GI": return serverResponse.Layer; case "OGC:WMS": return removeNameless( flattenLayerList(serverResponse.Capability.Layer[0])); } return null; } private function getFeatureTypeNamesFromResponse(serverResponse:XMLList, server:XML):Array { var names:Array = new Array(); var serviceType:String = server.Service; if(serviceType == "OGC:WFS") { for each(var type:XML in serverResponse.FeatureTypeList.FeatureType) { var name:String = type.Name; var uri:String = null; if(name.indexOf(":") != -1) { var prefix:String = name.split(":")[0]; name = name.split(":")[1]; uri = type.namespace(prefix); } var list:XMLListCollection = new XMLListCollection(); doDescribeFeatureRequest(server, uri, name, list); names.push([new QName(uri, name), list]); } } else if(serviceType == "GI") { } return names; } private function doDescribeFeatureRequest(server:XML, uri:String, name:String, list:XMLListCollection):void { var service:HTTPService = new HTTPService(); service.url = server.Onlineresource.toString() + "service=WFS&version=1.1.0&request=DescribeFeatureType" + "&typeName=" + (uri ? "pref:" : "") + name; if(uri != null) { service.url += "&namespace=xmlns(" + "pref=" + uri + ")"; } service.resultFormat = "e4x"; service.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void { var result:XMLList = XMLList(service.lastResult); var typeName:String = result.element.(@name == name).@type; var prefix:String = ""; var nspace:String = ""; if(typeName.indexOf(":") != -1) { var parts:Array = typeName.split(":"); if(result.namespace(parts[0]) == result.@targetNamespace) { typeName = parts[1]; } prefix = parts[0]; nspace = parts[1]; } var complexType:XMLList = result.complexType.(@name == typeName); var elements:XMLList = new XMLList(); elements.elements += complexType..element; elements.@prefix = prefix; elements.@nspace = nspace; list.source = elements.element; }); service.send(); } public function getLayerFeatureTypeAttributes(server:XML, layer:QName, forceLoad:Boolean = false):XMLListCollection { if(server.Service.toString() == "OGC:WFS") { return getCapabilities(server, forceLoad).getFeatureTypeAttributes(layer, forceLoad); } else { return getCapabilities(server, forceLoad).getLayerFeatureTypeAttributes(layer.localName); } } public function getFeatureTypeForQueryLayer(layer:XML, server:XML, forceLoad:Boolean = false):XML { var serverProps:XML = getProps(server)[0]; if(serverProps.Service == "OGC:WFS") { return layer; } else if(serverProps.Service == "GI") { return getCapabilities(server, forceLoad).layerFeatureTypes[layer.Name]; } return null; } public function getQueryLayers(server:XML, forceLoad:Boolean = false):XMLListCollection { if(server == null) { return null; } var serverProps:XML = getProps(server)[0]; if(serverProps.Service == "GI") { return getServerLayers(server, forceLoad); } else if(serverProps.Service == "OGC:WFS") { return getFeatureTypes(server, forceLoad, false); } return null; } private function getServerVersion(version:XMLList, position:Number):Number { var str:String = version.toString(); var index:Number = -1; for(var i:Number = 0; i < position; i++) { index = str.indexOf(".", index + 1); } var end:Number = str.indexOf(".", index + 1); if(end == -1) { str = str.substr(index + 1); } else { str = str.substring(index + 1, end); } return Number(str); } public function getTransformationServers():XMLList { return serverProps.source.(Service == "GI") .(getServerVersion(Version, 0) == 3); } public function getMapServers():XMLList { return serverProps.source .(Service == "GI" || Service == "OGC:WMS"); } public function getQueryServers(omitWfs:Boolean = false):XMLList { return serverProps.source .(Service == "GI" || (Service == "OGC:WFS" && !omitWfs)); } public function getFeatureServers():XMLList { return serverProps.source .(Service == "OGC:WFS"); } public function supportsFormats(server:XML):Boolean { return getProps(server).Service == "OGC:WMS"; } public function supportsSelections(server:XML):Boolean { return getProps(server).Service == "GI"; } public function isUnique(type:String, name:String, newElement:Boolean = false):Boolean { var count:Number = newElement ? 0 : 1; switch(type) { case 'Context': return XMLList(contextProps.source.(Name == name)).length() == count; break; case 'Layer': return XMLList(layerProps.source.(Name == name)).length() == count; break; case 'QueryAspect': return XMLList(queryAspectProps.source.(Name == name)).length() == count; break; case 'Template': return XMLList(templateProps.source.(Name == name)).length() == count; break case 'Map': return XMLList(mapProps.source.(Name == name)).length() == count; } return true; } public function getUnusedLayers(map:XML):XMLList { var list:XMLList = layerProps.source.copy(); var usedLayers:XMLList = this.getLayers(map).copy(); for(var i:Number = 0; i < list.length(); i++) { for each(var currentLayer:XML in usedLayers) { if(currentLayer.@clientId == list[i].@clientId && currentLayer.@id == list[i].@id) { delete list[i]; i--; } } } return list; } public function getUnusedMaps(context:XML):XMLList { var list:XMLList = mapProps.source.copy(); var usedMaps:XMLList = this.getMaps(context).copy(); for(var i:Number = 0; i < list.length(); i++) { for each(var currentMap:XML in usedMaps) { if(currentMap.@clientId == list[i].@clientId && currentMap.@id == list[i].@id) { delete list[i]; i--; } } } return list; } public function getUnusedQueryAspects(map:XML):XMLList { var list:XMLList = queryAspectProps.source.copy(); var usedQueryAspects:XMLList = this.getQueryAspects(map).copy(); for(var i:Number = 0; i < list.length(); i++) { for each(var currentQueryAspect:XML in usedQueryAspects) { if(currentQueryAspect.@clientId == list[i].@clientId && currentQueryAspect.@id == list[i].@id) { delete list[i]; i--; } } } return list; } public function getUnusedTemplates(map:XML):XMLList { var list:XMLList = templateProps.source.copy(); var usedTemplates:XMLList = this.getTemplates(map).copy(); for(var i:Number = 0; i < list.length(); i++) { for each(var currentTemplate:XML in usedTemplates) { if(currentTemplate.@clientId == list[i].@clientId && currentTemplate.@id == list[i].@id) { delete list[i]; i--; } } } return list; } public function dropServerCache(server:XML):void { var clientId:Boolean = false; if(server.child("@clientId").length() > 0) { clientId = server.@clientId == "true"; } if(clientId) { clientCapabilities["" + server.@id] = null; } else { serverCapabilities["" + server.@id] = null; } //dispatchEvent(new Event("serverCacheDropped")); } public function isServerUsed(server:XML):Boolean { if(server.localName() != "Server") { return false; } var clientId:Boolean = false; if(server.attribute("clientId").length() > 0) { clientId = server.@clientId.toString().toLowerCase() == "true"; } for each(var currentServer:XML in layerProps.source..Server) { var currentClientId:Boolean = false; if(currentServer.attribute("clientId").length() > 0) { currentClientId = currentServer.@clientId.toString().toLowerCase() == "true"; } if(currentClientId == clientId && currentServer.@id == server.@id) { return true; } } for each(currentServer in layerProps.source..Featureserver) { currentClientId = false; if(currentServer.attribute("clientId").length() > 0) { currentClientId = currentServer.@clientId.toString().toLowerCase() == "true"; } if(currentClientId == clientId && currentServer.@id == server.@id) { return true; } } for each(currentServer in queryAspectProps.source..Server) { currentClientId = false; if(currentServer.attribute("clientId").length() > 0) { currentClientId = currentServer.@clientId.toString().toLowerCase() == "true"; } if(currentClientId == clientId && currentServer.@id == server.@id) { return true; } } for each(currentServer in contextProps.source..Server) { currentClientId = false; if(currentServer.attribute("clientId").length() > 0) { currentClientId = currentServer.@clientId.toString().toLowerCase() == "true"; } if(currentClientId == clientId && currentServer.@id == server.@id) { return true; } } return false; } public function treeToProps(tree:XML, disableListeners:Boolean = false):void { // Disable listeners if(disableListeners) { removeListeners(); } if(tree.localName() == "Contexts") { for each(var map:XML in tree..Map) { var currentRef:XML = newRef(map); if(map != currentRef) { var props:XML = getProps(map); var mapLayerChilds:XMLList = new XMLList(); for each(var mapLayer:XML in map.Layers.Layer) { mapLayerChilds += newRef(mapLayer, false); } XML(props.Layers[0]).setChildren(mapLayerChilds); // TODO: drag and drop between maps allowed?? /*XML(props.Templates[0]).setChildren(map.Templates.Template); XML(props.QueryAspects[0]).setChildren(map.QueryAspects.QueryAspect); XML(props.Reports[0]).setChildren(map.Reports.Report);*/ for each(var layer:XML in map.Layers..Layer.(getProps(copy()).Type.toString() == "Group")) { var layerProps:XML = getProps(layer); var layerChilds:XMLList = new XMLList(); for each(var subLayer:XML in layer.children()) { layerChilds += newRef(subLayer, false); } if(layerChilds != layerProps.Layers.Layer) { XML(layerProps.Layers[0]).setChildren(layerChilds); if(layerProps.@status != "new") { layerProps.@status = "changed"; } } } if(props.@status != "new") { props.@status = "changed"; } } } } // Re enable listeners if(disableListeners) { addListeners(); } } // Copy content of contextTree to entities (used for dragging) public function updateEntity(item:XML, disableListeners:Boolean = false):void { // Disable listeners if(disableListeners) { removeListeners(); } var groupName:String = item.localName(); if(groupName == "Layer") { groupName = "Layers"; } var items:XMLList = new XMLList(); for each(var currentItem:XML in item.children()) { items += newRef(currentItem, false); } var parentNode:XML = getParentEntity(item); if(parentNode != null) { XML(parentNode.child(groupName)).setChildren(items); if(parentNode.@status != "new") { parentNode.@status = "changed"; } } // Re enable listeners if(disableListeners) { addListeners(); } } } }