44
55import java .nio .file .Path ;
66import java .time .ZonedDateTime ;
7- import java .util .ArrayList ;
87import java .util .List ;
8+ import java .util .Optional ;
99import java .util .Scanner ;
10+ import java .util .stream .Stream ;
1011import test .api .JTest ;
1112import test .api .JTest .Test ;
1213
@@ -18,7 +19,17 @@ public static void main(String... args) {
1819 }
1920
2021 sealed interface Option {
21- record CreateArchive () implements Option {}
22+ enum Mode {
23+ CREATE ,
24+ UPDATE ,
25+ LIST ;
26+
27+ Operation toOption () {
28+ return new Operation (this );
29+ }
30+ }
31+
32+ record Operation (Mode mode ) implements Option {}
2233
2334 record File (Path jarFile ) implements Option {}
2435
@@ -34,7 +45,9 @@ record Arg(Path path) implements Option {}
3445
3546 static Option parse (String token , Scanner scanner ) {
3647 return switch (token ) {
37- case "-c" , "--create" -> new CreateArchive ();
48+ case "-c" , "--create" -> new Operation (Mode .CREATE );
49+ case "-l" , "--list" -> new Operation (Mode .LIST );
50+ case "-u" , "--update" -> new Operation (Mode .UPDATE );
3851 case "--verbose" , "-v" -> new Verbose ();
3952 case "--help" , "-h" , "-?" , "/?" -> new Help ();
4053 case "--version" -> new ShowVersionAndExit ();
@@ -47,52 +60,73 @@ static Option parse(String token, Scanner scanner) {
4760 }
4861
4962 record Options (List <Option > arguments ) {
50- static Options of (String line ) {
51- if (line .isBlank ()) return new Options (List .of ());
52- var options = new ArrayList <Option >();
63+ Options () {
64+ this (List .of ());
65+ }
66+
67+ Options add (Option option ) {
68+ if (option instanceof Option .Operation ) {
69+ if (operation ().isPresent ()) throw new IllegalStateException ("Mode already present" );
70+ }
71+ return new Options (Stream .concat (arguments .stream (), Stream .of (option )).toList ());
72+ }
73+
74+ Options parse (String line ) {
75+ if (line .isBlank ()) return this ;
5376 var delimiter = "\u0000 " ;
5477 var source = String .join (delimiter , line .split ("\\ s+" ));
5578 var scanner = new Scanner (source ).useDelimiter (delimiter );
79+ var options = this ;
5680 while (scanner .hasNext ()) {
5781 var token = scanner .next ();
5882 var parsed = Option .parse (token , scanner );
59- options .add (parsed );
83+ options = options .add (parsed );
6084 }
61- return new Options (List .copyOf (options ));
85+ return options ;
86+ }
87+
88+ Optional <Option .Operation > operation () {
89+ return arguments .stream ()
90+ .filter (Option .Operation .class ::isInstance )
91+ .map (Option .Operation .class ::cast )
92+ .findAny ();
6293 }
6394 }
6495
6596 @ Test
6697 void example1 () {
67- var options = Options . of ("--create --file classes.jar Foo.class Bar.class" );
98+ var actual = new Options (). parse ("--create --file classes.jar Foo.class Bar.class" );
6899 var expected =
69- List .of (
70- new Option .CreateArchive (),
71- new Option .File (Path .of ("classes.jar" )),
72- new Option .Arg (Path .of ("Foo.class" )),
73- new Option .Arg (Path .of ("Bar.class" )));
74- assertEquals (expected , options .arguments ());
100+ new Options (
101+ List .of (
102+ Option .Mode .CREATE .toOption (),
103+ new Option .File (Path .of ("classes.jar" )),
104+ new Option .Arg (Path .of ("Foo.class" )),
105+ new Option .Arg (Path .of ("Bar.class" ))
106+ )
107+ );
108+ assertEquals (expected , actual );
75109 }
76110
77111 @ Test
78112 void example2 () {
79- var options =
80- Options . of (
81- """
82- --create
83- --date 2021-01-06T14:36:00+02:00
84- --file classes.jar
85- Foo.class
86- Bar .class
87- """ );
88-
113+ var actual =
114+ new Options ()
115+ . parse (
116+ """
117+ --update
118+ --date 2021-01-06T14:36:00+02:00
119+ --file classes.jar
120+ Foo .class
121+ Bar.class
122+ """ );
89123 var expected =
90- List . of (
91- new Option .CreateArchive (),
92- new Option .Date (ZonedDateTime .parse ("2021-01-06T14:36:00+02:00" )),
93- new Option .File (Path .of ("classes.jar" )),
94- new Option .Arg (Path .of ("Foo.class" )),
95- new Option .Arg (Path .of ("Bar.class" )));
96- assertEquals (expected , options . arguments () );
124+ new Options ()
125+ . add ( new Option .Operation ( Option . Mode . UPDATE ))
126+ . add ( new Option .Date (ZonedDateTime .parse ("2021-01-06T14:36:00+02:00" )))
127+ . add ( new Option .File (Path .of ("classes.jar" )))
128+ . add ( new Option .Arg (Path .of ("Foo.class" )))
129+ . add ( new Option .Arg (Path .of ("Bar.class" )));
130+ assertEquals (expected , actual );
97131 }
98132}
0 commit comments