Skip to content

Method: getEntityClass(Class)

1: /**
2: * Copyright (C) 2019 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jopa.model.metamodel;
14:
15: import cz.cvut.kbss.jopa.exception.MetamodelInitializationException;
16: import cz.cvut.kbss.jopa.loaders.PersistenceUnitClassFinder;
17: import cz.cvut.kbss.jopa.model.annotations.Inheritance;
18: import cz.cvut.kbss.jopa.query.NamedQueryManager;
19: import cz.cvut.kbss.jopa.query.ResultSetMappingManager;
20: import cz.cvut.kbss.jopa.query.mapper.ResultSetMappingProcessor;
21: import cz.cvut.kbss.jopa.utils.Constants;
22: import org.slf4j.Logger;
23: import org.slf4j.LoggerFactory;
24:
25: import java.lang.reflect.Field;
26: import java.util.*;
27:
28: public class MetamodelBuilder {
29:
30: private static final Logger LOG = LoggerFactory.getLogger(MetamodelBuilder.class);
31:
32: private final NamedNativeQueryProcessor queryProcessor = new NamedNativeQueryProcessor();
33: private final ResultSetMappingProcessor mappingProcessor;
34:
35: private final Map<Class<?>, AbstractIdentifiableType<?>> typeMap = new HashMap<>();
36: private final Set<Class<?>> inferredClasses = new HashSet<>();
37:
38: private final ConverterResolver converterResolver = new ConverterResolver(new Converters());
39:
40: public MetamodelBuilder() {
41: this.mappingProcessor = new ResultSetMappingProcessor(this);
42: }
43:
44: /**
45: * Builds persistence unit metamodel based on classes discovered by the specified class finder.
46: *
47: * @param classFinder Holder of information about classes relevant for persistence unit building
48: */
49: public void buildMetamodel(PersistenceUnitClassFinder classFinder) {
50: classFinder.getEntities().forEach(this::processOWLClass);
51: classFinder.getResultSetMappings().forEach(mappingProcessor::buildMapper);
52: }
53:
54: private <X> void processOWLClass(final Class<X> cls) {
55: if (typeMap.containsKey(cls)) {
56: return;
57: }
58:
59: LOG.debug("Processing OWL class: {}", cls);
60:
61: final TypeBuilderContext<X> et = ManagedClassProcessor.processManagedType(cls);
62: et.setConverterResolver(converterResolver);
63:
64: processManagedType(et);
65: }
66:
67: private <X> void processManagedType(TypeBuilderContext<X> context) {
68: final AbstractIdentifiableType<X> type = context.getType();
69: final Class<X> cls = type.getJavaType();
70: typeMap.put(cls, type);
71:
72: final AbstractIdentifiableType<? super X> supertype = processSupertypes(cls);
73: if (supertype != null) {
74: type.setSupertype(supertype);
75: }
76: type.setLifecycleListenerManager(new EntityLifecycleCallbackResolver(type).resolve());
77:
78: final ClassFieldMetamodelProcessor<X> fieldProcessor = new ClassFieldMetamodelProcessor<>(context, this);
79:
80: for (Field f : cls.getDeclaredFields()) {
81: fieldProcessor.processField(f);
82: }
83:
84: if (type.getPersistenceType() == Type.PersistenceType.ENTITY) {
85: try {
86: type.getIdentifier();
87: } catch (IllegalArgumentException e) {
88: throw new MetamodelInitializationException("Missing identifier field in entity " + cls);
89: }
90: resolveInheritanceType((EntityTypeImpl<X>) type);
91: }
92:
93: queryProcessor.processClass(cls);
94: }
95:
96: private <X> AbstractIdentifiableType<? super X> processSupertypes(Class<X> cls) {
97: final Class<? super X> managedSupertype = ManagedClassProcessor.getManagedSupertype(cls);
98: if (managedSupertype != null) {
99: if (typeMap.containsKey(managedSupertype)) {
100: return (AbstractIdentifiableType<? super X>) typeMap.get(managedSupertype);
101: }
102: final TypeBuilderContext<? super X> context = ManagedClassProcessor.processManagedType(managedSupertype);
103: context.setConverterResolver(converterResolver);
104: processManagedType(context);
105: return context.getType();
106: }
107: return null;
108: }
109:
110: private static <X> void resolveInheritanceType(EntityTypeImpl<X> et) {
111: final Class<X> cls = et.getJavaType();
112: final Inheritance inheritance = cls.getDeclaredAnnotation(Inheritance.class);
113: if (inheritance != null) {
114: if (et.getSupertype() != null &&
115: et.getSupertype().getPersistenceType() != Type.PersistenceType.MAPPED_SUPERCLASS) {
116: throw new MetamodelInitializationException("Class " + cls +
117: " cannot declare inheritance strategy, because it already inherits it from its supertype.");
118: }
119: et.setInheritanceType(inheritance.strategy());
120: } else {
121: et.setInheritanceType(Constants.DEFAULT_INHERITANCE_TYPE);
122: }
123: }
124:
125: public Map<Class<?>, ManagedType<?>> getTypeMap() {
126: return Collections.unmodifiableMap(typeMap);
127: }
128:
129: public <X> AbstractIdentifiableType<X> entity(Class<X> cls) {
130: return (AbstractIdentifiableType<X>) typeMap.get(cls);
131: }
132:
133: public Map<Class<?>, EntityType<?>> getEntities() {
134: final Map<Class<?>, EntityType<?>> map = new HashMap<>();
135: typeMap.entrySet().stream().filter(e -> e.getValue().getPersistenceType() == Type.PersistenceType.ENTITY)
136: .forEach(e -> map.put(e.getKey(), (EntityType<?>) e.getValue()));
137: return map;
138: }
139:
140: public Set<Class<?>> getInferredClasses() {
141: return Collections.unmodifiableSet(inferredClasses);
142: }
143:
144: public NamedQueryManager getNamedQueryManager() {
145: return queryProcessor.getQueryManager();
146: }
147:
148: public ResultSetMappingManager getResultSetMappingManager() {
149: return mappingProcessor.getManager();
150: }
151:
152: void addInferredClass(Class<?> cls) {
153: inferredClasses.add(cls);
154: }
155:
156: @SuppressWarnings("unchecked")
157: <X> ManagedType<X> getEntityClass(Class<X> cls) {
158:• if (!typeMap.containsKey(cls)) {
159: processOWLClass(cls);
160: }
161: return (ManagedType<X>) typeMap.get(cls);
162: }
163: }