-
Notifications
You must be signed in to change notification settings - Fork 14
/
StaticMetamodelInitializer.java
115 lines (98 loc) · 5.02 KB
/
StaticMetamodelInitializer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package cz.cvut.kbss.jopa.model.metamodel;
import cz.cvut.kbss.jopa.exception.StaticMetamodelInitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Objects;
import java.util.Optional;
/**
* Initializes static metamodel based on the provided runtime metamodel.
* <p>
* Static metamodel initialization involves going through all managed types in the metamodel, finding a corresponding static metamodel class (if exists)
* and populating its attributes with values from the actual runtime metamodel.
*/
public class StaticMetamodelInitializer {
private static final Logger LOG = LoggerFactory.getLogger(StaticMetamodelInitializer.class);
/**
* Suffix appended to a static metamodel class corresponding to a metamodel class.
*/
private static final String STATIC_METAMODEL_CLASS_SUFFIX = "_";
private final Metamodel metamodel;
public StaticMetamodelInitializer(Metamodel metamodel) {
this.metamodel = metamodel;
}
/**
* Executes the static metamodel initialization.
*/
public void initializeStaticMetamodel() {
LOG.debug("Initializing static metamodel.");
processEntities();
// TODO process mapped superclasses
}
private void processEntities() {
metamodel.getEntities().forEach(et -> {
final Optional<Class<?>> smClass = tryFindingClass(et);
if (!smClass.isPresent()) {
LOG.trace("No static metamodel type found for {}.", et);
return;
}
LOG.debug("Processing static metamodel class {} corresponding to {}.", smClass.get(), et);
try {
initStaticMembers(et, smClass.get());
} catch (IllegalAccessException e) {
throw new StaticMetamodelInitializationException("Unable to initialize static metamodel class " + smClass, e);
}
});
}
private Optional<Class<?>> tryFindingClass(EntityType<?> et) {
final String staticName = et.getJavaType().getName() + STATIC_METAMODEL_CLASS_SUFFIX;
try {
final Class<?> smClass = Class.forName(staticName);
return Optional.of(smClass);
} catch (ClassNotFoundException e) {
// Swallow the exception, this just means there is no static metamodel type for the specified entity
return Optional.empty();
}
}
private <T> void initStaticMembers(EntityType<T> et, Class<?> smClass) throws IllegalAccessException {
final Field[] fields = smClass.getDeclaredFields();
for (Field f : fields) {
final FieldSpecification<T, ?> att = getMetamodelMember(f, et);
setFieldValue(f, att);
}
}
private void setFieldValue(Field field, Object value) throws IllegalAccessException {
if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isPublic(field.getModifiers())) {
throw new StaticMetamodelInitializationException("Static metamodel field " + field + " must be public static.");
}
field.set(null, value);
}
private <T> FieldSpecification<T, ?> getMetamodelMember(Field field, EntityType<T> et) {
LOG.trace("Finding metamodel member for static metamodel field {}.", field);
return getDeclaredIdentifier(field, et)
.orElseGet(() -> getDeclaredAttribute(field, et)
.orElseGet(() -> getDeclaredTypes(field, et)
.orElseGet(() -> getDeclaredProperties(field, et)
.orElseThrow(() -> new StaticMetamodelInitializationException("No corresponding metamodel member found for static metamodel field " + field)))));
}
private <T> Optional<FieldSpecification<T, ?>> getDeclaredIdentifier(Field field, EntityType<T> et) {
// TODO Declaring class check
return Objects.equals(field.getName(), et.getIdentifier().getJavaField().getName()) ? Optional.of((Identifier<T, ?>) et.getIdentifier()) : Optional.empty();
}
private <T> Optional<FieldSpecification<T, ?>> getDeclaredAttribute(Field field, EntityType<T> et) {
try {
return Optional.of(et.getDeclaredAttribute(field.getName()));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
private <T> Optional<FieldSpecification<T, ?>> getDeclaredTypes(Field field, EntityType<T> et) {
// TODO Declaring class check
return et.getTypes() != null && Objects.equals(field.getName(), et.getTypes().getJavaField().getName()) ? Optional.of((TypesSpecification<T, ?>) et.getTypes()) : Optional.empty();
}
private <T> Optional<FieldSpecification<T, ?>> getDeclaredProperties(Field field, EntityType<T> et) {
// TODO Declaring class check
return et.getProperties() != null && Objects.equals(field.getName(), et.getProperties().getJavaField().getName()) ? Optional.of((PropertiesSpecification<T, ?, ?, ?>) et.getProperties()) : Optional.empty();
}
}