Package: ManagedClassProcessor
ManagedClassProcessor
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ManagedClassProcessor() |
|
|
|
|
|
||||||||||||||||||||
checkForNoArgConstructor(Class) |
|
|
|
|
|
||||||||||||||||||||
detectNamespaces(Class) |
|
|
|
|
|
||||||||||||||||||||
detectNamespaces(Class, NamespaceResolver) |
|
|
|
|
|
||||||||||||||||||||
getManagedSuperClass(Class) |
|
|
|
|
|
||||||||||||||||||||
getManagedSuperInterfaces(Class) |
|
|
|
|
|
||||||||||||||||||||
isEntityType(Class) |
|
|
|
|
|
||||||||||||||||||||
isManagedType(Class) |
|
|
|
|
|
||||||||||||||||||||
isMappedSuperclassType(Class) |
|
|
|
|
|
||||||||||||||||||||
lambda$getManagedSuperInterfaces$0(Class) |
|
|
|
|
|
||||||||||||||||||||
processEntityType(Class, NamespaceResolver) |
|
|
|
|
|
||||||||||||||||||||
processManagedType(Class) |
|
|
|
|
|
||||||||||||||||||||
processMappedSuperclassType(Class) |
|
|
|
|
|
||||||||||||||||||||
resolveNamespaces(AnnotatedElement, NamespaceResolver) |
|
|
|
|
|
||||||||||||||||||||
static {...} |
|
|
|
|
|
Coverage
1: /*
2: * JOPA
3: * Copyright (C) 2023 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.model.metamodel;
19:
20: import cz.cvut.kbss.jopa.exception.MetamodelInitializationException;
21: import cz.cvut.kbss.jopa.model.IRI;
22: import cz.cvut.kbss.jopa.model.annotations.MappedSuperclass;
23: import cz.cvut.kbss.jopa.model.annotations.Namespace;
24: import cz.cvut.kbss.jopa.model.annotations.Namespaces;
25: import cz.cvut.kbss.jopa.model.annotations.OWLClass;
26: import cz.cvut.kbss.jopa.utils.NamespaceResolver;
27:
28: import java.lang.reflect.AnnotatedElement;
29: import java.lang.reflect.Modifier;
30: import java.util.Arrays;
31: import java.util.Objects;
32: import java.util.Set;
33: import java.util.stream.Collectors;
34:
35: /**
36: * Utility methods for processing managed types for metamodel construction.
37: */
38: public class ManagedClassProcessor {
39:
40: private ManagedClassProcessor() {
41: throw new AssertionError();
42: }
43:
44: static <T> TypeBuilderContext<T> processManagedType(Class<T> cls) {
45: final NamespaceResolver resolver = detectNamespaces(cls);
46: final AbstractIdentifiableType<T> type;
47:• if (isEntityType(cls)) {
48: type = processEntityType(cls, resolver);
49:• } else if (isMappedSuperclassType(cls)) {
50: type = processMappedSuperclassType(cls);
51: } else {
52: throw new MetamodelInitializationException("Type " + cls + " is not a managed type.");
53: }
54: return new TypeBuilderContext<>(type, resolver);
55: }
56:
57: /**
58: * Detects namespace declarations relevant to the specified class.
59: * <p>
60: * This means namespaces declared on the class itself, namespaces it inherited from super types, as well as
61: * namespaces declared for the package that contains the specified class.
62: * <p>
63: * Namespaces declared directly by {@link Namespace} as well as in {@link Namespaces} are considered.
64: *
65: * @param cls Class to detect namespaces for
66: * @return Namespace resolver containing detected namespaces
67: */
68: public static <T> NamespaceResolver detectNamespaces(Class<T> cls) {
69: final NamespaceResolver resolver = new NamespaceResolver();
70: detectNamespaces(cls, resolver);
71: return resolver;
72: }
73:
74: /**
75: * Detects namespace declarations relevant to the specified class and registers them with the specified {@link
76: * NamespaceResolver}.
77: * <p>
78: * This means namespaces declared on the class itself, namespaces it inherited from super types, as well as
79: * namespaces declared for the package that contains the specified class.
80: * <p>
81: * Namespaces declared directly by {@link Namespace} as well as in {@link Namespaces} are considered.
82: *
83: * @param cls Class to detect namespaces for
84: * @param namespaceResolver Namespace resolver containing detected namespaces
85: */
86: public static <T> void detectNamespaces(Class<T> cls, NamespaceResolver namespaceResolver) {
87: Objects.requireNonNull(cls);
88: Objects.requireNonNull(namespaceResolver);
89:• if (cls.getPackage() != null) {
90: resolveNamespaces(cls.getPackage(), namespaceResolver);
91: }
92: resolveNamespaces(cls, namespaceResolver);
93: }
94:
95: private static void resolveNamespaces(AnnotatedElement target, NamespaceResolver namespaceResolver) {
96: final Namespaces namespaces = target.getDeclaredAnnotation(Namespaces.class);
97:• if (namespaces != null) {
98:• for (Namespace ns : namespaces.value()) {
99: namespaceResolver.registerNamespace(ns.prefix(), ns.namespace());
100: }
101: }
102: final Namespace namespace = target.getDeclaredAnnotation(Namespace.class);
103:• if (namespace != null) {
104: namespaceResolver.registerNamespace(namespace.prefix(), namespace.namespace());
105: }
106: }
107:
108: private static <T> IdentifiableEntityType<T> processEntityType(Class<T> cls, NamespaceResolver namespaceResolver) {
109: final OWLClass c = cls.getDeclaredAnnotation(OWLClass.class);
110:• assert c != null;
111:
112:• if (cls.isInterface() || Modifier.isAbstract(cls.getModifiers())) {
113: return new AbstractEntityType<>(cls.getSimpleName(), cls, IRI.create(namespaceResolver.resolveFullIri(c.iri())));
114: } else {
115: checkForNoArgConstructor(cls);
116: return new ConcreteEntityType<>(cls.getSimpleName(), cls, IRI.create(namespaceResolver.resolveFullIri(c.iri())));
117: }
118: }
119:
120: private static <T> void checkForNoArgConstructor(Class<T> cls) {
121: try {
122: cls.getDeclaredConstructor();
123: } catch (NoSuchMethodException e) {
124: throw new MetamodelInitializationException("Class " + cls + " is missing required no-arg constructor.", e);
125: }
126: }
127:
128: private static <T> MappedSuperclassTypeImpl<T> processMappedSuperclassType(Class<T> cls) {
129:• assert cls.getDeclaredAnnotation(MappedSuperclass.class) != null;
130:
131: return new MappedSuperclassTypeImpl<>(cls);
132: }
133:
134: static <T> Class<? super T> getManagedSuperClass(Class<T> cls) {
135:• if (cls.getSuperclass() != null && isManagedType(cls.getSuperclass())) {
136: return cls.getSuperclass();
137: }
138: return null;
139: }
140:
141: public static <T> Set<Class<? super T>> getManagedSuperInterfaces(Class<T> cls) {
142: return Arrays.stream(cls.getInterfaces()).filter(ManagedClassProcessor::isManagedType)
143: .map(clazz -> (Class<? super T>) clazz)
144: .collect(Collectors.toSet());
145: }
146:
147: /**
148: * Checks whether the specified class is a managed type.
149: * <p>
150: * That is, if it is an entity type (annotated with {@link OWLClass}) or a mapped superclass (annotated with {@link
151: * MappedSuperclass}).
152: *
153: * @param cls Class to check
154: * @return {@code true} if the class is a managed type, {@code false} otherwise
155: */
156: public static boolean isManagedType(Class<?> cls) {
157:• return isEntityType(cls) || isMappedSuperclassType(cls);
158: }
159:
160: /**
161: * Checks whether the specified class is an entity type.
162: * <p>
163: * An entity is annotated with {@link OWLClass}.
164: *
165: * @param cls Class to check
166: * @return {@code true} if the class is an entity type, {@code false} otherwise
167: */
168: public static boolean isEntityType(Class<?> cls) {
169:• return cls != null && cls.getDeclaredAnnotation(OWLClass.class) != null;
170: }
171:
172: /**
173: * Checks whether the specified class is a managed superclass.
174: * <p>
175: * An entity is annotated with {@link MappedSuperclass}.
176: *
177: * @param cls Class to check
178: * @return {@code true} if the class is a mapped superclass, {@code false} otherwise
179: */
180: public static boolean isMappedSuperclassType(Class<?> cls) {
181:• return cls != null && cls.getDeclaredAnnotation(MappedSuperclass.class) != null;
182: }
183: }