Skip to content

Commit f5041f4

Browse files
authored
feat(core): Extract interface from MappedArgumentParser (#742)
1 parent a1da6c3 commit f5041f4

3 files changed

Lines changed: 107 additions & 73 deletions

File tree

cloud-core/src/main/java/org/incendo/cloud/parser/ArgumentParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public interface ArgumentParser<C, T> extends SuggestionProviderHolder<C> {
117117
*/
118118
@API(status = API.Status.STABLE)
119119
default <O> ArgumentParser.@NonNull FutureArgumentParser<C, O> flatMap(final MappedArgumentParser.Mapper<C, T, O> mapper) {
120-
return new MappedArgumentParser<>(this, requireNonNull(mapper, "mapper"));
120+
return new MappedArgumentParserImpl<>(this, requireNonNull(mapper, "mapper"));
121121
}
122122

123123
/**

cloud-core/src/main/java/org/incendo/cloud/parser/MappedArgumentParser.java

Lines changed: 3 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@
2626
import java.util.concurrent.CompletableFuture;
2727
import org.apiguardian.api.API;
2828
import org.checkerframework.checker.nullness.qual.NonNull;
29-
import org.checkerframework.checker.nullness.qual.Nullable;
3029
import org.incendo.cloud.context.CommandContext;
31-
import org.incendo.cloud.context.CommandInput;
32-
import org.incendo.cloud.suggestion.SuggestionProvider;
33-
34-
import static java.util.Objects.requireNonNull;
3530

3631
/**
3732
* An argument parser which wraps another argument parser, converting the output type.
@@ -41,81 +36,17 @@
4136
* @param <O> mapped output type
4237
*/
4338
@API(status = API.Status.STABLE)
44-
public final class MappedArgumentParser<C, I, O> implements ArgumentParser.FutureArgumentParser<C, O> {
45-
46-
private final ArgumentParser<C, I> base;
47-
private final Mapper<C, I, O> mapper;
48-
49-
MappedArgumentParser(
50-
final ArgumentParser<C, I> base,
51-
final Mapper<C, I, O> mapper
52-
) {
53-
this.base = base;
54-
this.mapper = mapper;
55-
}
39+
public interface MappedArgumentParser<C, I, O> extends ArgumentParser<C, O> {
5640

5741
/**
5842
* Get the parser this one is derived from.
5943
*
6044
* @return the base parser
6145
*/
62-
@API(status = API.Status.STABLE)
63-
public ArgumentParser<C, I> baseParser() {
64-
return this.base;
65-
}
66-
67-
@Override
68-
public @NonNull CompletableFuture<@NonNull ArgumentParseResult<O>> parseFuture(
69-
final @NonNull CommandContext<@NonNull C> commandContext,
70-
final @NonNull CommandInput commandInput
71-
) {
72-
return this.base.parseFuture(commandContext, commandInput)
73-
.thenCompose(result -> this.mapper.map(commandContext, result));
74-
}
75-
76-
@Override
77-
public @NonNull SuggestionProvider<C> suggestionProvider() {
78-
return this.base.suggestionProvider();
79-
}
80-
81-
@Override
82-
public <O1> ArgumentParser.@NonNull FutureArgumentParser<C, O1> flatMap(final Mapper<C, O, O1> mapper) {
83-
requireNonNull(mapper, "mapper");
84-
return new MappedArgumentParser<>(
85-
this.base,
86-
(ctx, orig) -> this.mapper.map(ctx, orig)
87-
.thenCompose(mapped -> mapper.map(ctx, mapped))
88-
);
89-
}
90-
91-
@Override
92-
public int hashCode() {
93-
return 31 + this.base.hashCode()
94-
+ 7 * this.mapper.hashCode();
95-
}
96-
97-
@Override
98-
public boolean equals(final @Nullable Object other) {
99-
if (!(other instanceof MappedArgumentParser<?, ?, ?>)) {
100-
return false;
101-
}
102-
103-
final MappedArgumentParser<?, ?, ?> that = (MappedArgumentParser<?, ?, ?>) other;
104-
return this.base.equals(that.base)
105-
&& this.mapper.equals(that.mapper);
106-
}
107-
108-
@Override
109-
public String toString() {
110-
return "MappedArgumentParser{"
111-
+ "base=" + this.base + ','
112-
+ "mapper=" + this.mapper + '}';
113-
}
114-
46+
@NonNull ArgumentParser<C, I> baseParser();
11547

11648
@FunctionalInterface
117-
@API(status = API.Status.STABLE)
118-
public interface Mapper<C, I, O> {
49+
interface Mapper<C, I, O> {
11950

12051
/**
12152
* Maps the input to a future that completes with the output.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2024 Incendo
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in all
14+
// copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//
24+
package org.incendo.cloud.parser;
25+
26+
import java.util.concurrent.CompletableFuture;
27+
import org.apiguardian.api.API;
28+
import org.checkerframework.checker.nullness.qual.NonNull;
29+
import org.checkerframework.checker.nullness.qual.Nullable;
30+
import org.incendo.cloud.context.CommandContext;
31+
import org.incendo.cloud.context.CommandInput;
32+
import org.incendo.cloud.suggestion.SuggestionProvider;
33+
34+
import static java.util.Objects.requireNonNull;
35+
36+
@API(status = API.Status.INTERNAL)
37+
public final class MappedArgumentParserImpl<C, I, O> implements MappedArgumentParser<C, I, O>,
38+
ArgumentParser.FutureArgumentParser<C, O> {
39+
40+
private final ArgumentParser<C, I> base;
41+
private final Mapper<C, I, O> mapper;
42+
43+
MappedArgumentParserImpl(
44+
final ArgumentParser<C, I> base,
45+
final Mapper<C, I, O> mapper
46+
) {
47+
this.base = base;
48+
this.mapper = mapper;
49+
}
50+
51+
@Override
52+
public @NonNull ArgumentParser<C, I> baseParser() {
53+
return this.base;
54+
}
55+
56+
@Override
57+
public @NonNull CompletableFuture<@NonNull ArgumentParseResult<O>> parseFuture(
58+
final @NonNull CommandContext<@NonNull C> commandContext,
59+
final @NonNull CommandInput commandInput
60+
) {
61+
return this.base.parseFuture(commandContext, commandInput)
62+
.thenCompose(result -> this.mapper.map(commandContext, result));
63+
}
64+
65+
@Override
66+
public @NonNull SuggestionProvider<C> suggestionProvider() {
67+
return this.base.suggestionProvider();
68+
}
69+
70+
@Override
71+
public <O1> ArgumentParser.@NonNull FutureArgumentParser<C, O1> flatMap(final Mapper<C, O, O1> mapper) {
72+
requireNonNull(mapper, "mapper");
73+
return new MappedArgumentParserImpl<>(
74+
this.base,
75+
(ctx, orig) -> this.mapper.map(ctx, orig)
76+
.thenCompose(mapped -> mapper.map(ctx, mapped))
77+
);
78+
}
79+
80+
@Override
81+
public int hashCode() {
82+
return 31 + this.base.hashCode()
83+
+ 7 * this.mapper.hashCode();
84+
}
85+
86+
@Override
87+
public boolean equals(final @Nullable Object other) {
88+
if (!(other instanceof MappedArgumentParserImpl<?, ?, ?>)) {
89+
return false;
90+
}
91+
92+
final MappedArgumentParserImpl<?, ?, ?> that = (MappedArgumentParserImpl<?, ?, ?>) other;
93+
return this.base.equals(that.base)
94+
&& this.mapper.equals(that.mapper);
95+
}
96+
97+
@Override
98+
public String toString() {
99+
return "MappedArgumentParserImpl{"
100+
+ "base=" + this.base + ','
101+
+ "mapper=" + this.mapper + '}';
102+
}
103+
}

0 commit comments

Comments
 (0)