Skip to contentMethod: setHint(String, Object)
1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jopa.model;
19:
20: import cz.cvut.kbss.jopa.exceptions.NoResultException;
21: import cz.cvut.kbss.jopa.exceptions.NoUniqueResultException;
22: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
23: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
24: import cz.cvut.kbss.jopa.model.descriptors.EntityDescriptor;
25: import cz.cvut.kbss.jopa.model.query.Parameter;
26: import cz.cvut.kbss.jopa.model.query.TypedQuery;
27: import cz.cvut.kbss.jopa.query.QueryHolder;
28: import cz.cvut.kbss.jopa.sessions.ConnectionWrapper;
29: import cz.cvut.kbss.jopa.sessions.UnitOfWork;
30: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
31: import cz.cvut.kbss.ontodriver.iteration.ResultRow;
32:
33: import java.net.URI;
34: import java.util.ArrayList;
35: import java.util.List;
36: import java.util.Objects;
37: import java.util.Optional;
38: import java.util.stream.Stream;
39:
40: public class TypedQueryImpl<X> extends AbstractQuery implements TypedQuery<X> {
41:
42: private final Class<X> resultType;
43:
44: private final UnitOfWork uow;
45:
46: private Descriptor descriptor = new EntityDescriptor();
47:
48: public TypedQueryImpl(final QueryHolder query, final Class<X> resultType,
49: final ConnectionWrapper connection, UnitOfWork uow) {
50: super(query, connection);
51: this.resultType = Objects.requireNonNull(resultType);
52: this.uow = Objects.requireNonNull(uow);
53: }
54:
55: @Override
56: public List<X> getResultList() {
57: ensureOpen();
58: try {
59: return getResultListImpl();
60: } catch (OntoDriverException e) {
61: markTransactionForRollback();
62: throw queryEvaluationException(e);
63: } catch (RuntimeException e) {
64: markTransactionForRollback();
65: throw e;
66: }
67: }
68:
69: private List<X> getResultListImpl() throws OntoDriverException {
70: final boolean isEntityType = uow.isEntityType(resultType);
71: final List<X> res = new ArrayList<>();
72: executeQuery(rs -> {
73: if (isEntityType) {
74: loadEntityInstance(rs, descriptor).ifPresent(res::add);
75: } else {
76: loadResultValue(rs).ifPresent(res::add);
77: }
78: });
79: return res;
80: }
81:
82: public Descriptor getDescriptor() {
83: return descriptor;
84: }
85:
86: private Optional<X> loadEntityInstance(ResultRow resultRow, Descriptor instanceDescriptor) {
87: if (uow == null) {
88: throw new IllegalStateException("Cannot load entity instance without Unit of Work.");
89: }
90: try {
91: assert resultRow.isBound(0);
92: final URI uri = URI.create(resultRow.getString(0));
93: return Optional.ofNullable(uow.readObject(resultType, uri, instanceDescriptor));
94: } catch (OntoDriverException e) {
95: throw new OWLPersistenceException("Unable to load query result as entity of type " + resultType, e);
96: }
97: }
98:
99: private Optional<X> loadResultValue(ResultRow resultRow) {
100: try {
101: return Optional.of(resultRow.getObject(0, resultType));
102: } catch (OntoDriverException e) {
103: throw new OWLPersistenceException("Unable to map the query result to class " + resultType, e);
104: }
105: }
106:
107: @Override
108: public X getSingleResult() {
109: ensureOpen();
110: try {
111: final List<X> res = getResultListImpl();
112: if (res.isEmpty()) {
113: throw new NoResultException("No result found for query " + query);
114: }
115: if (res.size() > 1) {
116: throw new NoUniqueResultException("Multiple results found for query " + query);
117: }
118: return res.get(0);
119: } catch (OntoDriverException e) {
120: markTransactionForRollback();
121: throw queryEvaluationException(e);
122: } catch (RuntimeException e) {
123: if (exceptionCausesRollback(e)) {
124: markTransactionForRollback();
125: }
126: throw e;
127: }
128: }
129:
130: @Override
131: public Stream<X> getResultStream() {
132: final boolean isEntityType = uow.isEntityType(resultType);
133: try {
134: return executeQueryForStream(row -> {
135: if (isEntityType) {
136: return loadEntityInstance(row, descriptor);
137: } else {
138: return loadResultValue(row);
139: }
140: });
141: } catch (OntoDriverException e) {
142: markTransactionForRollback();
143: throw queryEvaluationException(e);
144: } catch (RuntimeException e) {
145: if (exceptionCausesRollback(e)) {
146: markTransactionForRollback();
147: }
148: throw e;
149: }
150: }
151:
152: @Override
153: public TypedQuery<X> setMaxResults(int maxResults) {
154: ensureOpen();
155: checkNumericParameter(maxResults, "max results");
156: query.setMaxResults(maxResults);
157: return this;
158: }
159:
160: @Override
161: public TypedQuery<X> setFirstResult(int startPosition) {
162: ensureOpen();
163: checkNumericParameter(startPosition, "first result offset");
164: query.setFirstResult(startPosition);
165: return this;
166: }
167:
168: @Override
169: public TypedQuery<X> setParameter(int position, Object value) {
170: super.setParameter(position, value);
171: return this;
172: }
173:
174: @Override
175: public TypedQuery<X> setParameter(int position, String value, String language) {
176: super.setParameter(position, value, language);
177: return this;
178: }
179:
180: @Override
181: public TypedQuery<X> setParameter(String name, Object value) {
182: super.setParameter(name, value);
183: return this;
184: }
185:
186: @Override
187: public TypedQuery<X> setParameter(String name, String value, String language) {
188: super.setParameter(name, value, language);
189: return this;
190: }
191:
192: @Override
193: public <T> TypedQuery<X> setParameter(Parameter<T> parameter, T value) {
194: super.setParameter(parameter, value);
195: return this;
196: }
197:
198: @Override
199: public TypedQuery<X> setParameter(Parameter<String> parameter, String value, String language) {
200: super.setParameter(parameter, value, language);
201: return this;
202: }
203:
204: @Override
205: public TypedQuery<X> setUntypedParameter(int position, Object value) {
206: super.setUntypedParameter(position, value);
207: return this;
208: }
209:
210: @Override
211: public TypedQuery<X> setUntypedParameter(String name, Object value) {
212: super.setUntypedParameter(name, value);
213: return this;
214: }
215:
216: @Override
217: public <T> TypedQuery<X> setUntypedParameter(Parameter<T> parameter, T value) {
218: super.setUntypedParameter(parameter, value);
219: return this;
220: }
221:
222: @Override
223: public TypedQuery<X> setHint(String hintName, Object value) {
224: super.setHint(hintName, value);
225: return this;
226: }
227:
228: @Override
229: public TypedQuery<X> setDescriptor(Descriptor descriptor) {
230: this.descriptor = Objects.requireNonNull(descriptor);
231: return this;
232: }
233: }