diff --git a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/AlarmConfigurationParser.tjava b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/AlarmConfigurationParser.tjava index 010c950..d67dacc 100644 --- a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/AlarmConfigurationParser.tjava +++ b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/AlarmConfigurationParser.tjava @@ -6,9 +6,7 @@ import java.io.IOException; import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; +import java.util.*; public final class AlarmConfigurationParser { @@ -19,12 +17,18 @@ public final class AlarmConfigurationParser { for (int lineNumber = 1; lineNumber <= lines.size(); lineNumber++) { String line = lines.get(lineNumber - 1); String trimmed = line.trim(); - if (trimmed.isEmpty() || trimmed.startsWith("#")) { + + if(trimmed.isEmpty() || trimmed.startsWith("#")) { continue; } try { - alarms.add(parseLine(line)); + if(isConstantDefinition(trimmed)) { + parseConstantDefinition(constants, line); + } else { + String resolvedLine = replaceConstants(line, constants); + alarms.add(parseLine(resolvedLine)); + } } catch (RuntimeException exception) { throw new IllegalArgumentException( path + ":" + lineNumber + ": " + exception.getMessage(), @@ -218,6 +222,60 @@ public final class AlarmConfigurationParser { private int position; } + private static boolean isConstantDefinition(String trimmedLine) { + return trimmedLine.startsWith("{{"); + } + + private static void parseConstantDefinition( + Map constants, + String line + ) { + Cursor cursor = new Cursor(line); + + String name = cursor.nextToken("constant name"); + String value = cursor.nextToken("constant value"); + + cursor.skipWhitespace(); + if (!cursor.atEnd() && cursor.current() != '#') { + throw new IllegalArgumentException( + "Unexpected text after constant value: " + cursor.remaining() + ); + } + + validateConstantName(name); + + if (constants.putIfAbsent(name, value) != null) { + throw new IllegalArgumentException("Duplicate constant: " + name); + } + } + + private static String replaceConstants( + String line, + Map constants + ) { + String result = line; + + for (Map.Entry entry : constants.entrySet()) { + result = result.replace(entry.getKey(), entry.getValue()); + } + + if (result.contains("{{") || result.contains("}}")) { + throw new IllegalArgumentException( + "Unknown or malformed constant in line: " + line + ); + } + + return result; + } + + private static void validateConstantName(String name) { + if (!name.matches("\\{\\{[A-Z0-9_]+}}")) { + throw new IllegalArgumentException("Invalid constant name: " + name); + } + } + private AlarmConfigurationParser() { } + + private static Map constants = new LinkedHashMap<>(); }