From a4428494c58485ea11d215d4e2bc649e7ce6a1b2 Mon Sep 17 00:00:00 2001
From: David Bohn <davbohn@googlemail.com>
Date: Wed, 22 Jun 2016 12:23:05 +0200
Subject: [PATCH] Added configuration skeleton to ease the creation of certain
 wallet environments

---
 pom.xml                                       |  5 ++
 src/main/java/fucoin/Main.java                | 77 ++++++++++---------
 .../configurations/AbstractConfiguration.java | 75 ++++++++++++++++++
 .../configurations/DefaultConfiguration.java  | 18 +++++
 .../MassWalletConfiguration.java              | 17 ++++
 5 files changed, 157 insertions(+), 35 deletions(-)
 create mode 100644 src/main/java/fucoin/configurations/AbstractConfiguration.java
 create mode 100644 src/main/java/fucoin/configurations/DefaultConfiguration.java
 create mode 100644 src/main/java/fucoin/configurations/MassWalletConfiguration.java

diff --git a/pom.xml b/pom.xml
index 9bf2c6d..1a37142 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,5 +51,10 @@
             <artifactId>akka-remote_2.11</artifactId>
             <version>2.4.7</version>
         </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.10</version>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/src/main/java/fucoin/Main.java b/src/main/java/fucoin/Main.java
index f992c44..2b491c8 100644
--- a/src/main/java/fucoin/Main.java
+++ b/src/main/java/fucoin/Main.java
@@ -1,31 +1,30 @@
 package fucoin;
 
-import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
-import akka.actor.Props;
 import com.typesafe.config.Config;
 import com.typesafe.config.ConfigFactory;
-import fucoin.actions.join.ActionTellSupervisor;
+import fucoin.configurations.AbstractConfiguration;
 import fucoin.setup.NetworkInterfaceReader;
-import fucoin.supervisor.SuperVisorImpl;
-import fucoin.wallet.WalletImpl;
-
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+import org.reflections.util.FilterBuilder;
+
+import javax.swing.*;
 import java.io.File;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 
 public class Main {
 
-    private static int numberOfWallets = 2;
-    private static boolean createGUI = false;
-
     private static ActorSystem cSystem;
 
-    private static ActorRef cSuperVisorActor;
-
-    private static List<ActorRef> cActiveActors = new ArrayList<>();
-
     static {
         String hostname = NetworkInterfaceReader.readDefaultHostname();
 
@@ -41,37 +40,45 @@ public class Main {
 
         //Init System Actor System
         cSystem = ActorSystem.create("Core", ConfigFactory.parseString("akka.remote.netty.tcp.hostname=" + hostname).withFallback(config));
-        cSuperVisorActor = cSystem.actorOf(SuperVisorImpl.props(), "SuperVisorImpl");
     }
 
-    public static void main(String[] args) throws InterruptedException {
-        createWallets();
+    public static void main(String[] args) throws InterruptedException, IllegalAccessException, InstantiationException {
+        List<AbstractConfiguration> configurations = getAbstractConfigurations();
+
+        AbstractConfiguration[] configs = new AbstractConfiguration[configurations.size()];
+        configurations.toArray(configs);
+
+        AbstractConfiguration selectedConfig = (AbstractConfiguration) JOptionPane.showInputDialog(null, "Select a configuration to run", "Configuration Selection", JOptionPane.QUESTION_MESSAGE, null, configs, configurations.get(0));
+        if (selectedConfig != null) {
+            selectedConfig.setSystem(cSystem);
+            selectedConfig.run();
+        } else {
+            cSystem.terminate();
+        }
     }
 
-    private static void createWallets() {
-        //Init Wallets
-        for (int i = 0; i < numberOfWallets; i++) {
+    private static List<AbstractConfiguration> getAbstractConfigurations() throws InstantiationException, IllegalAccessException {
+        List<ClassLoader> classLoadersList = new LinkedList<>();
+        classLoadersList.add(ClasspathHelper.contextClassLoader());
+        classLoadersList.add(ClasspathHelper.staticClassLoader());
 
-            String nameOfTheWallet = "Wallet" + String.valueOf(i);
-            Props props;
+        Reflections reflections = new Reflections(new ConfigurationBuilder()
+                .setScanners(new SubTypesScanner(false), new ResourcesScanner())
+                .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[0])))
+                .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("fucoin.configurations"))));
 
-            if (i > 0) {
-                //chain the wallets. wallet2 knows wallet1, wallet3 knows wallet2 and so on.
-                props = WalletImpl.props(cActiveActors.get(i - 1), nameOfTheWallet, createGUI);
-            } else {
-                props = WalletImpl.props(null, nameOfTheWallet, createGUI);
-            }
+        Set<Class<? extends Object>> allClasses =
+                reflections.getSubTypesOf(Object.class);
 
-            ActorRef actorRef = cSystem.actorOf(props, nameOfTheWallet);
+        List<AbstractConfiguration> configurations = new ArrayList<>();
 
-            // first wallet does not have a neighbour, so it can't send a ActionJoin to anybody
-            // instead we send directly an ActionJoinAnswer with the supervisor reference
-            if (i == 0) {
-                //actorRef.tell(new ActionJoinAnswer(cSuperVisorActor), cSuperVisorActor);
-                actorRef.tell(new ActionTellSupervisor(cSuperVisorActor), cSuperVisorActor);
+        for (Class<? extends Object> oneClass: allClasses){
+            if (!Modifier.isAbstract(oneClass.getModifiers())) {
+                AbstractConfiguration cfg = (AbstractConfiguration)oneClass.newInstance();
+                cfg.setSystem(cSystem);
+                configurations.add(cfg);
             }
-
-            cActiveActors.add(actorRef);
         }
+        return configurations;
     }
 }
