aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/generator-cli/src/main/java/tools
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-12-24 19:42:21 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-12-25 00:04:37 +0100
commit1f9b4652b1f85fc9f2cefcd46b34431ecea5c381 (patch)
tree84aba7f8ce90ff5aea38c912b3999ec7810f6f44 /subprojects/generator-cli/src/main/java/tools
parentfeat: command line model generator (diff)
downloadrefinery-1f9b4652b1f85fc9f2cefcd46b34431ecea5c381.tar.gz
refinery-1f9b4652b1f85fc9f2cefcd46b34431ecea5c381.tar.zst
refinery-1f9b4652b1f85fc9f2cefcd46b34431ecea5c381.zip
refactor(generator): scope overrides
Diffstat (limited to 'subprojects/generator-cli/src/main/java/tools')
-rw-r--r--subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java72
1 files changed, 9 insertions, 63 deletions
diff --git a/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java b/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java
index 6c1d105d..b33fce23 100644
--- a/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java
+++ b/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java
@@ -11,16 +11,10 @@ import com.google.inject.Inject;
11import org.eclipse.emf.ecore.resource.Resource; 11import org.eclipse.emf.ecore.resource.Resource;
12import tools.refinery.generator.ModelGeneratorFactory; 12import tools.refinery.generator.ModelGeneratorFactory;
13import tools.refinery.generator.ProblemLoader; 13import tools.refinery.generator.ProblemLoader;
14import tools.refinery.language.model.problem.Problem;
15import tools.refinery.language.model.problem.Relation;
16import tools.refinery.language.model.problem.ScopeDeclaration;
17 14
18import java.io.ByteArrayOutputStream;
19import java.io.FileOutputStream; 15import java.io.FileOutputStream;
20import java.io.IOException; 16import java.io.IOException;
21import java.nio.charset.StandardCharsets;
22import java.util.ArrayList; 17import java.util.ArrayList;
23import java.util.HashSet;
24import java.util.List; 18import java.util.List;
25import java.util.Map; 19import java.util.Map;
26 20
@@ -32,15 +26,15 @@ public class GenerateCommand {
32 @Inject 26 @Inject
33 private ModelGeneratorFactory generatorFactory; 27 private ModelGeneratorFactory generatorFactory;
34 28
35 private String problemPath; 29 private String inputPath;
36 private String outputPath = "-"; 30 private String outputPath = "-";
37 private List<String> scopes = new ArrayList<>(); 31 private List<String> scopes = new ArrayList<>();
38 private List<String> overrideScopes = new ArrayList<>(); 32 private List<String> overrideScopes = new ArrayList<>();
39 private long randomSeed = 1; 33 private long randomSeed = 1;
40 34
41 @Parameter(description = "Input path", required = true) 35 @Parameter(description = "input path", required = true)
42 public void setProblemPath(String problemPath) { 36 public void setInputPath(String inputPath) {
43 this.problemPath = problemPath; 37 this.inputPath = inputPath;
44 } 38 }
45 39
46 @Parameter(names = {"-output", "-o"}, description = "Output path") 40 @Parameter(names = {"-output", "-o"}, description = "Output path")
@@ -64,14 +58,15 @@ public class GenerateCommand {
64 } 58 }
65 59
66 public void run() throws IOException { 60 public void run() throws IOException {
67 var problem = addScopeConstraints(loader.loadFile(problemPath)); 61 var problem = isStandardStream(inputPath) ? loader.loadStream(System.in) : loader.loadFile(inputPath);
62 problem = loader.loadScopeConstraints(problem, scopes, overrideScopes);
68 var generator = generatorFactory.createGenerator(problem); 63 var generator = generatorFactory.createGenerator(problem);
69 generator.setRandomSeed(randomSeed); 64 generator.setRandomSeed(randomSeed);
70 generator.generate(); 65 generator.generate();
71 var solution = generator.serializeSolution(); 66 var solution = generator.serializeSolution();
72 var solutionResource = solution.eResource(); 67 var solutionResource = solution.eResource();
73 var saveOptions = Map.of(); 68 var saveOptions = Map.of();
74 if (outputPath == null || outputPath.equals("-")) { 69 if (isStandardStream(outputPath)) {
75 printSolution(solutionResource, saveOptions); 70 printSolution(solutionResource, saveOptions);
76 } else { 71 } else {
77 try (var outputStream = new FileOutputStream(outputPath)) { 72 try (var outputStream = new FileOutputStream(outputPath)) {
@@ -80,57 +75,8 @@ public class GenerateCommand {
80 } 75 }
81 } 76 }
82 77
83 private Problem addScopeConstraints(Problem problem) throws IOException { 78 private boolean isStandardStream(String path) {
84 var allScopes = new ArrayList<>(scopes); 79 return path == null || path.equals("-");
85 allScopes.addAll(overrideScopes);
86 if (allScopes.isEmpty()) {
87 return problem;
88 }
89 int originalStatementCount = problem.getStatements().size();
90 var builder = new StringBuilder();
91 var problemResource = problem.eResource();
92 try (var outputStream = new ByteArrayOutputStream()) {
93 problemResource.save(outputStream, Map.of());
94 builder.append(outputStream.toString(StandardCharsets.UTF_8));
95 }
96 builder.append('\n');
97 for (var scope : allScopes) {
98 builder.append("scope ").append(scope).append(".\n");
99 }
100 var modifiedProblem = loader.loadString(builder.toString(), problemResource.getURI());
101 var modifiedStatements = modifiedProblem.getStatements();
102 int modifiedStatementCount = modifiedStatements.size();
103 if (modifiedStatementCount != originalStatementCount + allScopes.size()) {
104 throw new IllegalStateException("Failed to parse scope constraints");
105 }
106 // Override scopes remove any scope constraint from the original problem with the same target type.
107 var overriddenScopes = new HashSet<Relation>();
108 for (int i = modifiedStatementCount - overrideScopes.size(); i < modifiedStatementCount; i++) {
109 var statement = modifiedStatements.get(i);
110 if (!(statement instanceof ScopeDeclaration scopeDeclaration)) {
111 throw new IllegalStateException("Invalid scope constraint: " + statement);
112 }
113 for (var typeScope : scopeDeclaration.getTypeScopes()) {
114 overriddenScopes.add(typeScope.getTargetType());
115 }
116 }
117 int statementIndex = 0;
118 var iterator = modifiedStatements.iterator();
119 // Scope overrides only affect type scopes from the original problem and leave type scopes added on the
120 // command line intact.
121 while (statementIndex < originalStatementCount && iterator.hasNext()) {
122 var statement = iterator.next();
123 if (statement instanceof ScopeDeclaration scopeDeclaration) {
124 var typeScopes = scopeDeclaration.getTypeScopes();
125 typeScopes.removeIf(typeScope -> overriddenScopes.contains(typeScope.getTargetType()));
126 // Scope declarations with no type scopes are invalid, so we have to remove them.
127 if (typeScopes.isEmpty()) {
128 iterator.remove();
129 }
130 }
131 statementIndex++;
132 }
133 return modifiedProblem;
134 } 80 }
135 81
136 // We deliberately write to the standard output if no output path is specified. 82 // We deliberately write to the standard output if no output path is specified.