Gateway selection added when removing an application
diff --git a/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/GatewayHttpClient.java b/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/GatewayHttpClient.java
index 60b4f18..e3481d5 100644
--- a/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/GatewayHttpClient.java
+++ b/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/GatewayHttpClient.java
@@ -12,11 +12,9 @@
 
 import java.io.IOException;
 import java.io.StringWriter;
-import java.net.URL;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.ConcurrentMap;
 
 import org.apache.log4j.Logger;
 import org.eclipse.sensinact.studio.http.client.snamessage.MsgFactory;
@@ -38,7 +36,6 @@
 import org.restlet.representation.Representation;
 import org.restlet.representation.StringRepresentation;
 import org.restlet.resource.ClientResource;
-import org.restlet.util.Series;
 
 /**
  * Central point for SYNCHRONUS communication with the sensinact gateway.
diff --git a/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/StudioRequest.java b/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/StudioRequest.java
index 8022585..df25774 100644
--- a/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/StudioRequest.java
+++ b/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/StudioRequest.java
@@ -17,13 +17,11 @@
 import org.eclipse.sensinact.studio.http.client.UIResult.DialogStatus;
 import org.eclipse.sensinact.studio.http.client.snamessage.MsgSensinact;
 import org.eclipse.sensinact.studio.http.client.snamessage.actresponse.MsgActResponse;
-import org.eclipse.sensinact.studio.http.client.snamessage.basic.MsgHttpError;
 import org.eclipse.sensinact.studio.http.client.snamessage.getresponse.MsgGetResponse;
 import org.eclipse.sensinact.studio.model.resource.utils.ResourceDescriptor;
 import org.eclipse.sensinact.studio.model.resource.utils.Segments;
-import org.restlet.data.Parameter;
-
 import org.eclipse.sensinact.studio.resource.AccessMethodType;
+import org.restlet.data.Parameter;
 
 /**
  * @author Etienne Gandrille
diff --git a/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/snamessage/MsgFactory.java b/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/snamessage/MsgFactory.java
index c25879c..5645a5e 100644
--- a/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/snamessage/MsgFactory.java
+++ b/services/org.eclipse.sensinact.studio.http/src/org/eclipse/sensinact/studio/http/client/snamessage/MsgFactory.java
@@ -19,6 +19,7 @@
 import org.eclipse.sensinact.studio.model.resource.utils.Segments;
 import org.json.JSONObject;
 
+import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
@@ -92,6 +93,7 @@
 	
 	private static ObjectMapper getMapper() {
 		ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 		SimpleModule module = new SimpleModule();
 		module.addDeserializer(ObjectNameTypeValue.class, new NameTypeValueDeserializer());
 		mapper.registerModule(module);
diff --git a/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelEditor.java b/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelEditor.java
index c96a061..0fa6c8c 100644
--- a/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelEditor.java
+++ b/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelEditor.java
@@ -33,6 +33,7 @@
 import org.eclipse.sensinact.studio.model.resource.utils.DeviceDescriptor;
 import org.eclipse.sensinact.studio.model.resource.utils.ResourceDescriptor;
 import org.eclipse.sensinact.studio.model.resource.utils.Segments;
+import org.eclipse.sensinact.studio.model.resource.utils.ServiceDescriptor;
 import org.eclipse.sensinact.studio.preferences.ConfigurationListerner;
 import org.eclipse.sensinact.studio.preferences.ConfigurationManager;
 import org.eclipse.sensinact.studio.preferences.GatewayHttpConfig;
@@ -319,6 +320,55 @@
 		});
 	}
 
+	/* ================= */
+	/* Find Applications */
+	/* ================= */
+	
+	@SuppressWarnings("unchecked")
+	public List<ServiceDescriptor> findApplications() throws InterruptedException {
+
+		setupStudio();
+
+		return (List<ServiceDescriptor>) getEditingDomain().runExclusive(new RunnableWithResult.Impl<List<ServiceDescriptor>>() {
+			@Override
+			public void run() {
+				List<ServiceDescriptor> retval = new ArrayList<>();
+				EList<Gateway> gateways = USE_IN_RUNEXLUSIVE_getStudio().getGateways();
+				for (Gateway gateway : gateways) {
+					Device appManager = findAppManager(gateway.getDevice());
+					if (appManager != null) {
+						retval.addAll(findApplications(appManager));
+					}
+				}
+				setResult(retval);
+				return;
+			}
+			
+			private Device findAppManager(EList<Device> devices) {
+				for (Device device : devices) {
+					if (device.getName().equals("AppManager"))
+						return device;
+				}
+				return null;
+			}
+			
+			private List<ServiceDescriptor> findApplications(Device appManager) {
+				List<ServiceDescriptor> retval = new ArrayList<>();
+				
+				String gateway = ((Gateway) appManager.eContainer()).getName();
+				String device = appManager.getName();
+				
+				for (Service service : appManager.getService()) {
+					String srvName = service.getName();
+					if (srvName != null && (! srvName.equalsIgnoreCase("admin"))) {
+						retval.add(new ServiceDescriptor(gateway, device, srvName));
+					}
+				}
+				return retval;
+			} 
+		});
+	}
+		
 	/* ============= */
 	/* Checks exists */
 	/* ============= */
