Skip to contentMethod: getInferredClasses()
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;
16:
17: import cz.cvut.kbss.jopa.exception.MetamodelInitializationException;
18: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
19: import cz.cvut.kbss.jopa.loaders.EntityLoader;
20: import cz.cvut.kbss.jopa.model.metamodel.*;
21: import cz.cvut.kbss.jopa.utils.Configuration;
22: import cz.cvut.kbss.ontodriver.config.OntoDriverProperties;
23: import org.slf4j.Logger;
24: import org.slf4j.LoggerFactory;
25:
26: import java.lang.reflect.Field;
27: import java.net.URI;
28: import java.net.URISyntaxException;
29: import java.util.*;
30:
31: public class MetamodelImpl implements Metamodel {
32:
33: private static final Logger LOG = LoggerFactory.getLogger(Metamodel.class);
34:
35: private static final String ASPECTJ_CLASS = "org.aspectj.weaver.loadtime.Agent";
36:
37: private final Map<Class<?>, EntityType<?>> typeMap = new HashMap<>();
38:
39: private final Set<Class<?>> inferredClasses = new HashSet<>();
40:
41: private final Configuration configuration;
42:
43: private Set<URI> moduleExtractionSignature;
44:
45: private final Set<Class<?>> entities = new HashSet<>();
46:
47: public MetamodelImpl(Configuration configuration, EntityLoader entityLoader) {
48: this.configuration = Objects.requireNonNull(configuration);
49: Objects.requireNonNull(entityLoader);
50: build(entityLoader);
51: }
52:
53: private void build(EntityLoader entityLoader) {
54: LOG.debug("Building metamodel ... ");
55: checkForWeaver();
56:
57: loadEntities(entityLoader);
58:
59: entities.forEach(cls -> processOWLClass(cls));
60: }
61:
62: /**
63: * Check the class path for aspectj weaver, which is vital for using lazy loading.
64: */
65: private void checkForWeaver() {
66: try {
67: @SuppressWarnings("unused")
68: Class<?> c = MetamodelImpl.class.getClassLoader().loadClass(
69: ASPECTJ_CLASS);
70: } catch (ClassNotFoundException e) {
71: LOG.error("AspectJ not found on classpath. Cannot run without AspectJ.");
72: throw new OWLPersistenceException(e);
73: }
74: }
75:
76: private void loadEntities(EntityLoader entityLoader) {
77: Set<Class<?>> discoveredEntities = entityLoader.discoverEntityClasses(configuration);
78: entities.addAll(discoveredEntities);
79: }
80:
81: private <X> void processOWLClass(final Class<X> cls) {
82: if (typeMap.containsKey(cls)) {
83: return;
84: }
85:
86: LOG.debug("processing OWL class: {}", cls);
87:
88: final EntityClassProcessor classProcessor = new EntityClassProcessor();
89:
90: final EntityTypeImpl<X> et = classProcessor.processEntityType(cls);
91:
92: typeMap.put(cls, et);
93: final EntityFieldMetamodelProcessor<X> fieldProcessor = new EntityFieldMetamodelProcessor<>(cls, et, this);
94:
95: for (final Field field : cls.getDeclaredFields()) {
96: fieldProcessor.processField(field);
97: }
98:
99: if (et.getIdentifier() == null) {
100: throw new MetamodelInitializationException("Missing identifier field in entity class " + cls);
101: }
102: }
103:
104: @SuppressWarnings("unchecked")
105: public <X> EntityType<X> entity(Class<X> cls) {
106: if (!typeMap.containsKey(cls)) {
107: processOWLClass(cls);
108: }
109:
110: return (EntityType<X>) typeMap.get(cls);
111: }
112:
113: public <X> EmbeddableType<X> embeddable(Class<X> cls) {
114: throw new IllegalArgumentException("Embeddable entities not supported.");
115: }
116:
117: public Set<EmbeddableType<?>> getEmbeddables() {
118: return Collections.emptySet();
119: }
120:
121: public Set<EntityType<?>> getEntities() {
122: return new HashSet<>(typeMap.values());
123: }
124:
125: public Set<ManagedType<?>> getManagedTypes() {
126: return new HashSet<>(typeMap.values());
127: }
128:
129: public <X> ManagedType<X> managedType(Class<X> cls) {
130: return entity(cls);
131: }
132:
133: public Set<Class<?>> getInferredClasses() {
134: return Collections.unmodifiableSet(inferredClasses);
135: }
136:
137: public void addInferredClass(Class<?> cls) {
138: inferredClasses.add(cls);
139: }
140:
141: @Override
142: public Set<URI> getModuleExtractionExtraSignature() {
143: return Collections.unmodifiableSet(getSignatureInternal());
144: }
145:
146: @Override
147: public void addUriToModuleExtractionSignature(URI uri) {
148: if (uri == null) {
149: throw new NullPointerException();
150: }
151: synchronized (this) {
152: getSignatureInternal().add(uri);
153: }
154: }
155:
156: private synchronized Set<URI> getSignatureInternal() {
157: // This can be lazily loaded since we don'attributeType know if we'll need it
158: if (moduleExtractionSignature == null) {
159: final String sig = configuration.get(OntoDriverProperties.MODULE_EXTRACTION_SIGNATURE);
160: if (sig == null) {
161: this.moduleExtractionSignature = new HashSet<>();
162: } else {
163: final String[] signature = sig.split(OntoDriverProperties.SIGNATURE_DELIMITER);
164: this.moduleExtractionSignature = new HashSet<>(signature.length);
165: try {
166: for (String uri : signature) {
167: moduleExtractionSignature.add(new URI(uri));
168: }
169: } catch (URISyntaxException e) {
170: throw new OWLPersistenceException("Invalid URI encountered in module extraction signature.", e);
171: }
172: }
173: }
174: return moduleExtractionSignature;
175: }
176: }