Skip to content

Commit 3261c1b

Browse files
committed
Can now run basic commands without parameters
1 parent f07790e commit 3261c1b

File tree

6 files changed

+102
-16
lines changed

6 files changed

+102
-16
lines changed

src/main/java/fr/zcraft/quartzlib/components/commands/internal/CommandEndpoint.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
package fr.zcraft.quartzlib.components.commands.internal;
22

3+
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
4+
35
import java.util.ArrayList;
46
import java.util.List;
57

68
class CommandEndpoint extends CommandNode {
79
private final List<CommandMethod> methods = new ArrayList<>();
810

911
CommandEndpoint(String name) {
10-
super(name);
12+
super(name, null);
13+
}
14+
15+
@Override
16+
void run(Object instance, String[] args) {
17+
this.methods.get(0).run(instance, args);
1118
}
1219

1320
void addMethod(CommandMethod method) {

src/main/java/fr/zcraft/quartzlib/components/commands/internal/CommandGroup.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,23 @@
33
import java.util.Arrays;
44
import java.util.HashMap;
55
import java.util.Map;
6-
import java.util.stream.Stream;
6+
import java.util.function.Supplier;
77

88
class CommandGroup extends CommandNode {
99
private final Class<?> commandGroupClass;
10-
private final CommandGroup parent;
10+
private final Supplier<?> classInstanceSupplier;
1111

1212
private final Map<String, CommandNode> subCommands = new HashMap<>();
1313

14-
public CommandGroup(Class<?> commandGroupClass, String name) {
15-
super(name);
16-
this.commandGroupClass = commandGroupClass;
17-
this.parent = null;
18-
getCommandMethods(commandGroupClass).forEach(this::addMethod);
14+
public CommandGroup(Class<?> commandGroupClass, Supplier<?> classInstanceSupplier, String name) {
15+
this(commandGroupClass, classInstanceSupplier, name, null);
1916
}
2017

21-
public CommandGroup(Class<?> commandGroupClass, String name, CommandGroup parent) {
22-
super(name);
18+
public CommandGroup(Class<?> commandGroupClass, Supplier<?> classInstanceSupplier, String name, CommandGroup parent) {
19+
super(name, parent);
2320
this.commandGroupClass = commandGroupClass;
24-
this.parent = parent;
21+
this.classInstanceSupplier = classInstanceSupplier;
22+
DiscoveryUtils.getCommandMethods(commandGroupClass).forEach(this::addMethod);
2523
}
2624

2725
public Iterable<CommandNode> getSubCommands () {
@@ -39,9 +37,15 @@ private void addMethod(CommandMethod method) {
3937
endpoint.addMethod(method);
4038
}
4139

42-
// Private utils TODO: move to DiscoveryUtils?
40+
void run(String... args) {
41+
Object commandObject = classInstanceSupplier.get();
42+
run(commandObject, args);
43+
}
4344

44-
private static Stream<CommandMethod> getCommandMethods(Class<?> commandGroupClass) {
45-
return Arrays.stream(commandGroupClass.getDeclaredMethods()).map(CommandMethod::new);
45+
@Override
46+
void run(Object instance, String[] args) {
47+
String commandName = args[0];
48+
CommandNode subCommand = subCommands.get(commandName);
49+
subCommand.run(instance, Arrays.copyOfRange(args, 1, args.length));
4650
}
4751
}

src/main/java/fr/zcraft/quartzlib/components/commands/internal/CommandMethod.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.zcraft.quartzlib.components.commands.internal;
22

3+
import java.lang.reflect.InvocationTargetException;
34
import java.lang.reflect.Method;
45

56
class CommandMethod {
@@ -14,4 +15,12 @@ class CommandMethod {
1415
public String getName() {
1516
return name;
1617
}
18+
19+
public void run(Object target, String[] args) {
20+
try {
21+
this.method.invoke(target, (Object[]) args);
22+
} catch (IllegalAccessException | InvocationTargetException e) {
23+
e.printStackTrace(); // TODO
24+
}
25+
}
1726
}

src/main/java/fr/zcraft/quartzlib/components/commands/internal/CommandNode.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@
22

33
abstract class CommandNode {
44
private final String name;
5+
private final CommandGroup parent;
56

6-
protected CommandNode(String name) {
7+
protected CommandNode(String name, CommandGroup parent) {
78
this.name = name;
9+
this.parent = parent;
810
}
911

1012
public String getName() {
1113
return name;
1214
}
15+
16+
public CommandGroup getParent() {
17+
return parent;
18+
}
19+
20+
abstract void run(Object instance, String[] args);
1321
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package fr.zcraft.quartzlib.components.commands.internal;
2+
3+
import java.lang.reflect.Constructor;
4+
import java.lang.reflect.InvocationTargetException;
5+
import java.lang.reflect.Modifier;
6+
import java.util.Arrays;
7+
import java.util.function.Supplier;
8+
import java.util.stream.Stream;
9+
10+
abstract class DiscoveryUtils {
11+
public static Stream<CommandMethod> getCommandMethods(Class<?> commandGroupClass) {
12+
return Arrays.stream(commandGroupClass.getDeclaredMethods())
13+
.filter(m -> Modifier.isPublic(m.getModifiers()) && !Modifier.isStatic(m.getModifiers()))
14+
.map(CommandMethod::new);
15+
}
16+
17+
public static Supplier<?> getClassConstructorSupplier (Class<?> commandGroupClass) {
18+
Constructor<?> constructor = commandGroupClass.getDeclaredConstructors()[0];
19+
return () -> {
20+
try {
21+
return constructor.newInstance();
22+
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
23+
throw new RuntimeException(e); // TODO
24+
}
25+
};
26+
}
27+
}

src/test/java/fr/zcraft/quartzlib/components/commands/internal/CommandGraphTests.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55

66
import java.util.stream.StreamSupport;
77

8+
// This is outside because inner classes cannot have statics
9+
class CommandWithStatics {
10+
public void add () {}
11+
private void get () {}
12+
protected void list () {}
13+
public void delete () {}
14+
void update () {}
15+
static public void staticMethod () {}
16+
}
17+
818
public class CommandGraphTests {
919
@Test public void canDiscoverBasicSubcommands() {
1020
class FooCommand {
@@ -13,8 +23,29 @@ public void get () {}
1323
public void list () {}
1424
}
1525

16-
CommandGroup commandGroup = new CommandGroup(FooCommand.class, "foo");
26+
CommandGroup commandGroup = new CommandGroup(FooCommand.class, () -> new FooCommand(), "foo");
1727
String[] commandNames = StreamSupport.stream(commandGroup.getSubCommands().spliterator(), false).map(CommandNode::getName).toArray(String[]::new);
1828
Assertions.assertArrayEquals(new String[] {"add", "get", "list"}, commandNames);
1929
}
30+
31+
@Test public void onlyDiscoversPublicMethods() {
32+
CommandGroup commandGroup = new CommandGroup(CommandWithStatics.class, () -> new CommandWithStatics(), "foo");
33+
String[] commandNames = StreamSupport.stream(commandGroup.getSubCommands().spliterator(), false).map(CommandNode::getName).toArray(String[]::new);
34+
Assertions.assertArrayEquals(new String[] {"add", "delete"}, commandNames);
35+
}
36+
37+
@Test public void canRunBasicSubcommands() {
38+
final boolean[] ran = {false, false, false};
39+
40+
class FooCommand {
41+
public void add () { ran[0] = true; }
42+
public void get () { ran[1] = true; }
43+
public void list () { ran[2] = true; }
44+
}
45+
46+
FooCommand f = new FooCommand();
47+
CommandGroup commandGroup = new CommandGroup(FooCommand.class, () -> new FooCommand(),"foo");
48+
commandGroup.run("get");
49+
Assertions.assertArrayEquals(new boolean[] { false, true, false }, ran);
50+
}
2051
}

0 commit comments

Comments
 (0)