package org.mafagafogigante.dungeon.date; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; public final class DungeonTimeParser { private DungeonTimeParser() { throw new AssertionError(); } /** * Parses a period string. * * <p>Such string should only contain pairs of positive numerical multipliers and time units separated by spaces, * "and", and commas. * * <p>For example: "2 years, 5 months, 8 days, and 20 hours". * * @param string a period string, not null * @return a Duration, not null */ @NotNull public static Duration parsePeriod(@NotNull String string) { List<String> tokens = cleanAndTokenize(string); if (tokens.size() < 2) { throw new IllegalArgumentException("string should provide at least one multiplier-unit pair."); } long milliseconds = 0; // Alternatively get a multiplier and a unit. Long multiplier = null; DungeonTimeUnit unit = null; for (String token : tokens) { if (multiplier == null) { try { multiplier = Long.parseLong(token); if (multiplier <= 0) { throw new InvalidMultiplierException("nonpositive multipliers are not allowed."); } } catch (NumberFormatException bad) { throw new InvalidMultiplierException(token + " is not a valid multiplier."); } } else { unit = parseDungeonTimeUnit(token); } if (unit != null) { milliseconds += multiplier * unit.milliseconds; multiplier = null; unit = null; } } return new Duration(milliseconds); } @NotNull private static DungeonTimeUnit parseDungeonTimeUnit(final String token) { String cleanToken; if (token.endsWith("s")) { cleanToken = token.substring(0, token.length() - 1); } else { cleanToken = token; } try { return DungeonTimeUnit.valueOf(cleanToken.toUpperCase(Locale.ENGLISH)); } catch (IllegalArgumentException bad) { throw new InvalidUnitException(token + " is not a valid unit."); } } @NotNull private static List<String> cleanAndTokenize(String string) { string = string.replaceAll("and", ""); string = string.replaceAll(",", ""); return new ArrayList<>(Arrays.asList(StringUtils.split(string))); } public static class InvalidMultiplierException extends IllegalArgumentException { InvalidMultiplierException(@NotNull String string) { super(string); } } public static class InvalidUnitException extends IllegalArgumentException { InvalidUnitException(@NotNull String string) { super(string); } } }