Skip to content

Method: getManager()

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.model.annotations.*;
22: import cz.cvut.kbss.jopa.model.metamodel.*;
23: import cz.cvut.kbss.jopa.query.ResultSetMappingManager;
24: import org.slf4j.Logger;
25: import org.slf4j.LoggerFactory;
26:
27: import java.util.*;
28: import java.util.stream.Collectors;
29:
30: /**
31: * Builds mappers for {@link SparqlResultSetMapping} instances discovered on classpath.
32: */
33: public class ResultSetMappingProcessor {
34:
35: private static final Logger LOG = LoggerFactory.getLogger(ResultSetMappingProcessor.class);
36:
37: private final ResultSetMappingManager manager = new ResultSetMappingManager();
38:
39: private final MetamodelBuilder metamodelBuilder;
40:
41: public ResultSetMappingProcessor(MetamodelBuilder metamodelBuilder) {
42: this.metamodelBuilder = metamodelBuilder;
43: }
44:
45: /**
46: * Builds result set mapper for the specified mapping.
47: *
48: * @param mapping Mapping configuration
49: */
50: public void buildMapper(SparqlResultSetMapping mapping) {
51: Objects.requireNonNull(mapping);
52: final ResultRowMapper rowMapper = new ResultRowMapper(mapping.name());
53: buildVariableMappers(mapping, rowMapper);
54: buildConstructorMappers(mapping, rowMapper);
55: buildEntityMappers(mapping, rowMapper);
56: manager.addMapper(rowMapper.getName(), rowMapper);
57: }
58:
59: private static void buildVariableMappers(SparqlResultSetMapping mapping, ResultRowMapper parent) {
60: for (VariableResult vr : mapping.variables()) {
61: parent.addMapper(new VariableResultMapper(vr));
62: }
63: }
64:
65: private static void buildConstructorMappers(SparqlResultSetMapping mapping, ResultRowMapper parent) {
66: for (ConstructorResult cr : mapping.classes()) {
67: final ConstructorResultMapper mapper = new ConstructorResultMapper(cr.targetClass());
68: for (VariableResult vr : cr.variables()) {
69: mapper.addParameterMapper(new VariableResultMapper(vr));
70: }
71: parent.addMapper(mapper);
72: }
73: }
74:
75: private void buildEntityMappers(SparqlResultSetMapping mapping, ResultRowMapper parent) {
76: for (EntityResult er : mapping.entities()) {
77: final IdentifiableEntityType<?> et = getTargetType(er);
78: final EntityResultMapper<?> etMapper = new EntityResultMapper<>(et);
79: generateFieldMappersForFieldResults(er, et, etMapper);
80: generateFieldMappersForUnconfiguredFields(et, er).forEach(etMapper::addFieldMapper);
81: parent.addMapper(etMapper);
82: }
83: }
84:
85: private IdentifiableEntityType<?> getTargetType(EntityResult er) {
86: final AbstractIdentifiableType<?> targetType = metamodelBuilder.entity(er.entityClass());
87: if (targetType == null || targetType.isAbstract()) {
88: throw new SparqlResultMappingException(
89: "Type " + er.entityClass() +
90: " is not a known instantiable entity type and cannot be used as @EntityResult target class.");
91: }
92: return (IdentifiableEntityType<?>) targetType;
93: }
94:
95: private static void generateFieldMappersForFieldResults(EntityResult er, EntityType<?> et,
96: EntityResultMapper<?> etMapper) {
97: for (FieldResult fr : er.fields()) {
98: try {
99: final FieldSpecification<?, ?> fieldSpec = et.getFieldSpecification(fr.name());
100: createFieldMapper(fr, fieldSpec).ifPresent(etMapper::addFieldMapper);
101: } catch (IllegalArgumentException e) {
102: throw new SparqlResultMappingException(e);
103: }
104: }
105: }
106:
107: private static Optional<FieldResultMapper> createFieldMapper(FieldResult fr, FieldSpecification<?, ?> fieldSpec) {
108: if (fieldSpec.isCollection()) {
109: LOG.warn(
110: "Mapping of plural attributes via @FieldResult is not supported. Check the definition of {}.",
111: fr);
112: return Optional.empty();
113: }
114: if (fieldSpec instanceof Attribute &&
115: ((Attribute) fieldSpec).getPersistentAttributeType() == Attribute.PersistentAttributeType.OBJECT) {
116: return Optional.of(new ObjectPropertyFieldResultMapper(fr, fieldSpec));
117: } else {
118: return Optional.of(new FieldResultMapper(fr, fieldSpec));
119: }
120: }
121:
122: private static List<FieldResultMapper> generateFieldMappersForUnconfiguredFields(EntityType<?> et, EntityResult er) {
123: final Set<String> configuredFields = new HashSet<>(er.fields().length);
124: for (FieldResult fr : er.fields()) {
125: configuredFields.add(fr.name());
126: }
127: return et.getFieldSpecifications().stream()
128: .filter(fs -> !configuredFields.contains(fs.getName()) && !fs.isCollection())
129: .map(ResultSetMappingProcessor::createFieldMapper)
130: .collect(Collectors.toList());
131: }
132:
133: private static FieldResultMapper createFieldMapper(FieldSpecification<?, ?> fieldSpec) {
134: if (fieldSpec instanceof Attribute &&
135: ((Attribute) fieldSpec).getPersistentAttributeType() == Attribute.PersistentAttributeType.OBJECT) {
136: return new ObjectPropertyFieldResultMapper(fieldSpec);
137: } else {
138: return new FieldResultMapper(fieldSpec);
139: }
140: }
141:
142: public ResultSetMappingManager getManager() {
143: return manager;
144: }
145: }