Compare commits

..

3 commits

9 changed files with 214 additions and 61 deletions

3
.gitignore vendored
View file

@ -37,5 +37,6 @@ gradlew.bat
# Ignore manual compilation results # Ignore manual compilation results
/de/jotoho/ /de/jotoho/
/META-INF /META-INF
/.idea /.idea/*
!/.idea/codeStyles/
*.zst *.zst

View file

@ -0,0 +1,78 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="80" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="ENABLE_SECOND_REFORMAT" value="true" />
<option name="SOFT_MARGINS" value="80" />
<JavaCodeStyleSettings>
<option name="ANNOTATION_PARAMETER_WRAP" value="5" />
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
<option name="ALIGN_MULTILINE_TEXT_BLOCKS" value="true" />
<option name="NEW_LINE_AFTER_LPAREN_IN_RECORD_HEADER" value="true" />
<option name="RPAREN_ON_NEW_LINE_IN_RECORD_HEADER" value="true" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="false" />
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="false" />
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="false" />
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="false" />
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="1" />
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BETWEEN_PACKAGE_DECLARATION_AND_HEADER" value="0" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="5" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="RESOURCE_LIST_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="2" />
<option name="WRAP_FIRST_METHOD_IN_CALL_CHAIN" value="true" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE" value="true" />
<option name="ASSIGNMENT_WRAP" value="5" />
<option name="ASSERT_STATEMENT_WRAP" value="1" />
<option name="WRAP_LONG_LINES" value="true" />
<option name="PARAMETER_ANNOTATION_WRAP" value="5" />
<option name="VARIABLE_ANNOTATION_WRAP" value="5" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="5" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="5" />
<option name="METHOD_CALL_CHAIN_WRAP" value="5" />
<option name="ASSIGNMENT_WRAP" value="5" />
<option name="PARAMETER_ANNOTATION_WRAP" value="5" />
<option name="VARIABLE_ANNOTATION_WRAP" value="5" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
</codeStyleSettings>
</code_scheme>
</component>

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View file

@ -6,7 +6,7 @@ plugins {
application application
java java
id ("com.github.johnrengelman.shadow") version "7.1.2" id("com.github.johnrengelman.shadow") version "7.1.2"
} }
repositories { repositories {
@ -15,7 +15,9 @@ repositories {
} }
dependencies { dependencies {
implementation(group="commons-cli", name="commons-cli", version="1.5.0") implementation(group = "commons-cli",
name = "commons-cli",
version = "1.5.0")
} }
fun versionBanner(): String { fun versionBanner(): String {
@ -38,10 +40,9 @@ java {
tasks.jar { tasks.jar {
manifest { manifest {
attributes( attributes("Implementation-Title" to project.name,
"Implementation-Title" to project.name, "Implementation-Version" to project.version,
"Implementation-Version" to project.version, "Main-Class" to "de.jotoho.waituntil.Main"
"Main-Class" to "de.jotoho.waituntil.Main"
//"Main-Module" to "de.jotoho.waituntil.main" //"Main-Module" to "de.jotoho.waituntil.main"
) )
} }

View file

@ -22,14 +22,21 @@ import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options; import org.apache.commons.cli.Options;
final class AppOptions { final class AppOptions {
public final static Option help = Option.builder().argName("h").longOpt("help").desc("Shows this help " + "message and exits").build(); public final Option help = Option
public final static Option version = Option.builder().argName("v").longOpt("version").desc("Shows version information and exits").build(); .builder()
private final static Options options = new Options().addOption(help).addOption(version); .argName("h")
.longOpt("help")
.desc("Shows this help " + "message and exits")
.build();
// Disable Instance Creation public final Option version = Option
private AppOptions() {} .builder()
.argName("v")
.longOpt("version")
.desc("Shows version information and exits")
.build();
public static Options getOptions() { public final Options options = new Options()
return options; .addOption(help)
} .addOption(version);
} }

View file

@ -22,5 +22,12 @@ import java.util.Locale;
public record GlobalConf() { public record GlobalConf() {
public static final String langGerman = "de"; public static final String langGerman = "de";
public static final String applicationOutputLanguage = (Locale.getDefault().getLanguage().equals(Locale.GERMAN.getLanguage())) ? Locale.GERMAN.getLanguage() : Locale.ENGLISH.getLanguage(); public static final String applicationOutputLanguage = (Locale
.getDefault()
.getLanguage()
.equals(Locale.GERMAN.getLanguage()))
?
Locale.GERMAN.getLanguage()
:
Locale.ENGLISH.getLanguage();
} }

View file

@ -18,13 +18,16 @@ package de.jotoho.waituntil;
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import static de.jotoho.waituntil.GlobalConf.applicationOutputLanguage; import static de.jotoho.waituntil.GlobalConf.applicationOutputLanguage;
import static java.lang.System.Logger.Level; import static java.lang.System.Logger.Level;
// This file contains the main function and other utility function necessary for interpreting the terminal arguments. // This file contains the main function and other utility function necessary
// for interpreting the terminal arguments.
// See README.md and LICENSE.md for license information // See README.md and LICENSE.md for license information
// Author: Jonas Tobias Hopusch (@jotoho) // Author: Jonas Tobias Hopusch (@jotoho)
@ -33,55 +36,96 @@ public final class Main {
private static void printVersionInformation() { private static void printVersionInformation() {
final var thisPackage = Main.class.getPackage(); final var thisPackage = Main.class.getPackage();
final var appVersion = thisPackage.getImplementationVersion() != null ? thisPackage.getImplementationVersion() : "version unknown"; final var
appVersion =
thisPackage.getImplementationVersion() != null
? thisPackage.getImplementationVersion()
: "version unknown";
System.out.println("waituntil " + appVersion); System.out.println("waituntil " + appVersion);
System.out.println(""" System.out.println("""
Project Repository: https://gitea.jotoho.de/jotoho/waituntil Project Repository: https://gitea.jotoho.de/jotoho/waituntil
This program is free software: you can redistribute it and/or modify it under the terms of the This program is free software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation, either version 3 of the GNU General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details."""); See the GNU General Public License for more details.""");
} }
private static void printHelpInformation() { private static void printHelpInformation() {
switch (applicationOutputLanguage) { switch (applicationOutputLanguage) {
case GlobalConf.langGerman -> logger.log(Level.ERROR, "Hilfe kommt noch. (Nicht implementiert)"); case GlobalConf.langGerman -> logger.log(Level.ERROR,
default -> logger.log(Level.ERROR, "Help is yet to come. (Not implemented)"); "Hilfe " +
"kommt noch. (Nicht " +
"implementiert)");
default -> logger.log(Level.ERROR,
"Help is yet to come. (Not " +
"implemented)");
} }
} }
public static void main(final String[] args) { private static CommandLine parseArgs(final Options options,
try { final String[] args)
final var parsedArguments = DefaultParser.builder().setStripLeadingAndTrailingQuotes(true).build().parse(AppOptions.getOptions(), args); throws ParseException {
return DefaultParser
.builder()
.setStripLeadingAndTrailingQuotes(true)
.build()
.parse(options, args);
}
public synchronized static void main(final String[] args) {
// Retrieve defined CLI options
final var appOptions = new AppOptions();
try {
// Parse CLI
final var parsedArguments = parseArgs(appOptions.options, args);
final var userData = parsedArguments.getArgs(); final var userData = parsedArguments.getArgs();
if (parsedArguments.hasOption(AppOptions.help)) { // Differentiate between usage scenarios
if (parsedArguments.hasOption(appOptions.help)) {
printHelpInformation(); printHelpInformation();
} else if (parsedArguments.hasOption(AppOptions.version)) { } else if (parsedArguments.hasOption(appOptions.version)) {
printVersionInformation(); printVersionInformation();
} else if (userData.length == 0) { } else if (userData.length == 0) {
switch (applicationOutputLanguage) { switch (applicationOutputLanguage) {
case GlobalConf.langGerman -> logger.log(Level.ERROR, "Es wurde keine Uhrzeit angegeben."); case GlobalConf.langGerman -> logger.log(Level.ERROR,
default -> logger.log(Level.ERROR, "No target time" + " was " + "provided."); "Es" +
" wurde keine " +
"Uhrzeit " +
"angegeben.");
default -> logger.log(Level.ERROR,
"No target time was " + "provided.");
} }
System.exit(1); System.exit(1);
} else if (userData.length > 1) { } else if (userData.length > 1) {
switch (applicationOutputLanguage) { switch (applicationOutputLanguage) {
case GlobalConf.langGerman -> logger.log(Level.ERROR, "Zu viele Argumente wurden angegeben."); case GlobalConf.langGerman -> logger.log(Level.ERROR,
default -> logger.log(Level.ERROR, "Too many arguments " + "provided."); "Zu" + " viele " +
"Argumente " +
"wurden " +
"angegeben.");
default -> logger.log(Level.ERROR,
"Too many arguments " + "provided.");
} }
System.exit(1); System.exit(1);
} else { } else {
final var target = TimeCalculator.calculateAndAnnounceTargetTime(userData[0]); final var
target =
TimeCalculator.calculateAndAnnounceTargetTime(userData[0]);
Sleep.waitUntilTimeStamp(target); Sleep.waitUntilTimeStamp(target);
} }
} catch (final ParseException e) { } catch (final ParseException e) {
System.getLogger("main").log(Level.ERROR, "Parsing " + "of arguments failed and the program cannot continue.", e); System
.getLogger("main")
.log(Level.ERROR,
"Parsing of arguments " +
"failed and the program cannot " + "continue.",
e);
System.exit(1); System.exit(1);
} }
} }

View file

@ -30,14 +30,19 @@ import static java.lang.System.Logger.Level;
public final class Sleep { public final class Sleep {
public static void waitUntilTimeStamp(ZonedDateTime timestamp) { public static void waitUntilTimeStamp(ZonedDateTime timestamp) {
try { try {
Thread.sleep(Math.max(0, Instant.now().until(timestamp, ChronoUnit.MILLIS))); Thread.sleep(Math.max(0,
Instant
.now()
.until(timestamp, ChronoUnit.MILLIS)));
} catch (final InterruptedException ignored) { } catch (final InterruptedException ignored) {
} }
final String formattedTimeStamp = final String formattedTimeStamp = DateTimeFormatter
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG) .ofLocalizedDateTime(FormatStyle.LONG)
.withZone(TimeZone.getDefault().toZoneId()) .withZone(TimeZone
.format(Instant.now()); .getDefault()
.toZoneId())
.format(Instant.now());
final String msg = switch (GlobalConf.applicationOutputLanguage) { final String msg = switch (GlobalConf.applicationOutputLanguage) {
case GlobalConf.langGerman -> "Erfolgreich bis %s gewartet!"; case GlobalConf.langGerman -> "Erfolgreich bis %s gewartet!";
@ -45,6 +50,8 @@ public final class Sleep {
}; };
final String msgWithData = msg.formatted(formattedTimeStamp); final String msgWithData = msg.formatted(formattedTimeStamp);
System.getLogger("sleep").log(Level.INFO, msgWithData); System
.getLogger("sleep")
.log(Level.INFO, msgWithData);
} }
} }

View file

@ -32,28 +32,31 @@ public final class TimeCalculator {
public static ZonedDateTime calculateAndAnnounceTargetTime(final String userTimeInputRaw) { public static ZonedDateTime calculateAndAnnounceTargetTime(final String userTimeInputRaw) {
final var userTimeInputRelative = LocalTime.parse(userTimeInputRaw); final var userTimeInputRelative = LocalTime.parse(userTimeInputRaw);
final var userTimeInputAbsolute = final var userTimeInputAbsolute = ZonedDateTime.of(LocalDate.now(),
ZonedDateTime.of( userTimeInputRelative,
LocalDate.now(), TimeZone
userTimeInputRelative, .getDefault()
TimeZone.getDefault().toZoneId() .toZoneId());
);
final var userTimeInputFinal = (Instant.now().isBefore(userTimeInputAbsolute.toInstant())) final var userTimeInputFinal = (Instant
? userTimeInputAbsolute .now()
: userTimeInputAbsolute.plusDays(1); .isBefore(userTimeInputAbsolute.toInstant()))
? userTimeInputAbsolute
: userTimeInputAbsolute.plusDays(1);
final var formattedTimeStamp = final var formattedTimeStamp = userTimeInputFinal.format(
userTimeInputFinal.format( DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG));
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
);
final String msg = switch (GlobalConf.applicationOutputLanguage) { final String msg = switch (GlobalConf.applicationOutputLanguage) {
case GlobalConf.langGerman -> "Dieses Program wird bis zum %s warten." case GlobalConf.langGerman -> ("Dieses Program wird bis zum %s " +
.formatted(formattedTimeStamp); "warten.").formatted(
default -> "WaitUntil will suspend until %s".formatted(formattedTimeStamp); formattedTimeStamp);
default -> "WaitUntil will suspend until %s".formatted(
formattedTimeStamp);
}; };
System.getLogger("timecalculator").log(Level.INFO, msg); System
.getLogger("timecalculator")
.log(Level.INFO, msg);
return userTimeInputFinal; return userTimeInputFinal;
} }