-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathRuleFactory.java
104 lines (85 loc) · 3.28 KB
/
RuleFactory.java
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
package me.earth.headlessmc.launcher.version;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.val;
import me.earth.headlessmc.launcher.os.OS;
import me.earth.headlessmc.launcher.util.JsonUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
class RuleFactory {
public Rule parse(JsonElement jsonElement) {
if (jsonElement == null || !jsonElement.isJsonArray()) {
return Rule.ALLOW;
}
val jsonArray = jsonElement.getAsJsonArray();
val rules = new ArrayList<Rule>(jsonArray.size() + 1);
rules.add(Rule.DISALLOW); // libraries seem to be disallowed by default
for (val ruleElement : jsonArray) {
if (!ruleElement.isJsonObject()) {
continue;
}
val ruleJo = ruleElement.getAsJsonObject();
rules.add(parse(ruleJo));
}
return ofRules(rules);
}
private Rule parse(JsonObject ruleJo) {
val a = ruleJo.get("action");
if (a == null) {
return Rule.UNDECIDED;
}
val action = Rule.Action.valueOf(a.getAsString().toUpperCase(Locale.ENGLISH));
val os = ruleJo.get("os");
val feat = ruleJo.get("features");
val rules = new ArrayList<Rule>(os != null && feat != null ? 3 : 2);
if (os != null) {
rules.add(parseOs(os.getAsJsonObject(), action));
}
if (feat != null) {
val m = JsonUtil.toBoolMap(feat.getAsJsonObject());
rules.add(ofFeature(m, action));
}
if (rules.isEmpty()) {
rules.add((operatingSystem, feature) -> action);
}
return ofRules(rules);
}
private Rule parseOs(JsonObject os, Rule.Action action) {
val osType = os.getAsJsonObject().get("name");
val type = osType == null ? null : osType.getAsString();
Pattern version = null;
val versionObject = os.getAsJsonObject().get("version");
if (versionObject != null) {
version = Pattern.compile(versionObject.getAsString());
}
// val arch = os.getAsJsonObject().get("arch"); TODO: this?
return ofOs(type, version, action);
}
private Rule ofOs(String type, Pattern version, Rule.Action action) {
val osType = type == null ? null : OS.Type.valueOf(type.toUpperCase(Locale.ENGLISH));
return (os, features) -> osType != null && osType != os.getType()
|| version != null && !version.matcher(os.getVersion()).find()
? Rule.Action.UNDECIDED
: action;
}
private Rule ofFeature(Map<String, Boolean> features, Rule.Action action) {
return (os, f) ->
features.entrySet()
.stream()
.allMatch(e -> f.getFeature(e.getKey()) == e.getValue())
? action : Rule.Action.UNDECIDED;
}
private Rule ofRules(List<Rule> rules) {
return (os, features) -> {
Rule.Action result = Rule.Action.UNDECIDED;
for (val rule : rules) {
val action = rule.apply(os, features);
result = action == Rule.Action.UNDECIDED ? result : action;
}
return result;
};
}
}