From 147092efd55111453183edfd438cf5db0dd72e5b Mon Sep 17 00:00:00 2001
From: Philipp Spohr <spohr.philipp@web.de>
Date: Mon, 11 Dec 2017 08:11:24 +0100
Subject: [PATCH] -Hotfix: Prevented using forbidden and permanent for the same
 edge -Work on CyRest support

---
 pom.xml                                       |  5 ++
 .../de/hhu/ba/yoshikoWrapper/CyActivator.java |  2 +
 .../de/hhu/ba/yoshikoWrapper/core/CyCore.java |  2 +
 .../ba/yoshikoWrapper/core/NetworkParser.java | 31 +++++----
 .../core/NetworkParsingException.java         | 17 +++++
 .../hhu/ba/yoshikoWrapper/core/YoshUtil.java  |  2 +
 .../cytoUtil/CommandExecutor.java             | 20 ++++++
 .../hhu/ba/yoshikoWrapper/help/HelpLinks.java | 68 +------------------
 .../swing/AboutDialogFactory.java             | 57 ----------------
 .../swing/components/HelpButton.java          | 26 ++++---
 .../swing/components/MainPanel.java           |  3 +-
 src/main/resources/YoshikoStrings.properties  |  6 ++
 12 files changed, 91 insertions(+), 148 deletions(-)
 create mode 100644 src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParsingException.java
 create mode 100644 src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/CommandExecutor.java
 delete mode 100644 src/main/java/de/hhu/ba/yoshikoWrapper/swing/AboutDialogFactory.java

