forked from Mwexim/skript-parser
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathVariableMap.java
More file actions
160 lines (150 loc) · 5.52 KB
/
VariableMap.java
File metadata and controls
160 lines (150 loc) · 5.52 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
158
159
160
package io.github.syst3ms.skriptparser.variables;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.regex.Pattern;
public class VariableMap {
/**
* If all indexes are numerical, they should be ordered likewise. If not, natural order should take place.
*/
private static final Comparator<String> NUMERIC_INDEX_COMPARATOR = Comparator.comparingInt(Integer::parseInt);
private final Map<String, Object> hashMap = new HashMap<>(); // Ordering is not important right now
private final Map<String, Object> treeMap = new TreeMap<>();
public Map<String, Object> getMap() {
return this.hashMap;
}
private static String[] splitList(String name) {
return Pattern.compile(Pattern.quote(Variables.LIST_SEPARATOR)).split(name);
}
/**
* Returns the internal value of the requested variable.
* <p>
* <b>Do not modify the returned value!</b>
*
* @param name name of the variable
* @return an Object for a normal Variable or a Map<String, Object> for a list variable, or null if the variable is not set.
*/
@SuppressWarnings("unchecked")
public Optional<Object> getVariable(String name) {
if (!name.endsWith("*")) {
return Optional.ofNullable(hashMap.get(name));
} else {
var split = splitList(name);
var current = treeMap;
for (var i = 0; i < split.length; i++) {
var n = split[i];
if (n.equals("*")) {
assert i == split.length - 1;
return Optional.of(current);
}
var o = current.get(n);
if (o == null) {
return Optional.empty();
}
if (o instanceof Map) {
current = (Map<String, Object>) o;
assert i != split.length - 1;
} else {
return Optional.empty();
}
}
return Optional.empty();
}
}
/**
* Sets a variable.
*
* @param name The variable's name. Can be a "list variable::*" (<tt>value</tt> must be <tt>null</tt> in this case)
* @param value The variable's value. Use <tt>null</tt> to delete the variable.
*/
@SuppressWarnings("unchecked")
public void setVariable(String name, @Nullable Object value) {
if (!name.endsWith("*")) {
if (value == null) {
hashMap.remove(name);
} else {
hashMap.put(name, value);
}
}
var split = splitList(name);
var parent = treeMap;
for (var i = 0; i < split.length; i++) {
var n = split[i];
var current = parent.get(n);
if (current == null) {
if (i == split.length - 1) {
if (value != null) {
parent.put(n, value);
}
break;
} else if (value != null) {
parent.put(n, current = new HashMap<>());
parent = (Map<String, Object>) current;
} else {
break;
}
} else if (current instanceof Map) {
if (i == split.length - 1) {
if (value == null) {
((Map<String, Object>) current).remove(null);
} else {
((Map<String, Object>) current).put(null, value);
}
break;
} else if (i == split.length - 2 && split[i + 1].equals("*")) {
assert value == null;
deleteFromHashMap(String
.join(Variables.LIST_SEPARATOR, Arrays.copyOfRange(split, 0, i + 1)), (Map<String, Object>) current);
var v = ((Map<String, Object>) current).get(null);
if (v == null) {
parent.remove(n);
} else {
parent.put(n, v);
}
break;
} else {
parent = (Map<String, Object>) current;
}
} else {
if (i == split.length - 1) {
if (value == null) {
parent.remove(n);
} else {
parent.put(n, value);
}
break;
} else if (value != null) {
Map<String, Object> c = new HashMap<>();
c.put(null, current);
parent.put(n, c);
parent = c;
} else {
break;
}
}
}
}
/**
* Clears all variables
*/
public void clearVariables() {
hashMap.clear();
}
@SuppressWarnings("unchecked")
private void deleteFromHashMap(String parent, Map<String, Object> current) {
for (var e : current.entrySet()) {
if (e.getKey() == null) {
continue;
}
hashMap.remove(parent + Variables.LIST_SEPARATOR + e.getKey());
var val = e.getValue();
if (val instanceof Map) {
deleteFromHashMap(parent + Variables.LIST_SEPARATOR + e.getKey(), (Map<String, Object>) val);
}
}
}
}