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