Skip to content

Method: MetamodelBuilder()

1: /**
2: * Copyright (C) 2016 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.model.metamodel;
16:
17: import cz.cvut.kbss.jopa.exception.MetamodelInitializationException;
18: import cz.cvut.kbss.jopa.model.annotations.Inheritance;
19: import cz.cvut.kbss.jopa.query.NamedQueryManager;
20: import cz.cvut.kbss.jopa.utils.Constants;
21: import org.slf4j.Logger;
22: import org.slf4j.LoggerFactory;
23:
24: import java.lang.reflect.Field;
25: import java.util.*;
26:
27: public class MetamodelBuilder {
28:
29: private static final Logger LOG = LoggerFactory.getLogger(MetamodelBuilder.class);
30:
31: private final NamedNativeQueryProcessor queryProcessor;
32:
33: private final Map<Class<?>, AbstractIdentifiableType<?>> typeMap = new HashMap<>();
34: private final Set<Class<?>> inferredClasses = new HashSet<>();
35: private final NamedQueryManager namedQueryManager = new NamedQueryManager();
36:
37: public MetamodelBuilder() {
38: this.queryProcessor = new NamedNativeQueryProcessor(namedQueryManager);
39: }
40:
41: /**
42: * Builds persistence unit metamodel from the specified set of entities.
43: *
44: * @param entities Entities declared for the persistence unit
45: */
46: public void buildMetamodel(Set<Class<?>> entities) {
47: entities.forEach(this::processOWLClass);
48: }
49:
50: private <X> void processOWLClass(final Class<X> cls) {
51: if (typeMap.containsKey(cls)) {
52: return;
53: }
54:
55: LOG.debug("Processing OWL class: {}", cls);
56:
57: final AbstractIdentifiableType<X> et = ManagedClassProcessor.processManagedType(cls);
58:
59: processManagedType(et);
60: }
61:
62: private <X> void processManagedType(AbstractIdentifiableType<X> type) {
63: final Class<X> cls = type.getJavaType();
64: typeMap.put(cls, type);
65:
66: final AbstractIdentifiableType<? super X> supertype = processSupertypes(cls);
67: if (supertype != null) {
68: type.setSupertype(supertype);
69: }
70:
71: final ClassFieldMetamodelProcessor<X> fieldProcessor = new ClassFieldMetamodelProcessor<>(cls, type, this);
72:
73: for (Field f : cls.getDeclaredFields()) {
74: fieldProcessor.processField(f);
75: }
76:
77: if (type.getPersistenceType() == Type.PersistenceType.ENTITY) {
78: try {
79: type.getIdentifier();
80: } catch (IllegalArgumentException e) {
81: throw new MetamodelInitializationException("Missing identifier field in entity " + cls);
82: }
83: resolveInheritanceType((EntityTypeImpl<X>) type);
84: }
85:
86: queryProcessor.processClass(cls);
87: }
88:
89: private <X> AbstractIdentifiableType<? super X> processSupertypes(Class<X> cls) {
90: final Class<? super X> managedSupertype = ManagedClassProcessor.getManagedSupertype(cls);
91: if (managedSupertype != null) {
92: if (typeMap.containsKey(managedSupertype)) {
93: return (AbstractIdentifiableType<? super X>) typeMap.get(managedSupertype);
94: }
95: final AbstractIdentifiableType<? super X> type = ManagedClassProcessor.processManagedType(managedSupertype);
96: processManagedType(type);
97: return type;
98: }
99: return null;
100: }
101:
102: private <X> void resolveInheritanceType(EntityTypeImpl<X> et) {
103: final Class<X> cls = et.getJavaType();
104: final Inheritance inheritance = cls.getDeclaredAnnotation(Inheritance.class);
105: if (inheritance != null) {
106: if (et.getSupertype() != null &&
107: et.getSupertype().getPersistenceType() != Type.PersistenceType.MAPPED_SUPERCLASS) {
108: throw new MetamodelInitializationException("Class " + cls +
109: " cannot declare inheritance strategy, because it already inherits it from its supertype.");
110: }
111: et.setInheritanceType(inheritance.strategy());
112: } else {
113: et.setInheritanceType(Constants.DEFAULT_INHERITANCE_TYPE);
114: }
115: }
116:
117: public Map<Class<?>, ManagedType<?>> getTypeMap() {
118: return Collections.unmodifiableMap(typeMap);
119: }
120:
121: public Map<Class<?>, EntityType<?>> getEntities() {
122: final Map<Class<?>, EntityType<?>> map = new HashMap<>();
123: typeMap.entrySet().stream().filter(e -> e.getValue().getPersistenceType() == Type.PersistenceType.ENTITY)
124: .forEach(e -> map.put(e.getKey(), (EntityType<?>) e.getValue()));
125: return map;
126: }
127:
128: public Set<Class<?>> getInferredClasses() {
129: return Collections.unmodifiableSet(inferredClasses);
130: }
131:
132: public NamedQueryManager getNamedQueryManager() {
133: return namedQueryManager;
134: }
135:
136: void addInferredClass(Class<?> cls) {
137: inferredClasses.add(cls);
138: }
139:
140: @SuppressWarnings("unchecked")
141: <X> ManagedType<X> getEntityClass(Class<X> cls) {
142: if (!typeMap.containsKey(cls)) {
143: processOWLClass(cls);
144: }
145: return (ManagedType<X>) typeMap.get(cls);
146: }
147: }