From ac52f38867ecdbecce564e324f89cdf88069ef17 Mon Sep 17 00:00:00 2001
From: 51-code <146736881+51-code@users.noreply.github.com>
Date: Mon, 18 Nov 2024 14:10:19 +0200
Subject: [PATCH] Support command line arguments as a configuration (#22)
Remove unnecessary code in test
Support command line arguments as a configuration source
---
.../teragrep/cnf_01/ArgsConfiguration.java | 116 ++++++++++++
.../cnf_01/ConfigurationException.java | 4 +
.../cnf_01/ArgsConfigurationTest.java | 167 ++++++++++++++++++
3 files changed, 287 insertions(+)
create mode 100644 src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java
create mode 100644 src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java
diff --git a/src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java b/src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java
new file mode 100644
index 0000000..050523d
--- /dev/null
+++ b/src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java
@@ -0,0 +1,116 @@
+/*
+ * Teragrep Configuration Library for Java (cnf_01)
+ * Copyright (C) 2024 Suomen Kanuuna Oy
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ *
+ * Additional permission under GNU Affero General Public License version 3
+ * section 7
+ *
+ * If you modify this Program, or any covered work, by linking or combining it
+ * with other code, such other code is not for that reason alone subject to any
+ * of the requirements of the GNU Affero GPL version 3 as long as this Program
+ * is the same Program as licensed from Suomen Kanuuna Oy without any additional
+ * modifications.
+ *
+ * Supplemented terms under GNU Affero General Public License version 3
+ * section 7
+ *
+ * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified
+ * versions must be marked as "Modified version of" The Program.
+ *
+ * Names of the licensors and authors may not be used for publicity purposes.
+ *
+ * No rights are granted for use of trade names, trademarks, or service marks
+ * which are in The Program if any.
+ *
+ * Licensee must indemnify licensors and authors for any liability that these
+ * contractual assumptions impose on licensors and authors.
+ *
+ * To the extent this program is licensed as part of the Commercial versions of
+ * Teragrep, the applicable Commercial License may apply to this file if you as
+ * a licensee so wish it.
+ */
+package com.teragrep.cnf_01;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class ArgsConfiguration implements Configuration {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ArgsConfiguration.class);
+
+ private final String[] args;
+
+ public ArgsConfiguration(final String[] args) {
+ this.args = Arrays.copyOf(args, args.length);
+ }
+
+ /**
+ * Produces a Map of configurations from the args.
+ *
+ * @return immutable map of the args
+ * @throws ConfigurationException If the args are not given in the format of this regex: ([a-z]+)(=.+)
+ */
+ @Override
+ public Map asMap() throws ConfigurationException {
+ final Map map = new HashMap<>();
+
+ if (args.length != 0) {
+ final Pattern ptn = Pattern.compile("([a-z]+)(=.+)");
+ for (final String arg : args) {
+ final Matcher matcher = ptn.matcher(arg);
+ if (!matcher.matches()) {
+ throw new ConfigurationException(
+ String
+ .format(
+ "Can't parse argument '%s'. Args have to be given in \"key=value\" format.",
+ arg
+ )
+ );
+ }
+ map.put(matcher.group(1), matcher.group(2).substring(1));
+ }
+ }
+ LOGGER.debug("Returning configuration map generated from command-line arguments.");
+ LOGGER.trace("Returning configuration map <[{}]>", map);
+
+ return Collections.unmodifiableMap(map);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ else if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final ArgsConfiguration config = (ArgsConfiguration) o;
+ return Arrays.equals(args, config.args);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(args);
+ }
+}
diff --git a/src/main/java/com/teragrep/cnf_01/ConfigurationException.java b/src/main/java/com/teragrep/cnf_01/ConfigurationException.java
index 023f333..0dd82c4 100644
--- a/src/main/java/com/teragrep/cnf_01/ConfigurationException.java
+++ b/src/main/java/com/teragrep/cnf_01/ConfigurationException.java
@@ -50,4 +50,8 @@ public final class ConfigurationException extends Exception {
public ConfigurationException(final String message, final Throwable cause) {
super(message, cause);
}
+
+ public ConfigurationException(final String message) {
+ super(message);
+ }
}
diff --git a/src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java b/src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java
new file mode 100644
index 0000000..f3b8556
--- /dev/null
+++ b/src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java
@@ -0,0 +1,167 @@
+/*
+ * Teragrep Configuration Library for Java (cnf_01)
+ * Copyright (C) 2024 Suomen Kanuuna Oy
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ *
+ * Additional permission under GNU Affero General Public License version 3
+ * section 7
+ *
+ * If you modify this Program, or any covered work, by linking or combining it
+ * with other code, such other code is not for that reason alone subject to any
+ * of the requirements of the GNU Affero GPL version 3 as long as this Program
+ * is the same Program as licensed from Suomen Kanuuna Oy without any additional
+ * modifications.
+ *
+ * Supplemented terms under GNU Affero General Public License version 3
+ * section 7
+ *
+ * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified
+ * versions must be marked as "Modified version of" The Program.
+ *
+ * Names of the licensors and authors may not be used for publicity purposes.
+ *
+ * No rights are granted for use of trade names, trademarks, or service marks
+ * which are in The Program if any.
+ *
+ * Licensee must indemnify licensors and authors for any liability that these
+ * contractual assumptions impose on licensors and authors.
+ *
+ * To the extent this program is licensed as part of the Commercial versions of
+ * Teragrep, the applicable Commercial License may apply to this file if you as
+ * a licensee so wish it.
+ */
+package com.teragrep.cnf_01;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+public class ArgsConfigurationTest {
+
+ @Test
+ public void testValidArgs() {
+ String param = "bar=foo";
+ String[] args = {
+ "foo=bar", param
+ };
+
+ ArgsConfiguration config = new ArgsConfiguration(args);
+ // modifying the original doesn't have effect on the result
+ args[1] = "biz=buz";
+
+ Map map = Assertions.assertDoesNotThrow(config::asMap);
+
+ Assertions.assertEquals(2, map.size());
+ Assertions.assertTrue(map.containsKey("foo"));
+ Assertions.assertTrue(map.containsKey("bar"));
+ Assertions.assertEquals("bar", map.get("foo"));
+ Assertions.assertEquals("foo", map.get("bar"));
+ }
+
+ @Test
+ public void testInvalidArgs() {
+ String[] args = {
+ "foo", "bar"
+ };
+
+ ArgsConfiguration config = new ArgsConfiguration(args);
+
+ ConfigurationException exception = Assertions.assertThrows(ConfigurationException.class, config::asMap);
+
+ Assertions
+ .assertEquals(
+ "Can't parse argument 'foo'. Args have to be given in \"key=value\" format.",
+ exception.getMessage()
+ );
+ }
+
+ @Test
+ public void testEmptyArgs() {
+ String[] args = new String[0];
+ ArgsConfiguration config = new ArgsConfiguration(args);
+
+ Map map = Assertions.assertDoesNotThrow(config::asMap);
+ Assertions.assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void testImmutability() {
+ String[] args = new String[0];
+ ArgsConfiguration config = new ArgsConfiguration(args);
+
+ Map map = Assertions.assertDoesNotThrow(config::asMap);
+ Assertions.assertThrows(UnsupportedOperationException.class, () -> map.put("foo", "bar")); // The map is immutable
+ }
+
+ @Test
+ public void testEquals() {
+ String[] args = {
+ "foo=bar", "bar=foo"
+ };
+ ArgsConfiguration config = new ArgsConfiguration(args);
+
+ String[] args2 = {
+ "foo=bar", "bar=foo"
+ };
+ ArgsConfiguration config2 = new ArgsConfiguration(args2);
+
+ Assertions.assertDoesNotThrow(config::asMap);
+
+ Assertions.assertEquals(config, config2);
+ }
+
+ @Test
+ public void testNotEquals() {
+ String[] args = {
+ "foo=bar", "bar=foo"
+ };
+ String[] args2 = {
+ ""
+ };
+
+ ArgsConfiguration config = new ArgsConfiguration(args);
+ ArgsConfiguration config2 = new ArgsConfiguration(args2);
+
+ Assertions.assertNotEquals(config, config2);
+ }
+
+ @Test
+ public void testHashCode() {
+ String[] args = {
+ "foo=bar", "bar=foo"
+ };
+ String[] args2 = {
+ "foo=bar", "bar=foo"
+ };
+ String[] args3 = {
+ ""
+ };
+
+ ArgsConfiguration config = new ArgsConfiguration(args);
+ ArgsConfiguration config2 = new ArgsConfiguration(args2);
+ ArgsConfiguration config3 = new ArgsConfiguration(args3);
+
+ Assertions.assertEquals(config.hashCode(), config2.hashCode());
+ Assertions.assertNotEquals(config.hashCode(), config3.hashCode());
+ }
+
+ @Test
+ public void testEqualsVerifier() {
+ EqualsVerifier.forClass(ArgsConfiguration.class).withNonnullFields("args").verify();
+ }
+}