-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GH-257 Add argument resolvers for temportal amounts, temporal accesso…
…rs (#256) * Add an argument resolver for temporal amounts * Add an argument resolver for temporal accessors * Fix code style issues
- Loading branch information
Showing
6 changed files
with
191 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 14 additions & 48 deletions
62
...core/src/dev/rollczi/litecommands/argument/resolver/standard/InstantArgumentResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,27 @@ | ||
package dev.rollczi.litecommands.argument.resolver.standard; | ||
|
||
import dev.rollczi.litecommands.argument.Argument; | ||
import dev.rollczi.litecommands.argument.parser.ParseResult; | ||
import dev.rollczi.litecommands.argument.resolver.MultipleArgumentResolver; | ||
import dev.rollczi.litecommands.input.raw.RawCommand; | ||
import dev.rollczi.litecommands.input.raw.RawInput; | ||
import dev.rollczi.litecommands.invocation.Invocation; | ||
import dev.rollczi.litecommands.message.LiteMessages; | ||
import static dev.rollczi.litecommands.argument.resolver.standard.TemporalAccessorUtils.allDaysOfWeek; | ||
import static dev.rollczi.litecommands.message.LiteMessages.INSTANT_INVALID_FORMAT; | ||
import static java.time.ZoneOffset.UTC; | ||
|
||
import dev.rollczi.litecommands.message.MessageRegistry; | ||
import dev.rollczi.litecommands.range.Range; | ||
import dev.rollczi.litecommands.suggestion.SuggestionContext; | ||
import dev.rollczi.litecommands.suggestion.SuggestionResult; | ||
|
||
import java.time.DateTimeException; | ||
import java.time.Instant; | ||
import java.time.ZoneOffset; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.stream.IntStream; | ||
|
||
@SuppressWarnings("Convert2MethodRef") | ||
public class InstantArgumentResolver<SENDER> implements MultipleArgumentResolver<SENDER, Instant> { | ||
public class InstantArgumentResolver<SENDER> extends TemporalAccessorArgumentResolver<SENDER, Instant> { | ||
|
||
private final DateTimeFormatter formatter = DateTimeFormatter | ||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter | ||
.ofPattern("yyyy-MM-dd HH:mm:ss") | ||
.withZone(ZoneOffset.UTC); | ||
|
||
private final MessageRegistry<SENDER> messageRegistry; | ||
.withZone(UTC); | ||
|
||
public InstantArgumentResolver(MessageRegistry<SENDER> messageRegistry) { | ||
this.messageRegistry = messageRegistry; | ||
} | ||
|
||
@Override | ||
public ParseResult<Instant> parse(Invocation<SENDER> invocation, Argument<Instant> argument, RawInput rawInput) { | ||
String commandInput = String.join(RawCommand.COMMAND_SEPARATOR, rawInput.seeNext(2)); | ||
|
||
try { | ||
String rawInstant = String.join(" ", rawInput.next(2)); | ||
return ParseResult.success(Instant.from(formatter.parse(rawInstant))); | ||
} | ||
catch (DateTimeException ignored) { | ||
return ParseResult.failure(this.messageRegistry.getInvoked(LiteMessages.INSTANT_INVALID_FORMAT, invocation, commandInput)); | ||
} | ||
super( | ||
messageRegistry, | ||
INSTANT_INVALID_FORMAT, | ||
FORMATTER, | ||
Instant::from, | ||
() -> allDaysOfWeek(Instant.now()) | ||
); | ||
} | ||
|
||
@Override | ||
public SuggestionResult suggest(Invocation<SENDER> invocation, Argument<Instant> argument, SuggestionContext context) { | ||
return IntStream.range(0, 7) | ||
.mapToObj(day -> Instant.now().plus(day, ChronoUnit.DAYS)) | ||
.map(instant -> formatter.format(instant)) | ||
.collect(SuggestionResult.collector()); | ||
} | ||
|
||
@Override | ||
public Range getRange(Argument<Instant> instantArgument) { | ||
return Range.of(2); | ||
} | ||
|
||
} |
26 changes: 3 additions & 23 deletions
26
...-core/src/dev/rollczi/litecommands/argument/resolver/standard/PeriodArgumentResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,19 @@ | ||
package dev.rollczi.litecommands.argument.resolver.standard; | ||
|
||
import dev.rollczi.litecommands.argument.Argument; | ||
import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; | ||
import dev.rollczi.litecommands.argument.parser.ParseResult; | ||
import dev.rollczi.litecommands.invalidusage.InvalidUsage; | ||
import dev.rollczi.litecommands.invocation.Invocation; | ||
import dev.rollczi.litecommands.suggestion.SuggestionContext; | ||
import dev.rollczi.litecommands.suggestion.SuggestionResult; | ||
import dev.rollczi.litecommands.time.PeriodParser; | ||
|
||
import java.time.Period; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class PeriodArgumentResolver<SENDER> extends ArgumentResolver<SENDER, Period> { | ||
public class PeriodArgumentResolver<SENDER> extends TemporalAmountArgumentResolver<SENDER, Period> { | ||
|
||
private static final List<String> SUGGESTIONS_LIST = Arrays.asList( | ||
"1h", "3h", "7h", | ||
"1d", "7d", "30d", | ||
"1m", "3m", "6m", "1y", "5y" | ||
); | ||
|
||
@Override | ||
protected ParseResult<Period> parse(Invocation<SENDER> invocation, Argument<Period> context, String argument) { | ||
try { | ||
Period parse = PeriodParser.DATE_UNITS.parse(argument); | ||
|
||
return ParseResult.success(parse); | ||
} catch (IllegalArgumentException e) { | ||
return ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT); | ||
} | ||
} | ||
|
||
@Override | ||
public SuggestionResult suggest(Invocation<SENDER> invocation, Argument<Period> argument, SuggestionContext context) { | ||
return SuggestionResult.of(SUGGESTIONS_LIST); | ||
public PeriodArgumentResolver() { | ||
super(PeriodParser.DATE_UNITS, () -> SUGGESTIONS_LIST); | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
...dev/rollczi/litecommands/argument/resolver/standard/TemporalAccessorArgumentResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package dev.rollczi.litecommands.argument.resolver.standard; | ||
|
||
import static dev.rollczi.litecommands.argument.parser.ParseResult.failure; | ||
import static dev.rollczi.litecommands.argument.parser.ParseResult.success; | ||
import static dev.rollczi.litecommands.input.raw.RawCommand.COMMAND_SEPARATOR; | ||
|
||
import dev.rollczi.litecommands.argument.Argument; | ||
import dev.rollczi.litecommands.argument.parser.ParseResult; | ||
import dev.rollczi.litecommands.argument.resolver.MultipleArgumentResolver; | ||
import dev.rollczi.litecommands.input.raw.RawInput; | ||
import dev.rollczi.litecommands.invocation.Invocation; | ||
import dev.rollczi.litecommands.message.MessageKey; | ||
import dev.rollczi.litecommands.message.MessageRegistry; | ||
import dev.rollczi.litecommands.range.Range; | ||
import dev.rollczi.litecommands.suggestion.SuggestionContext; | ||
import dev.rollczi.litecommands.suggestion.SuggestionResult; | ||
import java.time.DateTimeException; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.temporal.TemporalAccessor; | ||
import java.time.temporal.TemporalQuery; | ||
import java.util.List; | ||
import java.util.function.Supplier; | ||
|
||
class TemporalAccessorArgumentResolver<SENDER, UNIT extends TemporalAccessor> implements MultipleArgumentResolver<SENDER, UNIT> { | ||
|
||
private static final String ARGUMENT_SEPARATOR = " "; | ||
private static final String FORMATTER_ELEMENT_SEPARATOR = " "; | ||
private final MessageRegistry<SENDER> messageRegistry; | ||
private final MessageKey<String> invalidFormatMessage; | ||
private final DateTimeFormatter formatter; | ||
private final TemporalQuery<UNIT> query; | ||
private final Supplier<List<UNIT>> suggestions; | ||
private final int argumentCount; | ||
|
||
protected TemporalAccessorArgumentResolver( | ||
MessageRegistry<SENDER> messageRegistry, | ||
MessageKey<String> invalidFormatMessage, | ||
DateTimeFormatter formatter, | ||
TemporalQuery<UNIT> query, | ||
Supplier<List<UNIT>> suggestions | ||
) { | ||
this.messageRegistry = messageRegistry; | ||
this.invalidFormatMessage = invalidFormatMessage; | ||
this.formatter = formatter; | ||
this.query = query; | ||
this.suggestions = suggestions; | ||
this.argumentCount = getElementCount(formatter); | ||
} | ||
|
||
protected TemporalAccessorArgumentResolver( | ||
MessageRegistry<SENDER> messageRegistry, | ||
MessageKey<String> invalidFormatMessage, | ||
String formatterPattern, | ||
TemporalQuery<UNIT> query, | ||
Supplier<List<UNIT>> suggestions | ||
) { | ||
this(messageRegistry, invalidFormatMessage, DateTimeFormatter.ofPattern(formatterPattern), query, suggestions); | ||
} | ||
|
||
@Override | ||
public ParseResult<UNIT> parse(Invocation<SENDER> invocation, Argument<UNIT> argument, RawInput rawInput) { | ||
String commandInput = String.join(COMMAND_SEPARATOR, rawInput.seeNext(this.argumentCount)); | ||
try { | ||
String rawInstant = String.join(ARGUMENT_SEPARATOR, rawInput.next(this.argumentCount)); | ||
return success(this.formatter.parse(rawInstant, query)); | ||
} catch (DateTimeException exception) { | ||
return failure(this.messageRegistry.getInvoked(this.invalidFormatMessage, invocation, commandInput)); | ||
} | ||
} | ||
|
||
@Override | ||
public SuggestionResult suggest(Invocation<SENDER> invocation, Argument<UNIT> argument, SuggestionContext context) { | ||
return this.suggestions.get().stream() | ||
.map(this.formatter::format) | ||
.collect(SuggestionResult.collector()); | ||
} | ||
|
||
@Override | ||
public Range getRange(Argument<UNIT> unitArgument) { | ||
return Range.of(this.argumentCount); | ||
} | ||
|
||
private int getElementCount(DateTimeFormatter formatter) { | ||
return formatter.toString().split(FORMATTER_ELEMENT_SEPARATOR).length; | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
...s-core/src/dev/rollczi/litecommands/argument/resolver/standard/TemporalAccessorUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package dev.rollczi.litecommands.argument.resolver.standard; | ||
|
||
import static java.time.temporal.ChronoUnit.DAYS; | ||
import static java.time.temporal.ChronoUnit.HOURS; | ||
import static java.time.temporal.ChronoUnit.YEARS; | ||
|
||
import java.time.temporal.ChronoUnit; | ||
import java.time.temporal.Temporal; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
final class TemporalAccessorUtils { | ||
|
||
private static final int WEEK_DAYS = 7; | ||
private static final int HOURS_IN_DAY = 24; | ||
private static final int YEARS_IN_DECADE = 10; | ||
|
||
private TemporalAccessorUtils() { | ||
|
||
} | ||
|
||
static <T extends Temporal> List<T> allDaysOfWeek(T start) { | ||
return generateTemporal(start, DAYS, WEEK_DAYS); | ||
} | ||
|
||
static <T extends Temporal> List<T> allHoursOfDay(T start) { | ||
return generateTemporal(start, HOURS, HOURS_IN_DAY); | ||
} | ||
|
||
static <T extends Temporal> List<T> allYearsOfDecade(T start) { | ||
return generateTemporal(start, YEARS, YEARS_IN_DECADE); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private static <T extends Temporal> List<T> generateTemporal(T start, ChronoUnit unit, int countGenerate) { | ||
Class<T> temporalClass = (Class<T>) start.getClass(); | ||
return IntStream.range(0, countGenerate).boxed() | ||
.map(temporalCount -> start.plus(temporalCount, unit)) | ||
.filter(temporalClass::isInstance) | ||
.map(temporalClass::cast) | ||
.collect(Collectors.toList()); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
...c/dev/rollczi/litecommands/argument/resolver/standard/TemporalAmountArgumentResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package dev.rollczi.litecommands.argument.resolver.standard; | ||
|
||
import static dev.rollczi.litecommands.argument.parser.ParseResult.failure; | ||
import static dev.rollczi.litecommands.argument.parser.ParseResult.success; | ||
import static dev.rollczi.litecommands.invalidusage.InvalidUsage.Cause.INVALID_ARGUMENT; | ||
|
||
import dev.rollczi.litecommands.argument.Argument; | ||
import dev.rollczi.litecommands.argument.parser.ParseResult; | ||
import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; | ||
import dev.rollczi.litecommands.invocation.Invocation; | ||
import dev.rollczi.litecommands.suggestion.SuggestionContext; | ||
import dev.rollczi.litecommands.suggestion.SuggestionResult; | ||
import dev.rollczi.litecommands.time.TemporalAmountParser; | ||
import java.time.temporal.TemporalAmount; | ||
import java.util.List; | ||
import java.util.function.Supplier; | ||
|
||
class TemporalAmountArgumentResolver<SENDER, UNIT extends TemporalAmount> extends ArgumentResolver<SENDER, UNIT> { | ||
|
||
private final TemporalAmountParser<UNIT> parser; | ||
private final Supplier<List<String>> suggestions; | ||
|
||
protected TemporalAmountArgumentResolver(TemporalAmountParser<UNIT> parser, Supplier<List<String>> suggestions) { | ||
this.parser = parser; | ||
this.suggestions = suggestions; | ||
} | ||
|
||
@Override | ||
protected ParseResult<UNIT> parse(Invocation<SENDER> invocation, Argument<UNIT> context, String argument) { | ||
try { | ||
return success(parser.parse(argument)); | ||
} catch (IllegalArgumentException exception) { | ||
return failure(INVALID_ARGUMENT); | ||
} | ||
} | ||
|
||
@Override | ||
public SuggestionResult suggest(Invocation<SENDER> invocation, Argument<UNIT> argument, SuggestionContext context) { | ||
return SuggestionResult.of(suggestions.get()); | ||
} | ||
} |