Package: SparqlQueryParser
SparqlQueryParser
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SparqlQueryParser(ParameterValueFactory) |
|
|
|
|
|
||||||||||||||||||||
getQueryParameter(Integer) |
|
|
|
|
|
||||||||||||||||||||
getQueryParameter(String) |
|
|
|
|
|
||||||||||||||||||||
parameterEnd(int) |
|
|
|
|
|
||||||||||||||||||||
parameterStart(int, SparqlQueryParser.ParamType) |
|
|
|
|
|
||||||||||||||||||||
parseQuery(String) |
|
|
|
|
|
||||||||||||||||||||
resolveParamIdentification(String) |
|
|
|
|
|
Coverage
1: /**
2: * Copyright (C) 2022 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.query.sparql;
16:
17: import cz.cvut.kbss.jopa.exception.QueryParserException;
18: import cz.cvut.kbss.jopa.query.QueryParameter;
19: import cz.cvut.kbss.jopa.query.QueryParser;
20: import cz.cvut.kbss.jopa.query.parameter.ParameterValueFactory;
21:
22: import java.util.ArrayList;
23: import java.util.HashMap;
24: import java.util.List;
25: import java.util.Map;
26:
27: public class SparqlQueryParser implements QueryParser {
28:
29: private final ParameterValueFactory parameterValueFactory;
30:
31: private String query;
32:
33: private Map<Object, QueryParameter<?>> uniqueParams;
34: private Integer positionalCounter;
35:
36: private List<String> queryParts;
37: private List<QueryParameter<?>> parameters;
38: private boolean inParam;
39: private boolean inSQString; // In apostrophe string (')
40: private boolean inDQString; // In double-quoted string (")
41: private int lastParamEndIndex;
42: private int paramStartIndex;
43: private ParamType currentParamType;
44:
45: public SparqlQueryParser(ParameterValueFactory parameterValueFactory) {
46: this.parameterValueFactory = parameterValueFactory;
47: }
48:
49: private enum ParamType {
50: POSITIONAL, NAMED
51: }
52:
53:
54: @Override
55: public SparqlQueryHolder parseQuery(String query) {
56: this.query = query;
57: this.queryParts = new ArrayList<>();
58: this.uniqueParams = new HashMap<>();
59: this.positionalCounter = 1;
60: this.parameters = new ArrayList<>();
61: this.inSQString = false;
62: // In double-quoted string
63: this.inDQString = false;
64: this.inParam = false;
65: this.lastParamEndIndex = 0;
66: this.paramStartIndex = 0;
67: this.currentParamType = null;
68: int i;
69:• for (i = 0; i < query.length(); i++) {
70: final char c = query.charAt(i);
71:• switch (c) {
72: case '\'':
73:• inSQString = !inSQString;
74: break;
75: case '"':
76:• inDQString = !inDQString;
77: break;
78: case '$':
79: parameterStart(i, ParamType.POSITIONAL);
80: break;
81: case '?':
82:• if (inParam) {
83: parameterEnd(i); // Property path zero or one
84: } else {
85: parameterStart(i, ParamType.NAMED);
86: }
87: break;
88: // TODO Use an algebra and AST to parse queries
89: case '<':
90: case '>':
91: case ',':
92: case '\n':
93: case '\r':
94: case ')':
95: case ' ':
96: case '.':
97: case ';':
98: case '{':
99: case '}':
100: case '[':
101: case ']':
102: case '+':
103: case '*':
104: case '/':
105: case '|':
106:• if (inParam) {
107: parameterEnd(i);
108: }
109: break;
110: default:
111: break;
112: }
113: }
114:• if (inParam) {
115: parameterEnd(i);
116: } else {
117: queryParts.add(query.substring(lastParamEndIndex));
118: }
119: return new SparqlQueryHolder(query, queryParts, parameters);
120: }
121:
122: private void parameterStart(int index, ParamType paramType) {
123:• if (!inSQString && !inDQString) {
124: queryParts.add(query.substring(lastParamEndIndex, index));
125: paramStartIndex = index + 1;
126: inParam = true;
127: this.currentParamType = paramType;
128: }
129: }
130:
131: private void parameterEnd(int index) {
132: this.lastParamEndIndex = index;
133: this.inParam = false;
134: final String param = query.substring(paramStartIndex, index);
135: parameters.add(resolveParamIdentification(param));
136: }
137:
138: private QueryParameter<?> resolveParamIdentification(String identification) {
139: final QueryParameter<?> queryParameter;
140:• if (identification.isEmpty()) {
141:• if (currentParamType == ParamType.POSITIONAL) {
142: queryParameter = getQueryParameter(positionalCounter++);
143: } else {
144: throw new QueryParserException("Missing parameter name in query " + query);
145: }
146: } else {
147:• if (currentParamType == ParamType.POSITIONAL) {
148: try {
149: Integer position = Integer.parseInt(identification);
150: positionalCounter++;
151: queryParameter = getQueryParameter(position);
152: } catch (NumberFormatException e) {
153: throw new QueryParserException(identification + " is not a valid parameter position.", e);
154: }
155: } else {
156: queryParameter = getQueryParameter(identification);
157: }
158: }
159: return queryParameter;
160: }
161:
162: private QueryParameter<?> getQueryParameter(String name) {
163: // We want to reuse the param instances, so that changes to them apply throughout the whole query
164:• if (!uniqueParams.containsKey(name)) {
165: uniqueParams.put(name, new QueryParameter<>(name, parameterValueFactory));
166: }
167: return uniqueParams.get(name);
168: }
169:
170: private QueryParameter<?> getQueryParameter(Integer position) {
171: // We want to reuse the param instances, so that changes to them apply throughout the whole query
172:• if (uniqueParams.containsKey(position)) {
173: throw new QueryParserException("Parameter with position " + position + " already found in query " + query);
174: }
175: final QueryParameter<?> qp = new QueryParameter<>(position, parameterValueFactory);
176: uniqueParams.put(position, qp);
177: return qp;
178: }
179: }