Skip to content

Package: SparqlQueryParser$ParamType

SparqlQueryParser$ParamType

nameinstructionbranchcomplexitylinemethod
static {...}
M: 0 C: 24
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2019 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:
21: import java.util.ArrayList;
22: import java.util.HashMap;
23: import java.util.List;
24: import java.util.Map;
25:
26: public class SparqlQueryParser implements QueryParser {
27:
28: private String query;
29:
30: private Map<Object, QueryParameter<?>> uniqueParams;
31: private Integer positionalCounter;
32:
33: private List<String> queryParts;
34: private List<QueryParameter<?>> parameters;
35: private boolean inParam;
36: private boolean inSQString; // In apostrophe string (')
37: private boolean inDQString; // In double-quoted string (")
38: private int lastParamEndIndex;
39: private int paramStartIndex;
40: private ParamType currentParamType;
41:
42: private enum ParamType {
43: POSITIONAL, NAMED
44: }
45:
46: @Override
47: public SparqlQueryHolder parseQuery(String query) {
48: this.query = query;
49: this.queryParts = new ArrayList<>();
50: this.uniqueParams = new HashMap<>();
51: this.positionalCounter = 1;
52: this.parameters = new ArrayList<>();
53: this.inSQString = false;
54: // In double-quoted string
55: this.inDQString = false;
56: this.inParam = false;
57: this.lastParamEndIndex = 0;
58: this.paramStartIndex = 0;
59: this.currentParamType = null;
60: int i;
61: for (i = 0; i < query.length(); i++) {
62: final char c = query.charAt(i);
63: switch (c) {
64: case '\'':
65: inSQString = !inSQString;
66: break;
67: case '"':
68: inDQString = !inDQString;
69: break;
70: case '$':
71: parameterStart(i, ParamType.POSITIONAL);
72: break;
73: case '?':
74: if (inParam) {
75: parameterEnd(i); // Property path zero or one
76: } else {
77: parameterStart(i, ParamType.NAMED);
78: }
79: break;
80: // TODO Use an algebra and AST to parse queries
81: case '<':
82: case '>':
83: case ',':
84: case '\n':
85: case ')':
86: case ' ':
87: case '.':
88: case ';':
89: case '{':
90: case '}':
91: case '[':
92: case ']':
93: case '+':
94: case '*':
95: case '/':
96: case '|':
97: if (inParam) {
98: parameterEnd(i);
99: }
100: break;
101: default:
102: break;
103: }
104: }
105: if (inParam) {
106: parameterEnd(i);
107: } else {
108: queryParts.add(query.substring(lastParamEndIndex));
109: }
110: return new SparqlQueryHolder(query, queryParts, parameters);
111: }
112:
113: private void parameterStart(int index, ParamType paramType) {
114: if (!inSQString && !inDQString) {
115: queryParts.add(query.substring(lastParamEndIndex, index));
116: paramStartIndex = index + 1;
117: inParam = true;
118: this.currentParamType = paramType;
119: }
120: }
121:
122: private void parameterEnd(int index) {
123: this.lastParamEndIndex = index;
124: this.inParam = false;
125: final String param = query.substring(paramStartIndex, index);
126: parameters.add(resolveParamIdentification(param));
127: }
128:
129: private QueryParameter<?> resolveParamIdentification(String identification) {
130: final QueryParameter<?> queryParameter;
131: if (identification.isEmpty()) {
132: if (currentParamType == ParamType.POSITIONAL) {
133: queryParameter = getQueryParameter(positionalCounter++);
134: } else {
135: throw new QueryParserException("Missing parameter name in query " + query);
136: }
137: } else {
138: if (currentParamType == ParamType.POSITIONAL) {
139: try {
140: Integer position = Integer.parseInt(identification);
141: positionalCounter++;
142: queryParameter = getQueryParameter(position);
143: } catch (NumberFormatException e) {
144: throw new QueryParserException(identification + " is not a valid parameter position.", e);
145: }
146: } else {
147: queryParameter = getQueryParameter(identification);
148: }
149: }
150: return queryParameter;
151: }
152:
153: private QueryParameter<?> getQueryParameter(String name) {
154: // We want to reuse the param instances, so that changes to them apply throughout the whole query
155: if (!uniqueParams.containsKey(name)) {
156: uniqueParams.put(name, new QueryParameter<>(name));
157: }
158: return uniqueParams.get(name);
159: }
160:
161: private QueryParameter<?> getQueryParameter(Integer position) {
162: // We want to reuse the param instances, so that changes to them apply throughout the whole query
163: if (uniqueParams.containsKey(position)) {
164: throw new QueryParserException("Parameter with position " + position + " already found in query " + query);
165: }
166: final QueryParameter<?> qp = new QueryParameter<>(position);
167: uniqueParams.put(position, qp);
168: return qp;
169: }
170: }