1 package org.metricshub.wbem.client;
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.HashMap;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Optional;
28 import java.util.Set;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33 import org.metricshub.wbem.client.exceptions.WqlQuerySyntaxException;
34
35
36
37
38
39 public class WqlQuery {
40
41 private WqlQuery() {}
42
43 private static final String ID = "[^\\s]+";
44 private static final String LIST_SEPARATOR = "\\s*,\\s*";
45
46 private static final Pattern CHECK_SELECT_PATTERN = Pattern.compile(
47 "^\\s*SELECT\\s+(\\*|(?!SELECT|FROM|WHERE)\\w+|((?!SELECT|FROM|WHERE)\\w+\\s*,\\s*)+((?!SELECT|FROM|WHERE)\\w+))\\s+FROM\\s+((?!SELECT|WHERE|FROM)\\w+)\\s*?$",
48 Pattern.CASE_INSENSITIVE
49 );
50
51 private static final Pattern EXTRACT_SELECT_PATTERN = Pattern.compile(
52 "^\\s*SELECT\\s+(.+)\\s+FROM\\s+(" + ID + ")\\s*$",
53 Pattern.CASE_INSENSITIVE
54 );
55 private static final int SELECT_GROUP_CLASSNAME = 2;
56 private static final int SELECT_GROUP_FIELDS = 1;
57 private static final int SELECT_GROUP_COUNT = 2;
58
59 private String className;
60 private Set<String> properties;
61 private List<String> originalProperties;
62
63
64
65
66
67
68
69 public static WqlQuery parseQuery(final String query) throws WqlQuerySyntaxException {
70 Utils.checkNonNull(query, "query");
71
72 if (CHECK_SELECT_PATTERN.matcher(query).find()) {
73 final WqlQuery wqlQuery = new WqlQuery();
74 wqlQuery.parseSelect(query);
75 return wqlQuery;
76 }
77 throw new WqlQuerySyntaxException(query);
78 }
79
80 public String getClassName() {
81 return className;
82 }
83
84 public String[] getPropertiesArray() {
85 return properties.isEmpty()
86 ? null
87 : properties
88 .stream()
89 .filter(property -> !WbemCimDataHandler.PATH_PROPERTY.equalsIgnoreCase(property))
90 .toArray(String[]::new);
91 }
92
93 public Set<String> getProperties() {
94 return properties;
95 }
96
97 public List<String> getOriginalProperties() {
98 return originalProperties;
99 }
100
101 public boolean hasDuplicateProperties() {
102 return properties != null && originalProperties != null && properties.size() != originalProperties.size();
103 }
104
105 private void parseSelect(final String query) throws WqlQuerySyntaxException {
106 final Matcher matcher = EXTRACT_SELECT_PATTERN.matcher(query);
107 if (!matcher.find()) {
108 throw new WqlQuerySyntaxException(query);
109 }
110 if (matcher.groupCount() < SELECT_GROUP_COUNT) {
111 throw new WqlQuerySyntaxException(query);
112 }
113
114 className = matcher.group(SELECT_GROUP_CLASSNAME);
115
116 final String fieldsList = matcher.group(SELECT_GROUP_FIELDS);
117 final String[] fieldArray = Optional
118 .ofNullable(fieldsList)
119 .filter(s -> !"*".equals(s))
120 .map(s -> s.split(LIST_SEPARATOR))
121 .orElse(new String[0]);
122
123 originalProperties = Stream.of(fieldArray).map(String::trim).collect(Collectors.toList());
124
125
126 final Map<String, String> originalMap = new HashMap<>();
127 originalProperties
128 .stream()
129 .forEach(property -> originalMap.computeIfAbsent(property.toLowerCase(), prop -> property));
130
131 properties =
132 originalProperties
133 .stream()
134 .map(property -> originalMap.get(property.toLowerCase()))
135 .collect(Collectors.toCollection(LinkedHashSet::new));
136 }
137 }