Skip to content

Commit 89ca871

Browse files
committed
Centralize command dispatch map
Replace the command switch with an immutable command-to-handler map to simplify routing and make command registration easier to maintain. Bump the CLI project version and codecmedia dependency to 1.1.1 to align with the updated release.
1 parent 79deecd commit 89ca871

3 files changed

Lines changed: 132 additions & 18 deletions

File tree

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<groupId>me.tamkungz.codecmedia</groupId>
99
<artifactId>codecmedia-cli</artifactId>
10-
<version>1.1.0</version>
10+
<version>1.1.1</version>
1111
<packaging>jar</packaging>
1212

1313
<name>CodecMedia CLI</name>
@@ -90,7 +90,7 @@
9090
<dependency>
9191
<groupId>me.tamkungz.codecmedia</groupId>
9292
<artifactId>codecmedia</artifactId>
93-
<version>1.1.0</version>
93+
<version>1.1.1</version>
9494
</dependency>
9595

9696
<dependency>

src/main/java/me/tamkungz/codecmedia/CodecMediaCli.java

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.io.PrintStream;
44
import java.nio.file.Path;
5+
import java.util.Collections;
6+
import java.util.HashMap;
57
import java.util.LinkedHashMap;
68
import java.util.Locale;
79
import java.util.Map;
@@ -37,6 +39,13 @@
3739
*/
3840
public final class CodecMediaCli {
3941

42+
@FunctionalInterface
43+
private interface CommandHandler {
44+
int handle(CodecMediaEngine engine, String[] args, PrintStream out) throws CodecMediaException;
45+
}
46+
47+
private static final Map<String, CommandHandler> COMMANDS = createCommands();
48+
4049
private CodecMediaCli() {
4150
}
4251

@@ -83,21 +92,13 @@ static int run(String[] args, PrintStream out, PrintStream err) {
8392
String command = args[0].toLowerCase(Locale.ROOT);
8493
CodecMediaEngine engine = CodecMedia.createDefault();
8594

86-
return switch (command) {
87-
case "get" -> handleGet(engine, args, out);
88-
case "probe" -> handleProbe(engine, args, out);
89-
case "validate" -> handleValidate(engine, args, out);
90-
case "convert" -> handleConvert(engine, args, out);
91-
case "extract-audio" -> handleExtractAudio(engine, args, out);
92-
case "play" -> handlePlay(engine, args, out);
93-
case "read-metadata" -> handleReadMetadata(engine, args, out);
94-
case "write-metadata" -> handleWriteMetadata(engine, args, out);
95-
default -> {
96-
err.println("Unknown command: " + command);
97-
printUsage(err);
98-
yield 2;
99-
}
100-
};
95+
CommandHandler handler = COMMANDS.get(command);
96+
if (handler == null) {
97+
err.println("Unknown command: " + command);
98+
printUsage(err);
99+
return 2;
100+
}
101+
return handler.handle(engine, args, out);
101102
} catch (IllegalArgumentException ex) {
102103
err.println("Invalid arguments: " + ex.getMessage());
103104
return 2;
@@ -110,6 +111,19 @@ static int run(String[] args, PrintStream out, PrintStream err) {
110111
}
111112
}
112113

114+
private static Map<String, CommandHandler> createCommands() {
115+
Map<String, CommandHandler> handlers = new HashMap<>();
116+
handlers.put("get", CodecMediaCli::handleGet);
117+
handlers.put("probe", CodecMediaCli::handleProbe);
118+
handlers.put("validate", CodecMediaCli::handleValidate);
119+
handlers.put("convert", CodecMediaCli::handleConvert);
120+
handlers.put("extract-audio", CodecMediaCli::handleExtractAudio);
121+
handlers.put("play", CodecMediaCli::handlePlay);
122+
handlers.put("read-metadata", CodecMediaCli::handleReadMetadata);
123+
handlers.put("write-metadata", CodecMediaCli::handleWriteMetadata);
124+
return Collections.unmodifiableMap(handlers);
125+
}
126+
113127
/**
114128
* Handles the {@code get} command.
115129
*
@@ -543,4 +557,4 @@ private static void printUsage(PrintStream out) {
543557
out.println(" read-metadata <input>");
544558
out.println(" write-metadata <input> --entry <key=value> [--entry <key=value> ...]");
545559
}
546-
}
560+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package me.tamkungz.codecmedia;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import java.io.ByteArrayOutputStream;
7+
import java.io.PrintStream;
8+
import java.nio.charset.StandardCharsets;
9+
10+
import org.junit.jupiter.api.Test;
11+
12+
class CodecMediaCliTest {
13+
14+
@Test
15+
void shouldPrintUsageWhenNoArgs() {
16+
RunResult result = runCli(new String[0]);
17+
18+
assertEquals(0, result.code());
19+
assertTrue(result.out().contains("CodecMedia CLI"));
20+
assertTrue(result.out().contains("Usage:"));
21+
}
22+
23+
@Test
24+
void shouldReturnCode2ForUnknownCommand() {
25+
RunResult result = runCli(new String[] {"unknown-cmd"});
26+
27+
assertEquals(2, result.code());
28+
assertTrue(result.err().contains("Unknown command: unknown-cmd"));
29+
}
30+
31+
@Test
32+
void shouldReturnCode2WhenValidateMaxBytesValueMissing() {
33+
RunResult result = runCli(new String[] {"validate", "file.mp3", "--max-bytes"});
34+
35+
assertEquals(2, result.code());
36+
assertTrue(result.err().contains("--max-bytes requires a numeric value"));
37+
}
38+
39+
@Test
40+
void shouldReturnCode2WhenValidateMaxBytesNotNumeric() {
41+
RunResult result = runCli(new String[] {"validate", "file.mp3", "--max-bytes", "abc"});
42+
43+
assertEquals(2, result.code());
44+
assertTrue(result.err().contains("--max-bytes must be a long integer: abc"));
45+
}
46+
47+
@Test
48+
void shouldReturnCode2WhenConvertTargetFormatMissing() {
49+
RunResult result = runCli(new String[] {"convert", "input.media", "output"});
50+
51+
assertEquals(2, result.code());
52+
assertTrue(result.err().contains("Target format missing"));
53+
}
54+
55+
@Test
56+
void shouldReturnCode2WhenExtractAudioHasUnknownOption() {
57+
RunResult result = runCli(new String[] {"extract-audio", "input.mp4", "out", "--bad-option"});
58+
59+
assertEquals(2, result.code());
60+
assertTrue(result.err().contains("Unknown option for extract-audio: --bad-option"));
61+
}
62+
63+
@Test
64+
void shouldReturnCode2WhenWriteMetadataEntryMalformed() {
65+
RunResult result = runCli(new String[] {"write-metadata", "in.mp3", "--entry", "bad"});
66+
67+
assertEquals(2, result.code());
68+
assertTrue(result.err().contains("Invalid --entry value: bad"));
69+
}
70+
71+
@Test
72+
void shouldReturnCode2WhenWriteMetadataEntryValueMissing() {
73+
RunResult result = runCli(new String[] {"write-metadata", "in.mp3", "--entry"});
74+
75+
assertEquals(2, result.code());
76+
assertTrue(result.err().contains("Usage: write-metadata"));
77+
}
78+
79+
@Test
80+
void shouldReturnCode2WhenPlayHasUnknownOption() {
81+
RunResult result = runCli(new String[] {"play", "song.mp3", "--nope"});
82+
83+
assertEquals(2, result.code());
84+
assertTrue(result.err().contains("Unknown option for play: --nope"));
85+
}
86+
87+
private static RunResult runCli(String[] args) {
88+
ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
89+
ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
90+
int code = CodecMediaCli.run(args, new PrintStream(outBuffer), new PrintStream(errBuffer));
91+
return new RunResult(
92+
code,
93+
outBuffer.toString(StandardCharsets.UTF_8),
94+
errBuffer.toString(StandardCharsets.UTF_8)
95+
);
96+
}
97+
98+
private record RunResult(int code, String out, String err) {
99+
}
100+
}

0 commit comments

Comments
 (0)