From a16e85dfcda1e3080b7c2688b3cf4e516adf8ad3 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 28 Jul 2017 21:25:02 -0700 Subject: [PATCH] Rewrite Abacus to be the central class of the application. --- src/org/nwapw/abacus/Abacus.java | 150 +++++++++++++++--- .../nwapw/abacus/plugin/PluginManager.java | 9 +- src/org/nwapw/abacus/tree/NumberReducer.java | 18 +-- src/org/nwapw/abacus/window/Window.java | 58 ++----- 4 files changed, 155 insertions(+), 80 deletions(-) diff --git a/src/org/nwapw/abacus/Abacus.java b/src/org/nwapw/abacus/Abacus.java index 3343d71..9b6a6ea 100644 --- a/src/org/nwapw/abacus/Abacus.java +++ b/src/org/nwapw/abacus/Abacus.java @@ -1,46 +1,148 @@ package org.nwapw.abacus; -import org.nwapw.abacus.plugin.PluginManager; -//import org.nwapw.abacus.plugin.StandardPlugin; -import org.nwapw.abacus.plugin.StandardPlugin; -import org.nwapw.abacus.window.Window; +import org.nwapw.abacus.function.Operator; +import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.plugin.ClassFinder; +import org.nwapw.abacus.plugin.PluginListener; +import org.nwapw.abacus.plugin.PluginManager; +import org.nwapw.abacus.plugin.StandardPlugin; +import org.nwapw.abacus.tree.NumberReducer; +import org.nwapw.abacus.tree.TreeBuilder; +import org.nwapw.abacus.tree.TreeNode; +import org.nwapw.abacus.window.Window; import javax.swing.*; import java.io.IOException; -import java.util.ArrayList; -public class Abacus { +/** + * The main calculator class. This is responsible + * for piecing together all of the components, allowing + * their interaction with each other. + */ +public class Abacus implements PluginListener { + /** + * The main Abacus UI. + */ private Window mainUi; - private PluginManager manager; + /** + * The plugin manager responsible for + * loading and unloading plugins, + * and getting functions from them. + */ + private PluginManager pluginManager; + /** + * Tree builder built from plugin manager, + * used to construct parse trees. + */ + private TreeBuilder treeBuilder; + /** + * The reducer used to evaluate the tree. + */ + private NumberReducer numberReducer; + /** + * Creates a new instance of the Abacus calculator. + */ public Abacus(){ - init(); + pluginManager = new PluginManager(this); + mainUi = new Window(this); + numberReducer = new NumberReducer(this); + + pluginManager.addListener(this); + pluginManager.addInstantiated(new StandardPlugin(pluginManager)); + try { + ClassFinder.loadJars("plugins") + .forEach(plugin -> pluginManager.addClass(plugin)); + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + pluginManager.load(); + + mainUi.setVisible(true); } - private void init() { + /** + * Gets the current tree builder. + * @return the main tree builder in this abacus instance. + */ + public TreeBuilder getTreeBuilder() { + return treeBuilder; + } + + /** + * Gets the current plugin manager, + * @return the plugin manager in this abacus instance. + */ + public PluginManager getPluginManager() { + return pluginManager; + } + + /** + * Gets the current UI. + * @return the UI window in this abacus instance. + */ + public Window getMainUi() { + return mainUi; + } + + /** + * Get the reducer that is responsible for transforming + * an expression into a number. + * @return the number reducer in this abacus instance. + */ + public NumberReducer getNumberReducer() { + return numberReducer; + } + + /** + * Parses a string into a tree structure using the main + * tree builder. + * @param input the input string to parse + * @return the resulting tree, null if the tree builder or the produced tree are null. + */ + public TreeNode parseString(String input){ + if(treeBuilder == null) return null; + return treeBuilder.fromString(input); + } + + /** + * Evaluates the given tree using the main + * number reducer. + * @param tree the tree to reduce, must not be null. + * @return the resulting number, or null of the reduction failed. + */ + public NumberInterface evaluateTree(TreeNode tree){ + return tree.reduce(numberReducer); + } + + @Override + public void onLoad(PluginManager manager) { + treeBuilder = new TreeBuilder(); + for(String function : manager.getAllFunctions()){ + treeBuilder.registerFunction(function); + } + for(String operator : manager.getAllOperators()){ + Operator operatorObject = manager.operatorFor(operator); + treeBuilder.registerOperator(operator, + operatorObject.getAssociativity(), + operatorObject.getType(), + operatorObject.getPrecedence()); + } + } + + @Override + public void onUnload(PluginManager manager) { + treeBuilder = null; + } + + public static void main(String[] args){ try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | UnsupportedLookAndFeelException | IllegalAccessException e) { e.printStackTrace(); } - manager = new PluginManager(); - manager.addInstantiated(new StandardPlugin(manager)); - try { - ClassFinder.loadJars("plugins") - .forEach(plugin -> manager.addClass(plugin)); - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - mainUi = new Window(manager); - mainUi.setVisible(true); - manager.load(); - } - - public static void main(String[] args){ new Abacus(); } - } diff --git a/src/org/nwapw/abacus/plugin/PluginManager.java b/src/org/nwapw/abacus/plugin/PluginManager.java index 8bb3879..25e3aac 100644 --- a/src/org/nwapw/abacus/plugin/PluginManager.java +++ b/src/org/nwapw/abacus/plugin/PluginManager.java @@ -1,5 +1,6 @@ package org.nwapw.abacus.plugin; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.Function; import org.nwapw.abacus.function.Operator; @@ -42,11 +43,17 @@ public class PluginManager { * The list of plugin listeners attached to this instance. */ private Set listeners; + /** + * The instance of Abacus that is used to interact with its other + * components. + */ + private Abacus abacus; /** * Creates a new plugin manager. */ - public PluginManager(){ + public PluginManager(Abacus abacus){ + this.abacus = abacus; loadedPluginClasses = new HashSet<>(); plugins = new HashSet<>(); cachedFunctions = new HashMap<>(); diff --git a/src/org/nwapw/abacus/tree/NumberReducer.java b/src/org/nwapw/abacus/tree/NumberReducer.java index bb10a5e..6fcff47 100644 --- a/src/org/nwapw/abacus/tree/NumberReducer.java +++ b/src/org/nwapw/abacus/tree/NumberReducer.java @@ -1,8 +1,8 @@ package org.nwapw.abacus.tree; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.Function; import org.nwapw.abacus.number.NumberInterface; -import org.nwapw.abacus.plugin.PluginManager; /** * A reducer implementation that turns a tree into a single number. @@ -13,14 +13,14 @@ public class NumberReducer implements Reducer { /** * The plugin manager from which to draw the functions. */ - private PluginManager manager; + private Abacus abacus; /** - * Creates a new number reducer with the given plugin manager. - * @param manager the plugin manager. + * Creates a new number reducer. + * @param abacus the calculator instance. */ - public NumberReducer(PluginManager manager){ - this.manager = manager; + public NumberReducer(Abacus abacus){ + this.abacus = abacus; } @Override @@ -30,12 +30,12 @@ public class NumberReducer implements Reducer { } else if(node instanceof BinaryInfixNode){ NumberInterface left = (NumberInterface) children[0]; NumberInterface right = (NumberInterface) children[1]; - Function function = manager.operatorFor(((BinaryInfixNode) node).getOperation()).getFunction(); + Function function = abacus.getPluginManager().operatorFor(((BinaryInfixNode) node).getOperation()).getFunction(); if(function == null) return null; return function.apply(left, right); } else if(node instanceof UnaryPrefixNode) { NumberInterface child = (NumberInterface) children[0]; - Function functionn = manager.operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction(); + Function functionn = abacus.getPluginManager().operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction(); if(functionn == null) return null; return functionn.apply(child); } else if(node instanceof FunctionNode){ @@ -43,7 +43,7 @@ public class NumberReducer implements Reducer { for(int i = 0; i < convertedChildren.length; i++){ convertedChildren[i] = (NumberInterface) children[i]; } - Function function = manager.functionFor(((FunctionNode) node).getFunction()); + Function function = abacus.getPluginManager().functionFor(((FunctionNode) node).getFunction()); if(function == null) return null; return function.apply(convertedChildren); } diff --git a/src/org/nwapw/abacus/window/Window.java b/src/org/nwapw/abacus/window/Window.java index 0e7a95e..0484cf2 100644 --- a/src/org/nwapw/abacus/window/Window.java +++ b/src/org/nwapw/abacus/window/Window.java @@ -1,11 +1,7 @@ package org.nwapw.abacus.window; -import org.nwapw.abacus.function.Operator; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.number.NumberInterface; -import org.nwapw.abacus.plugin.PluginListener; -import org.nwapw.abacus.plugin.PluginManager; -import org.nwapw.abacus.tree.NumberReducer; -import org.nwapw.abacus.tree.TreeBuilder; import org.nwapw.abacus.tree.TreeNode; import javax.swing.*; @@ -18,7 +14,7 @@ import java.awt.event.MouseEvent; /** * The main UI window for the calculator. */ -public class Window extends JFrame implements PluginListener { +public class Window extends JFrame { private static final String CALC_STRING = "Calculate"; private static final String SYNTAX_ERR_STRING = "Syntax Error"; @@ -47,18 +43,10 @@ public class Window extends JFrame implements PluginListener { }; /** - * The plugin manager used to retrieve functions. + * The instance of the Abacus class, used + * for interaction with plugins and configuration. */ - private PluginManager manager; - /** - * The builder used to construct the parse trees. - */ - private TreeBuilder builder; - /** - * The reducer used to evaluate the tree. - */ - private NumberReducer reducer; - + private Abacus abacus; /** * The last output by the calculator. */ @@ -130,15 +118,14 @@ public class Window extends JFrame implements PluginListener { * Action listener that causes the input to be evaluated. */ private ActionListener evaluateListener = (event) -> { - if(builder == null) return; - TreeNode parsedExpression = builder.fromString(inputField.getText()); + TreeNode parsedExpression = abacus.parseString(inputField.getText()); if(parsedExpression == null){ lastOutputArea.setText(SYNTAX_ERR_STRING); return; } - NumberInterface numberInterface = parsedExpression.reduce(reducer); - if(numberInterface == null){ - lastOutputArea.setText(EVAL_ERR_STRING);; + NumberInterface numberInterface = abacus.evaluateTree(parsedExpression); + if(numberInterface == null) { + lastOutputArea.setText(EVAL_ERR_STRING); return; } lastOutput = numberInterface.toString(); @@ -159,13 +146,11 @@ public class Window extends JFrame implements PluginListener { /** * Creates a new window with the given manager. - * @param manager the manager to use. + * @param abacus the calculator instance to interact with other components. */ - public Window(PluginManager manager){ + public Window(Abacus abacus){ this(); - this.manager = manager; - manager.addListener(this); - reducer = new NumberReducer(manager); + this.abacus = abacus; } /** @@ -261,23 +246,4 @@ public class Window extends JFrame implements PluginListener { }); } - @Override - public void onLoad(PluginManager manager) { - builder = new TreeBuilder(); - for(String function : manager.getAllFunctions()){ - builder.registerFunction(function); - } - for(String operator : manager.getAllOperators()){ - Operator operatorObject = manager.operatorFor(operator); - builder.registerOperator(operator, - operatorObject.getAssociativity(), - operatorObject.getType(), - operatorObject.getPrecedence()); - } - } - - @Override - public void onUnload(PluginManager manager) { - builder = null; - } }