1 package org.metricshub.winrm;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 import java.util.stream.Collectors;
34 import org.metricshub.winrm.exceptions.WqlQuerySyntaxException;
35
36 public class WqlQuery {
37
38
39
40
41
42
43
44
45
46
47 private static final Pattern WQL_PATTERN = Pattern.compile(
48 "^\\s*(SELECT\\s+(?:\\*|([a-z0-9._]+(?:\\s*,\\s*[a-z0-9._]+)*))\\s+FROM\\s+)?(?:((?:ASSOCIATORS|REFERENCES)\\s+OF\\s+\\{.*\\})|([a-z0-9_]+))(\\s+WHERE\\s*+.+)?\\s*$",
49 Pattern.CASE_INSENSITIVE | Pattern.DOTALL
50 );
51
52 private String wql;
53 private List<String> selectedProperties;
54 private Map<String, Set<String>> subPropertiesMap;
55 private String cleanWql;
56
57 private WqlQuery(
58 String wql,
59 List<String> selectedProperties,
60 Map<String, Set<String>> subPropertiesMap,
61 String cleanWql
62 ) {
63 this.wql = wql;
64 this.selectedProperties = selectedProperties;
65 this.subPropertiesMap = subPropertiesMap;
66 this.cleanWql = cleanWql;
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public static WqlQuery newInstance(CharSequence wql) throws WqlQuerySyntaxException {
88 Utils.checkNonNull(wql, "wql");
89
90 Matcher wqlMatcher = WQL_PATTERN.matcher(wql);
91
92
93 if (!wqlMatcher.find()) {
94 throw new WqlQuerySyntaxException(wql.toString());
95 }
96
97
98 String selectFragment = wqlMatcher.group(1);
99 String propertiesFragment = wqlMatcher.group(2);
100 String associatorsFragment = wqlMatcher.group(3);
101 String classFragment = wqlMatcher.group(4);
102 String restFragment = wqlMatcher.group(5);
103
104
105 if (selectFragment == null && associatorsFragment == null) {
106 throw new WqlQuerySyntaxException(wql.toString());
107 }
108
109 List<String> properties = buildSelectedProperties(propertiesFragment);
110 Map<String, Set<String>> subPropertiesMap = buildSupPropertiesMap(properties);
111 String cleanWql = buildCleanWql(associatorsFragment, subPropertiesMap, classFragment, restFragment);
112
113 return new WqlQuery(wql.toString(), properties, subPropertiesMap, cleanWql);
114 }
115
116
117
118
119
120
121 static List<String> buildSelectedProperties(String propertiesFragment) {
122 if (Utils.isNotBlank(propertiesFragment)) {
123 return Arrays.asList(propertiesFragment.trim().toLowerCase().split("\\s*,\\s*"));
124 }
125 return new ArrayList<>();
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 static Map<String, Set<String>> buildSupPropertiesMap(final List<String> properties) {
146
147 if (properties == null || properties.isEmpty()) {
148 return new HashMap<>();
149 }
150
151 Map<String, Set<String>> subPropertiesMap = new LinkedHashMap<>();
152 properties
153 .stream()
154 .filter(Utils::isNotBlank)
155 .forEachOrdered(property -> {
156
157
158
159 String[] propertyFragmentArray = property.toLowerCase().split("\\.", 2);
160 String mainProperty = propertyFragmentArray[0];
161 String subProperty = propertyFragmentArray.length == 2 ? propertyFragmentArray[1] : null;
162
163
164 subPropertiesMap.compute(
165 mainProperty,
166 (key, subPropertiesSet) -> {
167 if (subPropertiesSet == null) {
168 subPropertiesSet = new HashSet<>();
169 }
170 if (subProperty != null) {
171 subPropertiesSet.add(subProperty);
172 }
173 return subPropertiesSet;
174 }
175 );
176 });
177
178 return subPropertiesMap;
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 static String buildCleanWql(
202 String associatorsFragment,
203 Map<String, Set<String>> subPropertiesMap,
204 String classFragment,
205 String restFragment
206 ) {
207 String cleanWql;
208
209 if (associatorsFragment == null) {
210 if (subPropertiesMap.keySet().isEmpty()) {
211 cleanWql = "SELECT * FROM " + classFragment;
212 } else {
213 cleanWql =
214 String.format(
215 "SELECT %s FROM %s",
216 subPropertiesMap.keySet().stream().collect(Collectors.joining(",")),
217 classFragment
218 );
219 }
220 } else {
221 cleanWql = associatorsFragment;
222 }
223 if (restFragment != null) {
224 cleanWql = cleanWql + restFragment;
225 }
226 return cleanWql;
227 }
228
229 public List<String> getSelectedProperties() {
230 return selectedProperties;
231 }
232
233 public Map<String, Set<String>> getSubPropertiesMap() {
234 return subPropertiesMap;
235 }
236
237 public String getCleanWql() {
238 return cleanWql;
239 }
240
241 @Override
242 public String toString() {
243 return wql;
244 }
245 }