diff --git a/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelUpdater.java b/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelUpdater.java
index b83267e..cfd69cc 100644
--- a/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelUpdater.java
+++ b/services/org.eclipse.sensinact.studio.model.manager/src/org/eclipse/sensinact/studio/model/manager/modelupdater/ModelUpdater.java
@@ -21,7 +21,6 @@
 import org.eclipse.sensinact.studio.http.client.GatewayHttpClient;
 import org.eclipse.sensinact.studio.http.client.GatewayHttpClient.RequestParameter;
 import org.eclipse.sensinact.studio.http.client.snamessage.MsgSensinact;
-import org.eclipse.sensinact.studio.http.client.snamessage.basic.MsgHttpError;
 import org.eclipse.sensinact.studio.http.client.snamessage.completelist.MsgCompleteList;
 import org.eclipse.sensinact.studio.http.client.snamessage.completelist.ObjectProvider;
 import org.eclipse.sensinact.studio.http.client.snamessage.completelist.ObjectResource;
diff --git a/services/org.eclipse.sensinact.studio.model.resource/src/org/eclipse/sensinact/studio/model/resource/utils/ServiceDescriptor.java b/services/org.eclipse.sensinact.studio.model.resource/src/org/eclipse/sensinact/studio/model/resource/utils/ServiceDescriptor.java
new file mode 100644
index 0000000..a447f03
--- /dev/null
+++ b/services/org.eclipse.sensinact.studio.model.resource/src/org/eclipse/sensinact/studio/model/resource/utils/ServiceDescriptor.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2018 CEA.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *     CEA - initial API and implementation and/or initial documentation
+ */
+package org.eclipse.sensinact.studio.model.resource.utils;
+
+/**
+ * @author Etienne Gandrille
+ */
+public class ServiceDescriptor {
+	
+	private final String gateway;
+	private final String device;
+	private final String service;
+	
+	public ServiceDescriptor(String gateway, String device, String service) {
+		super();
+		this.gateway = gateway;
+		this.device = device;
+		this.service = service;
+	}
+
+	public String getGateway() {
+		return gateway;
+	}
+
+	public String getDevice() {
+		return device;
+	}
+
+	public String getService() {
+		return service;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((device == null) ? 0 : device.hashCode());
+		result = prime * result + ((gateway == null) ? 0 : gateway.hashCode());
+		result = prime * result + ((service == null) ? 0 : service.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		ServiceDescriptor other = (ServiceDescriptor) obj;
+		if (device == null) {
+			if (other.device != null)
+				return false;
+		} else if (!device.equals(other.device))
+			return false;
+		if (gateway == null) {
+			if (other.gateway != null)
+				return false;
+		} else if (!gateway.equals(other.gateway))
+			return false;
+		if (service == null) {
+			if (other.service != null)
+				return false;
+		} else if (!service.equals(other.service))
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		return "ServiceDescriptor [gateway=" + gateway + ", device=" + device + ", service=" + service + "]";
+	}
+}
diff --git a/ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/DeviceNavigatorSorter.java b/ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/DeviceNavigatorSorter.java
index 3f278b1..b6fbe17 100644
--- a/ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/DeviceNavigatorSorter.java
+++ b/ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/DeviceNavigatorSorter.java
@@ -14,7 +14,6 @@
 
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerSorter;
-
 import org.eclipse.sensinact.studio.resource.impl.NamedElementImpl;
 
 /**
diff --git a/ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/toolbar/dialog/BasicListDialog.java b/ui/org.eclipse.sensinact.studio.ui.common/src/org/eclipse/sensinact/studio/ui/common/dialog/BasicListDialog.java
similarity index 83%
rename from ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/toolbar/dialog/BasicListDialog.java
rename to ui/org.eclipse.sensinact.studio.ui.common/src/org/eclipse/sensinact/studio/ui/common/dialog/BasicListDialog.java
index 7fc1cc0..57f6810 100644
--- a/ui/org.eclipse.sensinact.studio.navigator.device/src/org/eclipse/sensinact/studio/navigator/device/toolbar/dialog/BasicListDialog.java
+++ b/ui/org.eclipse.sensinact.studio.ui.common/src/org/eclipse/sensinact/studio/ui/common/dialog/BasicListDialog.java
@@ -8,7 +8,7 @@
  *  Contributors:
  *     CEA - initial API and implementation and/or initial documentation
  */
-package org.eclipse.sensinact.studio.navigator.device.toolbar.dialog;
+package org.eclipse.sensinact.studio.ui.common.dialog;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -20,6 +20,10 @@
 import org.eclipse.ui.dialogs.ListDialog;
 
 /**
+ * Dialog to pick a SINGLE element from a list.
+ * 
+ * getFirstResult method added for convinience. 
+ * 
  * @author Etienne Gandrille
  */
 public class BasicListDialog extends ListDialog {
@@ -58,4 +62,11 @@
 		
 		return list.toArray(new String[0]);
 	}
+	
+	public String getFirstResult() {
+		String[] results = getResult();
+		if (results == null || results.length == 0)
+			return null;
+		return results[0];
+	}	
 }
