some refactorings

This commit is contained in:
hneemann 2020-06-09 13:18:39 +02:00
parent f6ddd29682
commit e33812e4e3
17 changed files with 193 additions and 42 deletions

View File

@ -4,8 +4,8 @@
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
import de.neemann.digital.cli.CLIException; import de.neemann.digital.cli.cli.CLIException;
import de.neemann.digital.cli.Muxer; import de.neemann.digital.cli.cli.Muxer;
/** /**
* Entry point for the CLI interface * Entry point for the CLI interface

View File

@ -5,6 +5,9 @@
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli;
import de.neemann.digital.cli.cli.Argument;
import de.neemann.digital.cli.cli.BasicCommand;
import de.neemann.digital.cli.cli.CLIException;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import de.neemann.digital.testing.CommandLineTester; import de.neemann.digital.testing.CommandLineTester;
@ -12,9 +15,9 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
/** /**
* Used to test circuits * Used to test circuits.
*/ */
public class CLITester extends SimpleCommand { public class CLITester extends BasicCommand {
private final Argument<String> circ; private final Argument<String> circ;
private final Argument<String> test; private final Argument<String> test;

View File

@ -5,6 +5,10 @@
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli;
import de.neemann.digital.cli.cli.Argument;
import de.neemann.digital.cli.cli.ArgumentKey;
import de.neemann.digital.cli.cli.BasicCommand;
import de.neemann.digital.cli.cli.CLIException;
import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Key; import de.neemann.digital.core.element.Key;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
@ -23,7 +27,7 @@ import java.io.OutputStream;
/** /**
* CLI svg exporter * CLI svg exporter
*/ */
public class SVGExport extends SimpleCommand { public class SVGExport extends BasicCommand {
private final ElementAttributes attr; private final ElementAttributes attr;
private final Argument<String> digFile; private final Argument<String> digFile;
private final Argument<String> svgFile; private final Argument<String> svgFile;

View File

@ -5,6 +5,9 @@
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli;
import de.neemann.digital.cli.cli.Argument;
import de.neemann.digital.cli.cli.BasicCommand;
import de.neemann.digital.cli.cli.CLIException;
import de.neemann.digital.core.Model; import de.neemann.digital.core.Model;
import de.neemann.digital.core.NodeException; import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.stats.Statistics; import de.neemann.digital.core.stats.Statistics;
@ -21,7 +24,7 @@ import java.io.*;
/** /**
* CLI stats exporter * CLI stats exporter
*/ */
public class StatsExport extends SimpleCommand { public class StatsExport extends BasicCommand {
private final Argument<String> digFile; private final Argument<String> digFile;
private final Argument<String> csvFile; private final Argument<String> csvFile;
@ -46,13 +49,12 @@ public class StatsExport extends SimpleCommand {
Model model = new ModelCreator(circuit, library).createModel(false); Model model = new ModelCreator(circuit, library).createModel(false);
Statistics stats = new Statistics(model); Statistics stats = new Statistics(model);
String outName; BufferedWriter writer;
if (csvFile.isSet()) if (csvFile.isSet())
outName = csvFile.get(); writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile.get())));
else else
outName = digFile.get() + ".csv"; writer = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outName)));
new CSVWriter(stats.getTableModel()).writeTo(writer); new CSVWriter(stats.getTableModel()).writeTo(writer);
} catch (IOException | ElementNotFoundException | PinException | NodeException e) { } catch (IOException | ElementNotFoundException | PinException | NodeException e) {

View File

@ -3,7 +3,7 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;

View File

@ -3,7 +3,7 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
/** /**
* The base class of all arguments * The base class of all arguments

View File

@ -3,7 +3,7 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Key; import de.neemann.digital.core.element.Key;

View File

@ -3,7 +3,7 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
@ -13,10 +13,9 @@ import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
/** /**
* E simple executable command * A simple executable command
*/ */
public abstract class SimpleCommand implements CLICommand { public abstract class BasicCommand extends NamedCommand {
private final String name;
private final ArrayList<ArgumentBase<?>> arguments; private final ArrayList<ArgumentBase<?>> arguments;
/** /**
@ -24,8 +23,8 @@ public abstract class SimpleCommand implements CLICommand {
* *
* @param name the name of the command * @param name the name of the command
*/ */
public SimpleCommand(String name) { public BasicCommand(String name) {
this.name = name; super(name);
arguments = new ArrayList<>(); arguments = new ArrayList<>();
} }
@ -42,17 +41,10 @@ public abstract class SimpleCommand implements CLICommand {
return argument; return argument;
} }
/**
* @return the name of the argument
*/
public String getName() {
return name;
}
@Override @Override
public void printDescription(PrintStream out, String prefix) { public void printDescription(PrintStream out, String prefix) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(name); sb.append(getName());
for (ArgumentBase<?> a : arguments) { for (ArgumentBase<?> a : arguments) {
sb.append(" "); sb.append(" ");
sb.append(a); sb.append(a);
@ -63,7 +55,7 @@ public abstract class SimpleCommand implements CLICommand {
prefix += " "; prefix += " ";
out.print(prefix + " "); out.print(prefix + " ");
printString(out, prefix + " ", Lang.get("cli_help_" + name)); printString(out, prefix + " ", Lang.get("cli_help_" + getName()));
out.print(prefix); out.print(prefix);
out.println(Lang.get("cli_options")); out.println(Lang.get("cli_options"));
@ -71,7 +63,7 @@ public abstract class SimpleCommand implements CLICommand {
for (ArgumentBase<?> a : arguments) { for (ArgumentBase<?> a : arguments) {
out.println(prefix + " " + a.toStringDef()); out.println(prefix + " " + a.toStringDef());
out.print(prefix + " "); out.print(prefix + " ");
printString(out, prefix + " ", a.getDescription(name)); printString(out, prefix + " ", a.getDescription(getName()));
} }
} }

View File

@ -3,7 +3,7 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
import java.io.PrintStream; import java.io.PrintStream;

View File

@ -3,7 +3,7 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
import java.io.PrintStream; import java.io.PrintStream;
@ -43,7 +43,7 @@ public class CLIException extends Exception {
} }
/** /**
* Pronts a error message to the stream * Prints a error message to the stream
* *
* @param out the print stream * @param out the print stream
*/ */

View File

@ -3,8 +3,11 @@
* Use of this source code is governed by the GPL v3 license * Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli.cli;
import de.neemann.digital.cli.CLITester;
import de.neemann.digital.cli.SVGExport;
import de.neemann.digital.cli.StatsExport;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import java.io.PrintStream; import java.io.PrintStream;
@ -14,7 +17,7 @@ import java.util.HashMap;
/** /**
* The command muxer * The command muxer
*/ */
public class Muxer implements CLICommand { public class Muxer extends NamedCommand {
/** /**
* The main muxer * The main muxer
*/ */
@ -24,7 +27,6 @@ public class Muxer implements CLICommand {
.addCommand(new StatsExport()); .addCommand(new StatsExport());
private final HashMap<String, CLICommand> commands; private final HashMap<String, CLICommand> commands;
private final String name;
private Muxer() { private Muxer() {
this("java -cp Digital.jar CLI"); this("java -cp Digital.jar CLI");
@ -36,7 +38,7 @@ public class Muxer implements CLICommand {
* @param name the name of the muxer * @param name the name of the muxer
*/ */
public Muxer(String name) { public Muxer(String name) {
this.name = name; super(name);
this.commands = new HashMap<>(); this.commands = new HashMap<>();
} }
@ -46,7 +48,7 @@ public class Muxer implements CLICommand {
* @param command the command * @param command the command
* @return this for chained calls * @return this for chained calls
*/ */
public Muxer addCommand(SimpleCommand command) { public Muxer addCommand(NamedCommand command) {
return addCommand(command.getName(), command); return addCommand(command.getName(), command);
} }
@ -65,7 +67,7 @@ public class Muxer implements CLICommand {
@Override @Override
public void printDescription(PrintStream out, String prefix) { public void printDescription(PrintStream out, String prefix) {
out.print(prefix); out.print(prefix);
out.print(name); out.print(getName());
out.println(); out.println();
for (CLICommand c : commands.values()) for (CLICommand c : commands.values())
c.printDescription(out, prefix + " "); c.printDescription(out, prefix + " ");
@ -78,7 +80,7 @@ public class Muxer implements CLICommand {
CLICommand command = commands.get(args[0]); CLICommand command = commands.get(args[0]);
if (command == null) if (command == null)
throw new CLIException(Lang.get("cli_command_N_hasNoSubCommand_N", name, args[0]), 101); throw new CLIException(Lang.get("cli_command_N_hasNoSubCommand_N", getName(), args[0]), 101);
command.execute(Arrays.copyOfRange(args, 1, args.length)); command.execute(Arrays.copyOfRange(args, 1, args.length));
} }

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.cli.cli;
/**
* The base class of all named commands
*/
public abstract class NamedCommand implements CLICommand {
private final String name;
/**
* Create a new instance
*
* @param name the name of the command
*/
public NamedCommand(String name) {
this.name = name;
}
/**
* @return the name of the command
*/
public String getName() {
return name;
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2020 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
/**
* The classes needed to implement the command line interface
*/
package de.neemann.digital.cli.cli;

View File

@ -28,7 +28,7 @@ public class CommandLineTester {
private final ElementLibrary library; private final ElementLibrary library;
private final ShapeFactory shapeFactory; private final ShapeFactory shapeFactory;
private Circuit circuit; private final Circuit circuit;
private PrintStream out = System.out; private PrintStream out = System.out;
private ArrayList<TestCase> testCases; private ArrayList<TestCase> testCases;
private int testsPassed; private int testsPassed;

View File

@ -5,6 +5,8 @@
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli;
import de.neemann.digital.cli.cli.Argument;
import de.neemann.digital.cli.cli.CLIException;
import junit.framework.TestCase; import junit.framework.TestCase;
public class ArgumentTest extends TestCase { public class ArgumentTest extends TestCase {
@ -39,6 +41,14 @@ public class ArgumentTest extends TestCase {
} }
} }
public void testToggle() throws CLIException {
Argument<Boolean> a = new Argument<>("flag", false, false);
assertTrue(a.isBool());
assertFalse(a.get());
a.toggle();
assertTrue(a.get());
}
public void testInteger() throws CLIException { public void testInteger() throws CLIException {
Argument<Integer> a = new Argument<>("n", 2, false); Argument<Integer> a = new Argument<>("n", 2, false);
assertEquals(2, (int) a.get()); assertEquals(2, (int) a.get());

View File

@ -5,11 +5,14 @@
*/ */
package de.neemann.digital.cli; package de.neemann.digital.cli;
import de.neemann.digital.cli.cli.Argument;
import de.neemann.digital.cli.cli.BasicCommand;
import de.neemann.digital.cli.cli.CLIException;
import junit.framework.TestCase; import junit.framework.TestCase;
public class SimpleCommandTest extends TestCase { public class BasicCommandTest extends TestCase {
private static class TestCommand extends SimpleCommand { private static class TestCommand extends BasicCommand {
private boolean wasExecuted; private boolean wasExecuted;
private TestCommand() { private TestCommand() {

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2020 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.cli;
import de.neemann.digital.cli.cli.Argument;
import de.neemann.digital.cli.cli.BasicCommand;
import de.neemann.digital.cli.cli.CLIException;
import de.neemann.digital.cli.cli.Muxer;
import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class MuxerTest extends TestCase {
/**
* Creates the documentation.
* Used to make the maven build fail, if a language key is missing.
*/
public void testDocu() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Muxer.MAIN_MUXER.printDescription(new PrintStream(baos), "");
assertTrue(baos.toByteArray().length > 100);
}
public void testErrors() throws CLIException {
TestCommand tc = new TestCommand();
Muxer m = new Muxer("test").addCommand(tc);
try {
m.execute(new String[]{"add"});
fail();
} catch (CLIException e) {
assertTrue(true);
}
m.execute(new String[]{"add", "-arg", "zz"});
assertEquals("zz", tc.arg.get());
try {
m.execute(new String[]{"add", "-foo", "zz"});
fail();
} catch (CLIException e) {
assertTrue(true);
}
try {
m.execute(new String[]{"sub"});
fail();
} catch (CLIException e) {
assertTrue(true);
}
try {
m.execute(new String[]{});
fail();
} catch (CLIException e) {
assertTrue(true);
}
}
public void testNesting() throws CLIException {
TestCommand tc = new TestCommand();
Muxer m = new Muxer("main")
.addCommand(new Muxer("arith")
.addCommand(tc));
m.execute(new String[]{"arith", "add", "-arg", "tt"});
assertTrue(tc.wasExecuted);
}
private static class TestCommand extends BasicCommand {
private final Argument<String> arg;
private boolean wasExecuted = false;
public TestCommand() {
super("add");
arg = addArgument(new Argument<>("arg", "def", false));
}
@Override
public void printDescription(PrintStream out, String prefix) {
}
@Override
protected void execute() throws CLIException {
wasExecuted = true;
}
}
}