forked from typetools/checker-framework-inference
-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathSolutionJaifUpdater.java
More file actions
157 lines (131 loc) · 6.08 KB
/
Copy pathSolutionJaifUpdater.java
File metadata and controls
157 lines (131 loc) · 6.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package checkers.inference;
import org.json.simple.parser.ParseException;
import org.plumelib.options.Option;
import org.plumelib.options.Options;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import checkers.inference.model.serialization.JsonDeserializer;
/**
* SolutionJaifUpdater takes in a solved json constraints file and a JAIF that contains
* {@link @VarAnnot} annotations and creates a new JAIF by replacing the @VarAnnots with the
* annotation for that @VarAnnot's id in the solution.
*/
public class SolutionJaifUpdater {
public static final String CHECKERS_INFERENCE_QUALS_VAR_ANNOT =
"@checkers.inference.qual.VarAnnot(";
@Option("[filename] the input jaif.")
public static String jaifFilename = "default.jaif";
@Option("[filename] the original JSON file")
public static String originalJson;
@Option("[filename] the input solved constraints json filename.")
public static String solvedJson;
@Option("[filename] the output filename for the solved jaif.")
public static String outputFilename = "output.jaif";
@Option("The string representation of the top annotation in the hierarchy (e.g. @Nullable)")
public static String topAnnotation;
@Option("The string representation of the bottom annotation in the hierarchy (e.g. @NonNull)")
public static String botAnnotation;
public static void main(String[] args) throws IOException, ParseException {
Options options = new Options("SolutionJaifUpdator [options]", SolutionJaifUpdater.class);
options.parse(true, args);
if (solvedJson == null
|| originalJson == null
|| outputFilename == null
|| topAnnotation == null
|| botAnnotation == null) {
System.out.println("A required argument was not found.");
options.printUsage();
System.exit(1);
}
String solvedJsonStr = readFile(solvedJson);
JsonDeserializer solvedDeserializer = new JsonDeserializer(null, solvedJsonStr);
Map<String, Boolean> existentialValues =
getExistentialValues(originalJson, solvedDeserializer);
Map<String, String> solvedValues =
getSolvedValues(solvedDeserializer, topAnnotation, botAnnotation);
updateJaif(solvedValues, existentialValues, jaifFilename, outputFilename);
}
/**
* Parses the inference.jaif file provided by verigames.jar and updates the variable values with
* a boolean of true/false depending on the results obtained from the updates xml file after the
* user plays the game.
*
* @param values Map<String, Boolean> where the integer is the variable id and the boolean is
* the value to replace the variable id with.
* @param existentialValues
* @throws FileNotFoundException thrown if the file inference.jaif is not found in the current
* directory.
*/
private static void updateJaif(
Map<String, String> values,
Map<String, Boolean> existentialValues,
String jaifPath,
String outputFile)
throws FileNotFoundException {
if (values == null) {
throw new IllegalArgumentException("Map passed must not be null");
}
try (Scanner in = new Scanner(new File(jaifPath));
PrintStream out = new PrintStream(new File(outputFile))) {
while (in.hasNextLine()) {
String line = in.nextLine();
int start = -1;
if ((start = line.indexOf(CHECKERS_INFERENCE_QUALS_VAR_ANNOT)) != -1) {
int end = start + (CHECKERS_INFERENCE_QUALS_VAR_ANNOT.length());
String key = line.substring(end, line.length() - 1);
if (values.get(key) == null) {
System.out.println(
"Warning: Could not find value for "
+ key
+ " using supertype, skipping");
} else {
Boolean exists = existentialValues.get(key);
if (exists == null || exists) {
out.print(line.substring(0, start));
out.println(values.get(key));
}
}
} else out.println(line);
}
}
}
private static final Map<String, Boolean> getExistentialValues(
String originalJsonFilename, JsonDeserializer solvedDeserializer)
throws IOException, ParseException {
String json = readFile(originalJsonFilename);
JsonDeserializer deserializer = new JsonDeserializer(null, json);
List<String> allPotentialVariables = deserializer.getPotentialVariables();
Set<String> enabledVars = solvedDeserializer.getEnabledVars();
Map<String, Boolean> out = new LinkedHashMap<>();
for (String potentialVar : allPotentialVariables) {
out.put(potentialVar, enabledVars.contains(potentialVar));
}
return out;
}
private static final Map<String, String> getSolvedValues(
JsonDeserializer deserializer, String top, String bottom)
throws IOException, ParseException {
Map<String, String> values = deserializer.getAnnotationValues();
Map<String, String> results = new HashMap<>();
for (Map.Entry<String, String> entry : values.entrySet()) {
String value = entry.getValue().equals("0") ? bottom : top;
results.put(entry.getKey(), value);
}
return results;
}
static String readFile(String path) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, Charset.defaultCharset());
}
}