diff --git a/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaAppHandler.java b/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaAppHandler.java
index e8031ef..a8aa2a2 100644
--- a/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaAppHandler.java
+++ b/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaAppHandler.java
@@ -23,7 +23,6 @@
 import org.eclipse.sensinact.studio.ui.common.dialog.SnaHandler;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.sensinact.studio.http.client.snamessage.MsgSensinact;
-import org.eclipse.sensinact.studio.http.client.snamessage.basic.MsgHttpError;
 import org.eclipse.sensinact.studio.language.sensinact.DSL_SENSINACT;
 import org.eclipse.sensinact.studio.language.sensinact.Sensinact;
 
diff --git a/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaDeployHandler.java b/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaDeployHandler.java
index 1098311..96ccd9b 100644
--- a/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaDeployHandler.java
+++ b/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaDeployHandler.java
@@ -20,7 +20,6 @@
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.sensinact.studio.http.client.GatewayHttpClient;
 import org.eclipse.sensinact.studio.http.client.snamessage.MsgSensinact;
-import org.eclipse.sensinact.studio.http.client.snamessage.basic.MsgHttpError;
 import org.eclipse.sensinact.studio.model.resource.utils.Constants;
 import org.eclipse.sensinact.studio.model.resource.utils.ResourceDescriptor;
 import org.eclipse.sensinact.studio.model.resource.utils.Segments;
diff --git a/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaRemoveHandler.java b/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaRemoveHandler.java
index a082001..70dc582 100644
--- a/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaRemoveHandler.java
+++ b/ui/org.eclipse.sensinact.studio.view.projectexplorer/src/org/eclipse/sensinact/studio/view/projectexplorer/handler/SnaRemoveHandler.java
@@ -11,17 +11,24 @@
 package org.eclipse.sensinact.studio.view.projectexplorer.handler;
 
 import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.log4j.Logger;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.sensinact.studio.http.client.GatewayHttpClient;
 import org.eclipse.sensinact.studio.http.client.snamessage.MsgSensinact;
+import org.eclipse.sensinact.studio.model.manager.modelupdater.ModelEditor;
 import org.eclipse.sensinact.studio.model.resource.utils.Constants;
 import org.eclipse.sensinact.studio.model.resource.utils.JsonUtil;
 import org.eclipse.sensinact.studio.model.resource.utils.ResourceDescriptor;
 import org.eclipse.sensinact.studio.model.resource.utils.Segments;
 import org.eclipse.sensinact.studio.resource.AccessMethodType;
+import org.eclipse.sensinact.studio.ui.common.dialog.BasicListDialog;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -40,10 +47,18 @@
 		String fileName = computeRuleName(snaFileURI);
 		
 		try {
-			// TODO remove this when gateway management will be implemented
-			String gatewayID = null;
-			MsgSensinact response = uninstall(Constants.createUninstallAppRD(gatewayID), fileName);
-			displayResult(getShell(event), "Application removed", fileName, response);
+			List<String> gatewayIds = ModelEditor.getInstance().findApplications().stream().filter(sd -> sd.getService().equals(fileName)).map(sd -> sd.getGateway()).collect(Collectors.toList());
+			
+			if (gatewayIds.size() == 0) {
+				MessageDialog.openError(getShell(event), "Application removal failed", "Application not found.\nIs the gateway connected?");
+			} else {
+				BasicListDialog listDialog = new BasicListDialog(getShell(event), "Gateway selection", "Please choose a Gateway", gatewayIds.toArray(new String[0]));
+				if (listDialog.open() == Window.OK) {
+					String gatewayID = listDialog.getFirstResult();
+					MsgSensinact response = uninstall(Constants.createUninstallAppRD(gatewayID), fileName);
+					displayResult(getShell(event), "Application removed", fileName, response);					
+				}
+			}
 		} catch (Exception e) {
 			displayResult(getShell(event), "Application removed", fileName, e);
 			logger.error("Application removal failed", e);
@@ -60,6 +75,7 @@
 		JSONObject params = new JSONObject();
 		params.put("parameters", jsonParameters);
 		Segments path = new Segments.Builder().resource(resource).method(AccessMethodType.ACT).build();
-		return null; // (SnaMessage)  GatewayHttpClient.sendPostRequest(path, jsonParameters);
+		MsgSensinact msg = GatewayHttpClient.sendPostRequest(path, jsonParameters);
+		return msg;
 	}
 }