Package: ConstructorResultMapper
ConstructorResultMapper
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ConstructorResultMapper(Class) |
|
|
|
|
|
||||||||||||||||||||
addParameterMapper(VariableResultMapper) |
|
|
|
|
|
||||||||||||||||||||
buildInstance(Object[], Class[]) |
|
|
|
|
|
||||||||||||||||||||
getParamMappers() |
|
|
|
|
|
||||||||||||||||||||
getTargetType() |
|
|
|
|
|
||||||||||||||||||||
map(ResultRow, UnitOfWorkImpl) |
|
|
|
|
|
||||||||||||||||||||
resolveConstructor(Class[]) |
|
|
|
|
|
Coverage
1: /**
2: * Copyright (C) 2023 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.mapper;
16:
17: import cz.cvut.kbss.jopa.exception.SparqlResultMappingException;
18: import cz.cvut.kbss.jopa.sessions.UnitOfWorkImpl;
19: import cz.cvut.kbss.ontodriver.iteration.ResultRow;
20: import cz.cvut.kbss.ontodriver.model.LangString;
21:
22: import java.lang.reflect.Constructor;
23: import java.lang.reflect.InvocationTargetException;
24: import java.util.ArrayList;
25: import java.util.Arrays;
26: import java.util.Collections;
27: import java.util.List;
28:
29: /**
30: * Maps SPARQL query result to target value using a constructor configured via a {@link
31: * cz.cvut.kbss.jopa.model.annotations.ConstructorResult} configuration.
32: */
33: class ConstructorResultMapper implements SparqlResultMapper {
34:
35: private final Class<?> targetType;
36:
37: private final List<VariableResultMapper> paramMappers = new ArrayList<>();
38:
39: ConstructorResultMapper(Class<?> targetType) {
40: this.targetType = targetType;
41: }
42:
43: Class<?> getTargetType() {
44: return targetType;
45: }
46:
47: List<VariableResultMapper> getParamMappers() {
48: return Collections.unmodifiableList(paramMappers);
49: }
50:
51: void addParameterMapper(VariableResultMapper mapper) {
52: paramMappers.add(mapper);
53: }
54:
55: @Override
56: public Object map(ResultRow resultRow, UnitOfWorkImpl uow) {
57: final Object[] values = new Object[paramMappers.size()];
58: final Class<?>[] types = new Class[paramMappers.size()];
59:• for (int i = 0; i < paramMappers.size(); i++) {
60: values[i] = paramMappers.get(i).map(resultRow, uow);
61:• types[i] = values[i] != null ? values[i].getClass() : paramMappers.get(i).getTargetType();
62: }
63: return buildInstance(values, types);
64: }
65:
66: private Object buildInstance(Object[] values, Class<?>[] types) {
67: try {
68: final Constructor<?> ctor = resolveConstructor(types);
69:• if (!ctor.canAccess(null)) {
70: ctor.setAccessible(true);
71: }
72: return ctor.newInstance(values);
73: } catch (NoSuchMethodException e) {
74: throw new SparqlResultMappingException(
75: String.format("No matching constructor for values %s found in type %s.", Arrays.toString(values),
76: targetType), e);
77: } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
78: throw new SparqlResultMappingException(
79: String.format("Unable to map values %s to type %s.", Arrays.toString(values), targetType), e);
80: }
81: }
82:
83: private Constructor<?> resolveConstructor(Class<?>[] types) throws NoSuchMethodException {
84: try {
85: return targetType.getDeclaredConstructor(types);
86: } catch (NoSuchMethodException e) {
87: boolean replaced = false;
88: // Try replacing LangString with String and finding a constructor then
89:• for (int i = 0; i < types.length; i++) {
90:• if (types[i].equals(LangString.class)) {
91: replaced = true;
92: types[i] = String.class;
93: }
94: }
95:• if (replaced) {
96: return targetType.getDeclaredConstructor(types);
97: }
98: throw e;
99: }
100: }
101: }