Skip to content

Package: QueryHintsHandler$Hint

QueryHintsHandler$Hint

nameinstructionbranchcomplexitylinemethod
QueryHintsHandler.Hint(String, Object)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
apply(Object, AbstractQuery, Statement)
M: 0 C: 46
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 9
100%
M: 0 C: 1
100%
apply(String, Object, AbstractQuery, Statement)
M: 0 C: 18
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getSupportedHints()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
initialize()
M: 0 C: 45
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
registerHint(QueryHintsHandler.Hint)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
shouldUseDefault(Object)
M: 0 C: 11
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
toUpperCase(String)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: package cz.cvut.kbss.jopa.model;
2:
3: import cz.cvut.kbss.jopa.query.QueryHints;
4: import cz.cvut.kbss.ontodriver.Statement;
5: import org.slf4j.Logger;
6: import org.slf4j.LoggerFactory;
7:
8: import java.util.HashMap;
9: import java.util.Locale;
10: import java.util.Map;
11: import java.util.Set;
12:
13: /**
14: * Processes query hints.
15: * <p>
16: * To add a new hint (inspired by Eclipselink):
17: * <ul>
18: * <li>Define a hint in {@link QueryHints}</li>
19: * <li>Ad an inner class extending {@link Hint} corresponding to the new hint. The class should implement the
20: * {@link Hint#applyToQuery(Object, AbstractQuery, Statement)} method and provide an array of values for transformation.</li>
21: * <li>Register the new hint class by calling {@link Hint#registerHint(Hint)} with an instance of the hint</li>
22: * </ul>
23: */
24: public class QueryHintsHandler {
25:
26: private static final Logger LOG = LoggerFactory.getLogger(QueryHintsHandler.class);
27:
28: /**
29: * Gets query hints supported by this implementation.
30: *
31: * @return A set of query hint names
32: */
33: public static Set<String> getSupportedHints() {
34: return Hint.getSupportedHints();
35: }
36:
37: /**
38: * Applies the specified hint value to the specified query.
39: * <p>
40: * Note that if the hint is unknown, it is ignored.
41: *
42: * @param hintName Query hint name
43: * @param hintValue Query hint value
44: * @param query Query to apply the hint value to
45: * @param statement OntoDriver statement that will be used to execute the specified query. The hint value may be
46: * applied directly to it
47: * @throws IllegalArgumentException If the hint value is not supported
48: */
49: public static void apply(String hintName, Object hintValue, AbstractQuery query, Statement statement) {
50: Hint.apply(hintName, hintValue, query, statement);
51: }
52:
53: /**
54: * Representation of a query hint.
55: * <p>
56: * The {@code valueArray} ensures that only supported values are provided to {@link #applyToQuery(Object,
57: * AbstractQuery, Statement)}. For example, if a hint is boolean-based and the configuration passes string "true",
58: * it is mapped to {@code true} based on {@code valueMap} which was constructed automatically from {@code
59: * valueArray}.
60: * <p>
61: * The {@code valueArray} is a two-dimensional array where each element is a single value, which in turn is a
62: * two-element array where the first element is a string representation of the value and the second one is the value
63: * itself.
64: */
65: static abstract class Hint {
66:
67: private static final Map<String, Hint> HINTS = new HashMap<>();
68:
69: Object[][] valueArray;
70: HashMap<String, Object> valueMap;
71: Object defaultValue;
72: String name;
73:
74: static {
75: registerHint(new DisableInferenceHint());
76: }
77:
78: Hint(String name, Object defaultValue) {
79: this.name = name;
80: this.defaultValue = defaultValue;
81: }
82:
83: static void registerHint(Hint hint) {
84: hint.initialize();
85: HINTS.put(hint.name, hint);
86: }
87:
88: static Set<String> getSupportedHints() {
89: return HINTS.keySet();
90: }
91:
92: static String toUpperCase(String str) {
93: return str.toUpperCase(Locale.ROOT);
94: }
95:
96: static boolean shouldUseDefault(Object hintValue) {
97:• return hintValue instanceof String && ((String) hintValue).isEmpty();
98: }
99:
100: static void apply(String hintName, Object hintValue, AbstractQuery query, Statement statement) {
101:• if (!HINTS.containsKey(hintName)) {
102: LOG.warn("Unsupported query hint '{}'.", hintName);
103: return;
104: }
105: HINTS.get(hintName).apply(hintValue, query, statement);
106: }
107:
108: void apply(Object hintValue, AbstractQuery query, Statement statement) {
109: Object toApply = hintValue;
110:• if (shouldUseDefault(hintValue)) {
111: toApply = defaultValue;
112:• } else if (valueMap != null) {
113: toApply = valueMap.get(toUpperCase(hintValue.toString()));
114:• if (toApply == null) {
115: throw new IllegalArgumentException("Unsupported value '" + hintValue + "' of hint '" + name + "'.");
116: }
117: }
118: applyToQuery(toApply, query, statement);
119: }
120:
121: void initialize() {
122:• if (valueArray != null) {
123: this.valueMap = new HashMap<>(valueArray.length);
124:• for (Object[] elem : valueArray) {
125: valueMap.put(toUpperCase(elem[0].toString()), elem[1]);
126: }
127: // Don't need it anymore
128: this.valueArray = null;
129: }
130: }
131:
132: /**
133: * Applies the specified value of this hint to the specified query (or statement, if more suitable).
134: *
135: * @param hintValue Value of the hint to apply
136: * @param query Query to apply the value to
137: * @param statement OntoDriver statement that will be used to execute the specified query. The hint value may be
138: * applied directly to it
139: */
140: abstract void applyToQuery(Object hintValue, AbstractQuery query, Statement statement);
141: }
142:
143: /**
144: * Allows disabling inference for query execution.
145: *
146: * @see QueryHints#DISABLE_INFERENCE
147: */
148: protected static class DisableInferenceHint extends Hint {
149: DisableInferenceHint() {
150: super(QueryHints.DISABLE_INFERENCE, Boolean.FALSE);
151: this.valueArray =
152: new Object[][]{{Boolean.TRUE.toString(), Boolean.TRUE}, {Boolean.FALSE.toString(), Boolean.FALSE},};
153: }
154:
155: @Override
156: void applyToQuery(Object hintValue, AbstractQuery query, Statement statement) {
157: assert statement != null;
158: if (Boolean.TRUE == hintValue) {
159: statement.disableInference();
160: }
161: }
162: }
163: }