From 6549a67f86c6097b60af88d97eb57b89039ba630 Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Tue, 22 Jun 2021 17:48:21 +0200 Subject: [PATCH] allow components to not resolve --- src/main/jastadd/Coordinator.jrag | 61 +++++++++++++++---- src/main/jastadd/Coordinator.parser | 2 + src/main/jastadd/Coordinator.relast | 3 + .../inf/st/coordinator/MainCoordinator.java | 13 ++-- 4 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/main/jastadd/Coordinator.jrag b/src/main/jastadd/Coordinator.jrag index 1f9a8a2..c7bd041 100644 --- a/src/main/jastadd/Coordinator.jrag +++ b/src/main/jastadd/Coordinator.jrag @@ -49,10 +49,10 @@ aspect Manipulation { return Collections.emptySet(); } for (String service : services) { - resolveComponentByDockerComposeName(service).ifPresentOrElse( - comp -> result.add(comp), - () -> System.err.println("Could not resolve docker component for '" + service + "'!") - ); + Component resolvedComponent = resolveComponentByDockerComposeName(service); + if (!resolvedComponent.handleFailedComponentResolving("Service", () -> "resolving docker compose")) { + result.add(resolvedComponent); + } } return result; } @@ -137,6 +137,9 @@ aspect Navigation { syn MqttReportStrategy ReportStrategy.asMqttReportStrategy() = null; eq MqttReportStrategy.asMqttReportStrategy() = this; + + syn boolean Component.isUnknownComponent() = false; + eq UnknownComponent.isUnknownComponent() = true; } aspect Printing { @@ -222,31 +225,65 @@ aspect Printing { } aspect Resolving { - syn Optional<Component> Coordinator.resolveComponent(String name) { + public enum ResolvingFailedStrategy { + IGNORE, + WARNING, + EXIT + } + + public static ResolvingFailedStrategy Coordinator.RESOLVING_FAILED_STRATEGY = ResolvingFailedStrategy.EXIT; + + syn nta Component Coordinator.unknownComponent(String id) = new UnknownComponent().setName(id); + + syn Component Coordinator.resolveComponent(String name) { for (Component comp : getComponentList()) { if (comp.getName().equals(name)) { - return Optional.of(comp); + return comp; } } - return Optional.empty(); + return unknownComponent(name); } - syn Optional<Component> Coordinator.resolveComponentByDockerComposeName(String dockerComposeName) { + syn Component Coordinator.resolveComponentByDockerComposeName(String dockerComposeName) { for (Component comp : getComponentList()) { if (comp.getStartStrategy().isDockerComposeStartStrategy() && comp.getStartStrategy().asDockerComposeStartStrategy().getName().equals(dockerComposeName)) { - return Optional.of(comp); + return comp; } } - return Optional.empty(); + return unknownComponent(dockerComposeName); } refine RefResolverStubs eq ParsedPrecedenceRelation.resolvePredecessorByToken(String id, int position) { - return coordinator().resolveComponent(id).orElseThrow(() -> new RuntimeException("Predecessor '" + id + "' not found in " + this.prettyPrint() + "!")); + return coordinator().resolveComponent(id); } refine RefResolverStubs eq ParsedPrecedenceRelation.resolveSuccessorByToken(String id, int position) { - return coordinator().resolveComponent(id).orElseThrow(() -> new RuntimeException("Successor '" + id + "' not found in " + this.prettyPrint() + "!")); + return coordinator().resolveComponent(id); + } + + /** + * Handles component resolving based on the current strategy. + * If the component is an unknownComponent, decide based on RESOLVING_FAILED_STRATEGY what to do. + * Either do nothing (IGNORE), print a message (WARNING), or throw a RuntimeException (EXIT). + * @return false if a real component was resolved, true if this is an unknown component + */ + public boolean Component.handleFailedComponentResolving(String kind, java.util.function.Supplier<String> context) { + return false; + } + @Override + public boolean UnknownComponent.handleFailedComponentResolving(String kind, java.util.function.Supplier<String> context) { + String message = kind + " '" + getName() + "' not found in " + context.get() + "!"; + switch (Coordinator.RESOLVING_FAILED_STRATEGY) { + case IGNORE: + break; + case WARNING: + System.err.println(message); + break; + case EXIT: + throw new RuntimeException(message); + } + return true; } } diff --git a/src/main/jastadd/Coordinator.parser b/src/main/jastadd/Coordinator.parser index a1bb3f6..1b5e9d8 100644 --- a/src/main/jastadd/Coordinator.parser +++ b/src/main/jastadd/Coordinator.parser @@ -13,7 +13,9 @@ import java.util.HashMap; private void replaceRelations(Coordinator o) { for (ParsedPrecedenceRelation rel : o.getParsedPrecedenceRelationList()) { for (Component pred : rel.getPredecessorList()) { + if (pred.handleFailedComponentResolving("Predecessor", () -> rel.prettyPrint())) { continue; } for (Component succ : rel.getSuccessorList()) { + if (succ.handleFailedComponentResolving("Successor", () -> rel.prettyPrint())) { continue; } pred.addSuccessor(succ); } } diff --git a/src/main/jastadd/Coordinator.relast b/src/main/jastadd/Coordinator.relast index 11abd37..3eb491c 100644 --- a/src/main/jastadd/Coordinator.relast +++ b/src/main/jastadd/Coordinator.relast @@ -15,3 +15,6 @@ AutoSetStatus ::= <Status:String> <DelayInSeconds:int> ; ParsedPrecedenceRelation ; rel ParsedPrecedenceRelation.Predecessor* -> Component ; rel ParsedPrecedenceRelation.Successor* -> Component ; + +// Parser-only +UnknownComponent : Component ; diff --git a/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java b/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java index 7ccd1f6..c3923eb 100644 --- a/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java +++ b/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java @@ -1,10 +1,7 @@ package de.tudresden.inf.st.coordinator; import beaver.Parser; -import de.tudresden.inf.st.coordinator.ast.Component; -import de.tudresden.inf.st.coordinator.ast.Coordinator; -import de.tudresden.inf.st.coordinator.ast.MqttHandler; -import de.tudresden.inf.st.coordinator.ast.MqttReportStrategy; +import de.tudresden.inf.st.coordinator.ast.*; import de.tudresden.inf.st.coordinator.parser.CoordinatorParser; import de.tudresden.inf.st.coordinator.scanner.CoordinatorScanner; import picocli.CommandLine; @@ -45,17 +42,23 @@ public class MainCoordinator implements Callable<Integer> { @Option(names = { "--mqtt-host"}, description = "MQTT host to control this coordinator") String mqttHost = "localhost"; + @Option(names = { "-r", "--resolvingFailedStrategy"}, description = "Action if resolving of component fails, do nothing (IGNORE), print a message (WARNING), or throw a RuntimeException (EXIT)") + ResolvingFailedStrategy resolvingFailedStrategy = ResolvingFailedStrategy.EXIT; + @Parameters(description = "Coordinator config file to use") File configFile; public static void main(String[] args) { - int exitCode = new CommandLine(new MainCoordinator()).execute(args); + int exitCode = new CommandLine(new MainCoordinator()) + .setCaseInsensitiveEnumValuesAllowed(true) + .execute(args); System.exit(exitCode); } @Override public Integer call() throws Exception { Coordinator.DRY_RUN = dryRun; + Coordinator.RESOLVING_FAILED_STRATEGY = resolvingFailedStrategy; parsedBuild(); return start(); } -- GitLab