diff --git a/pom.xml b/pom.xml
index 453fd7a..83bdc3b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,6 +162,11 @@
 			<artifactId>group-api</artifactId>
 			<version>${cytoscape.api.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>org.cytoscape</groupId>
+			<artifactId>command-executor-api</artifactId>
+			<version>${cytoscape.api.version}</version>
+		</dependency>
 	</dependencies>
 
 	<description>A Cytoscape plugin for graph-based clustering that wraps the yoshiko algorithm.</description>
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java b/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java
index 1652fed..a228110 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java
@@ -26,6 +26,7 @@ import java.util.Properties;
 import org.cytoscape.application.CyApplicationManager;
 import org.cytoscape.application.swing.CySwingApplication;
 import org.cytoscape.application.swing.CytoPanelComponent;
+import org.cytoscape.command.CommandExecutorTaskFactory;
 import org.cytoscape.model.CyNetworkFactory;
 import org.cytoscape.model.CyNetworkManager;
 import org.cytoscape.model.subnetwork.CyRootNetworkManager;
@@ -94,6 +95,7 @@ public class CyActivator extends AbstractCyActivator {
 		//TODO: Not sure how to correctly infer arguments here
 		CyCore.renderingEngineFactory = getService(context,RenderingEngineFactory.class);
 		CyCore.cloneNetworkTaskFactory = getService(context,CloneNetworkTaskFactory.class);
+		CyCore.commandExecutorTaskFactory = getService(context,CommandExecutorTaskFactory.class);
 
 		//Store a reference to the Version for easier access
 		YoshUtil.version = context.getBundle().getVersion();
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java
index e51449e..0707782 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java
@@ -25,6 +25,7 @@ import java.util.concurrent.CountDownLatch;
 
 import org.cytoscape.application.CyApplicationManager;
 import org.cytoscape.application.swing.CySwingApplication;
+import org.cytoscape.command.CommandExecutorTaskFactory;
 import org.cytoscape.model.CyNetwork;
 import org.cytoscape.model.CyNetworkFactory;
 import org.cytoscape.model.CyNetworkManager;
@@ -68,6 +69,7 @@ public class CyCore {
 	public static CyRootNetworkManager rootNetworkManager;
 	public static RenderingEngineFactory<CyNetwork> renderingEngineFactory;
 	public static CloneNetworkTaskFactory cloneNetworkTaskFactory;
+	public static CommandExecutorTaskFactory commandExecutorTaskFactory;
 	//
 
 	//Convenience
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParser.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParser.java
index eed69b6..64d16b7 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParser.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParser.java
@@ -1,16 +1,16 @@
 /*******************************************************************************
  * Copyright (C) 2017 Philipp Spohr
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -34,18 +34,18 @@ import de.hhu.ba.yoshikoWrapper.logging.YoshikoLogger;
 import de.hhu.ba.yoshikoWrapper.swig.LibraryInput;
 
 public class NetworkParser {
-	
+
 	//Symbolic Links
 	private static Logger logger = YoshikoLogger.getInstance().getLogger();
 
-	public static LibraryInput parseNetwork(
+	public static LibraryInput parseNetwork (
 			CyNetwork net,
 			NodeMap nodeMap,
 			CyColumn weightColumn,
 			CyColumn permanentColumn,
 			CyColumn forbiddenColumn,
 			double deletionCostDefault
-			) 
+			) throws NetworkParsingException
 	{
 		//Create an empty instance / fetch C++ object pointer
 		LibraryInput generatedInput = new LibraryInput();
@@ -54,18 +54,16 @@ public class NetworkParser {
 			generatedInput.setSize(net.getNodeCount());
 			//Fetch edges
 			List<CyEdge> edges = net.getEdgeList();
-			
 
-			
 			//Loop over edges
 			for (CyEdge e : edges) {
-				
+
 				//Parse editing costs
 				double weight = deletionCostDefault;
-				
+
 				//Fetch entry and check if it exists
 				CyRow edgeEntry = net.getRow(e);
-				
+
 				//Check if there is a weight column defined, else skip
 				if (weightColumn != null){
 					//Check if the column contains an entry for the respective edge
@@ -83,7 +81,7 @@ public class NetworkParser {
 				//Parse Forbidden/Permanent markers
 				boolean forbidden = false;
 				boolean permanent = false;
-				
+
 				if (permanentColumn != null) {
 					//Additional check as it is not required to have a value in every row
 					if (edgeEntry.get(permanentColumn.getName(), Boolean.class) != null) {
@@ -97,8 +95,13 @@ public class NetworkParser {
 					}
 				}
 
+				//Check for edges that are forbidden AND permanent -> Throw exception
+				if (forbidden && permanent) {
+					throw new NetworkParsingException(LocalizationManager.get("dualInfinityError"));
+				}
+
 				logger.debug("Found Edge: "+edgeEntry.get("name", String.class)+ " with weight:"+weight);
-				
+
 				generatedInput.addEdge(
 						nodeMap.get(e.getSource()),
 						nodeMap.get(e.getTarget()),
@@ -106,7 +109,7 @@ public class NetworkParser {
 						permanent,
 						forbidden
 					);
-				
+
 			}
 		}
 		return generatedInput;
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParsingException.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParsingException.java
new file mode 100644
index 0000000..65b9c43
--- /dev/null
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/NetworkParsingException.java
@@ -0,0 +1,17 @@
+package de.hhu.ba.yoshikoWrapper.core;
+
+@SuppressWarnings("serial")
+public class NetworkParsingException extends Exception {
+
+	private String msg;
+
+	public NetworkParsingException(String msg) {
+		this.msg = msg;
+	}
+
+	@Override
+	public String getMessage() {
+		return LocalizationManager.get("networkParsingException")+" "+msg;
+	}
+
+}
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/YoshUtil.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/YoshUtil.java
index b85271e..9580bd5 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/YoshUtil.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/YoshUtil.java
@@ -5,4 +5,6 @@ import org.osgi.framework.Version;
 
 public class YoshUtil {
 	public static Version version;
+
+	public static final String ABOUT_LINK = "https://spqrph.github.io/cytoscape-tutorials/presentations/yoshiko/yoshiko.html#/title";
 }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/CommandExecutor.java b/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/CommandExecutor.java
new file mode 100644
index 0000000..382678f
--- /dev/null
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/CommandExecutor.java
@@ -0,0 +1,20 @@
+package de.hhu.ba.yoshikoWrapper.cytoUtil;
+
+import java.util.Map;
+
+import org.cytoscape.work.TaskObserver;
+
+import de.hhu.ba.yoshikoWrapper.core.CyCore;
+
+public class CommandExecutor{
+
+	public static void executeCommand(String namespace, String command,
+            Map<String, Object> args, TaskObserver observer) {
+		;
+		CyCore.dialogTaskManager.execute(
+				CyCore.commandExecutorTaskFactory.createTaskIterator(namespace, command, args, observer)
+				);
+
+	}
+
+}
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/help/HelpLinks.java b/src/main/java/de/hhu/ba/yoshikoWrapper/help/HelpLinks.java
index 3c77e1c..597eca4 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/help/HelpLinks.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/help/HelpLinks.java
@@ -21,75 +21,13 @@
  ******************************************************************************/
 package de.hhu.ba.yoshikoWrapper.help;
 
-import java.awt.Container;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.WeakHashMap;
+import java.util.HashMap;
 
-import org.slf4j.Logger;
-
-import de.hhu.ba.yoshikoWrapper.logging.YoshikoLogger;
-import de.hhu.ba.yoshikoWrapper.swing.components.EditCostPanel;
-
-/**
- * Helper class that provides URIs to access the Bachelor Thesis paper sections that can be used as a manual
- *
- */
 public final class HelpLinks {
 
-	//SYMBOLIC LINKS
-
-	/**
-	 * Convenience function for better code readability
-	 */
-	private static final Logger logger = YoshikoLogger.getInstance().getLogger();
-
-	//
-
-	/**
-	 * The base location of the bachelor thesis paper
-	 */
-	//TODO: Add final location when published
-	private static final String docLocation = "https://gitlab.cs.uni-duesseldorf.de/spohr/YoshikoWrapper/tree/master";
-
-	/**
-	 * A HashMap linking Classes to a link, pointing to a specific subsection of the BachelorThesis paper that is relevant for understanding the Class
-	 */
-	private static final WeakHashMap <Class<? extends Container>,URI> helpLinks;
-
-	/**
-	 * Initialization for the HashMap
-	 */
+	public static final HashMap<String,Object> mainInfo = new HashMap<String,Object>();
 	static {
-		helpLinks = new WeakHashMap<Class<? extends Container>,URI>();
-		try {
-			helpLinks.put(EditCostPanel.class, (buildURI("subsubsection.2.2.1")));
-		} catch (URISyntaxException e) {
-			logger.error("Error initializing URI for help file:\n"+e.getMessage());
-		}
-	}
-
-
-	/**
-	 * Returns the URI that leads to the relevant help section for the class provided
-	 * @param c The Container class for which the help link should be fetched
-	 * @return The help link as URI
-	 */
-	public static URI getHelpLink(Class<? extends Container> c) {
-		if (helpLinks.containsKey(c)) {
-			return helpLinks.get(c);
-		}
-		return null;
-	}
-
-	/**
-	 * Internal helper function that builds a valid URI from the base address and the fragment denoting the relevant section
-	 * @param fragment The fragment naming the nameddest in the pdf file
-	 * @return The compound URI made from base address and fragment
-	 * @throws URISyntaxException If invalid -> Should never be called during runtime in a stable version
-	 */
-	private static URI buildURI(String fragment) throws URISyntaxException {
-		return new URI(null,docLocation,"nameddest="+fragment);
+		mainInfo.put("url", "https://spqrph.github.io/cytoscape-tutorials/presentations/yoshiko/yoshiko.html#/title");
 	}
 
 }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/AboutDialogFactory.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/AboutDialogFactory.java
deleted file mode 100644
index 915093c..0000000
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/AboutDialogFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.hhu.ba.yoshikoWrapper.swing;
-
-import javax.swing.GroupLayout;
-import javax.swing.GroupLayout.Alignment;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
-import de.hhu.ba.yoshikoWrapper.core.YoshUtil;
-import de.hhu.ba.yoshikoWrapper.swing.components.YoshikoHeader;
-
-/**Factory for a simple About-Dialog that provides some basic info about the software
- *
- */
-public class AboutDialogFactory{
-	
-	private static JPanel getDialogPanel() {
-		
-		JPanel ret = new JPanel();
-		
-		final YoshikoHeader header;
-		final JLabel version;
-		final JLabel text;
-		
-		header = new YoshikoHeader();
-		version = new JLabel(LocalizationManager.get("wrapperVersion")+": "+YoshUtil.version);
-		text = new JLabel(LocalizationManager.get("about"));
-		
-		SwingUtil.addAll(ret, header,version,text);
-		
-		GroupLayout layout = new GroupLayout(ret);
-		layout.setAutoCreateGaps(true);
-		layout.setHorizontalGroup(layout.createParallelGroup(Alignment.CENTER)
-			.addComponent(header)
-			.addComponent(version)
-			.addComponent(text)
-		);
-		layout.setVerticalGroup(layout.createSequentialGroup()
-			.addComponent(header)
-			.addComponent(version)
-			.addComponent(text)
-		);
-		
-		ret.setLayout(layout);
-					
-		return ret;
-	}
-
-	public static void showDialog() {
-		JOptionPane.showMessageDialog(
-				null,
-				getDialogPanel(),
-				LocalizationManager.get("aboutTitle"),
-				JOptionPane.PLAIN_MESSAGE);
-	}
-}
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/HelpButton.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/HelpButton.java
index f4bdbc1..bb7a004 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/HelpButton.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/HelpButton.java
@@ -6,13 +6,17 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.io.IOException;
 import java.net.URI;
+import java.util.HashMap;
 
 import javax.swing.BorderFactory;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JOptionPane;
 
+import org.cytoscape.command.CommandExecutorTaskFactory;
+
 import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
+import de.hhu.ba.yoshikoWrapper.cytoUtil.CommandExecutor;
 import de.hhu.ba.yoshikoWrapper.help.HelpLinks;
 import de.hhu.ba.yoshikoWrapper.swing.GraphicsLoader;
 
@@ -28,31 +32,33 @@ public class HelpButton extends JButton{
 	 * The default icon for the help button that should be shown if the button is not highlighted
 	 */
 	private static final ImageIcon defaultIcon = GraphicsLoader.getInfoIcon(SIZE);
+
 	/**
-	 * The icon tor the help button that should be shown if the button is highlighted
+	 * The icon for the help button that should be shown if the button is highlighted
 	 */
 	private static final ImageIcon hlIcon = GraphicsLoader.getInfoIconHL(SIZE);
 
+
+
 	public HelpButton() {
+
 		super(defaultIcon);
+
+		//Design/Style
 		setToolTipText(LocalizationManager.get("tooltip_helpButton"));
 		setBorder(BorderFactory.createEmptyBorder());
+
+		//Add main functionality
 		addActionListener(
 			new ActionListener() {
 				@Override
 				public void actionPerformed(ActionEvent e) {
-					URI uri = HelpLinks.getHelpLink(getParent().getClass());
-					if (uri != null) {
-						try {
-							java.awt.Desktop.getDesktop().browse(uri);
-						} catch (IOException ex) {
-							JOptionPane.showMessageDialog(null, "DEBUG: Thesis is currently not online! Works only on my pc!");
-							ex.printStackTrace();
-						}
-					}
+
+					CommandExecutor.executeCommand("cybrowser", "show",HelpLinks.mainInfo , null);
 				}
 			}
 		);
+
 		//Add mouse listener (cosmetic only)
 		addMouseListener(new MouseListener() {
 			@Override
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java
index 0b60b3c..5c521c5 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swing/components/MainPanel.java
@@ -59,7 +59,6 @@ import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
 import de.hhu.ba.yoshikoWrapper.core.ParameterSet;
 import de.hhu.ba.yoshikoWrapper.core.YoshikoLoader;
 import de.hhu.ba.yoshikoWrapper.cytoUtil.GraphAnalyzer;
-import de.hhu.ba.yoshikoWrapper.swing.AboutDialogFactory;
 import de.hhu.ba.yoshikoWrapper.swing.GraphicsLoader;
 import de.hhu.ba.yoshikoWrapper.swing.LibraryPanelFactory;
 import de.hhu.ba.yoshikoWrapper.swing.SwingUtil;
@@ -118,7 +117,7 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 
 			@Override
 			public void actionPerformed(ActionEvent e) {
-				AboutDialogFactory.showDialog();
+				//CommandExecutorTaskFactory fac;
 			}
 
 		});
diff --git a/src/main/resources/YoshikoStrings.properties b/src/main/resources/YoshikoStrings.properties
index 085bc84..69c2d91 100644
--- a/src/main/resources/YoshikoStrings.properties
+++ b/src/main/resources/YoshikoStrings.properties
@@ -34,12 +34,15 @@ cost = Editing Cost:
 createMetaGraph = Create Meta-Graph
 createClusterView = Create Cluster Views
 currentGap = [ILP] Current Instance Gap
+
 defaultDeletion = Default deletion cost:
 defaultInsertion = Default insertion cost:
 deleteSolution = Do you really want to delete this solution?
 directedGraphWarning = This algorithm works on undirected graphs. Directed edges are \n treated as undirected edges.
 disableMultiThreading = Disable Multithreading
 discardSolution = Discard
+dualInfinityError = An edge was marked as forbidden and permanent.
+
 editingCostPanel = Editing Costs
 exportSelectedClusters = Export selected clusters
 firstStart = Thanks for using the Yoshiko Clustering Tool!\nIt appears, that this is your first time using this tool.\nIf you want an in-depth explanation of the algorithm please refer to: [INSERT COOL LINK HERE]
@@ -57,11 +60,14 @@ metaGraph = Meta Graph
 metaGraph_edges = Fetching edges and calculating edge strengths
 multFactor = Multiplicative Factor for SNR:
 multiGraphWarning = This graph is a multigraph. This algorithms behavior on multigraphs is not yet researched.
+
+networkParsingException: An error occured while parsing the network:
 noFeasible = No feasible solution found!
 noLibMessage = There is no Yoshiko Library currently loaded! You might have to specify its location.
 noLibTitle = Library not loaded!
 noMappingHint = You haven't mapped the cost value to a column in your edge table.\nYoshiko runs significantly faster and generates better solutions if you map values.
 nodes = Nodes
+
 optionpane_title = Yoshiko Info
 noClustersSelected = You have not selected any clusters
 notOptimal = Optimality not guaranteed
-- 
GitLab