diff --git a/src/main/java/fucoin/configurations/AbstractConfiguration.java b/src/main/java/fucoin/configurations/AbstractConfiguration.java
new file mode 100644
index 0000000..649ef96
--- /dev/null
+++ b/src/main/java/fucoin/configurations/AbstractConfiguration.java
@@ -0,0 +1,75 @@
+package fucoin.configurations;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import fucoin.actions.join.ActionTellSupervisor;
+import fucoin.supervisor.SuperVisorImpl;
+import fucoin.wallet.WalletImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ */
+public abstract class AbstractConfiguration {
+
+    protected ActorSystem cSystem;
+    protected ActorRef superVisor;
+
+    protected final List<ActorRef> activeActors = new ArrayList<>();
+
+    public void setSystem(ActorSystem system) {
+        cSystem = system;
+    }
+
+    public ActorRef spawnWallet(String name, boolean createGUI) {
+        Props props;
+        int numOfWallets = activeActors.size();
+        if (numOfWallets == 0) {
+            props = WalletImpl.props(null, name, createGUI);
+        } else {
+            props = WalletImpl.props(activeActors.get(numOfWallets - 1), name, createGUI);
+        }
+
+        ActorRef actorRef = cSystem.actorOf(props, name);
+
+        activeActors.add(actorRef);
+
+        if (numOfWallets == 0) {
+            //actorRef.tell(new ActionJoinAnswer(cSuperVisorActor), cSuperVisorActor);
+            actorRef.tell(new ActionTellSupervisor(superVisor), superVisor);
+        }
+
+        return actorRef;
+    }
+
+    public void spawnWallets(int n, boolean createGUI) {
+        for (int i = 0; i < n; i++) {
+            String nameOfTheWallet = "Wallet" + String.valueOf(activeActors.size());
+            spawnWallet(nameOfTheWallet, createGUI);
+        }
+    }
+
+    public ActorRef initSupervisor() {
+        superVisor = cSystem.actorOf(SuperVisorImpl.props(), "SuperVisorImpl");
+
+        // Don't ask.
+        try {
+            Thread.sleep(200);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return superVisor;
+    }
+
+    public abstract void run();
+
+    public abstract String getName();
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+}
diff --git a/src/main/java/fucoin/configurations/DefaultConfiguration.java b/src/main/java/fucoin/configurations/DefaultConfiguration.java
new file mode 100644
index 0000000..f3dd28a
--- /dev/null
+++ b/src/main/java/fucoin/configurations/DefaultConfiguration.java
@@ -0,0 +1,18 @@
+package fucoin.configurations;
+
+/**
+ *
+ */
+public class DefaultConfiguration extends AbstractConfiguration {
+
+    @Override
+    public void run() {
+        initSupervisor();
+        spawnWallets(2, true);
+    }
+
+    @Override
+    public String getName() {
+        return "Default Configuration";
+    }
+}
diff --git a/src/main/java/fucoin/configurations/MassWalletConfiguration.java b/src/main/java/fucoin/configurations/MassWalletConfiguration.java
new file mode 100644
index 0000000..f4c3587
--- /dev/null
+++ b/src/main/java/fucoin/configurations/MassWalletConfiguration.java
@@ -0,0 +1,17 @@
+package fucoin.configurations;
+
+/**
+ *
+ */
+public class MassWalletConfiguration extends AbstractConfiguration {
+    @Override
+    public void run() {
+        initSupervisor();
+        spawnWallets(200, false);
+    }
+
+    @Override
+    public String getName() {
+        return "Lots of wallets";
+    }
+}
-- 
GitLab