Skip to content

Package: EntityFieldMetamodelProcessor$InferenceInfo

EntityFieldMetamodelProcessor$InferenceInfo

nameinstructionbranchcomplexitylinemethod
EntityFieldMetamodelProcessor.InferenceInfo(Inferred)
M: 1 C: 19
95%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 4
100%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2016 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.exceptions.OWLPersistenceException;
17: import cz.cvut.kbss.jopa.model.*;
18: import cz.cvut.kbss.jopa.model.annotations.*;
19: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
20: import org.slf4j.Logger;
21: import org.slf4j.LoggerFactory;
22:
23: import java.lang.reflect.Field;
24: import java.lang.reflect.ParameterizedType;
25: import java.lang.reflect.Type;
26: import java.util.Collection;
27: import java.util.List;
28: import java.util.Map;
29: import java.util.Set;
30:
31: /**
32: * @author ledvima1
33: */
34: public class EntityFieldMetamodelProcessor<X> {
35:
36: private static final Logger LOG = LoggerFactory.getLogger(EntityFieldMetamodelProcessor.class);
37:
38: private final FieldMappingValidator mappingValidator = new FieldMappingValidator();
39:
40: private final Class<X> cls;
41: private final EntityTypeImpl<X> et;
42: private final MetamodelImpl metamodel;
43:
44: public EntityFieldMetamodelProcessor(Class<X> cls, EntityTypeImpl<X> et, MetamodelImpl metamodel) {
45: this.cls = cls;
46: this.et = et;
47: this.metamodel = metamodel;
48: }
49:
50: public void processField(Field field) {
51: LOG.trace("processing field: {}", field);
52: if (EntityPropertiesUtils.isFieldTransient(field)) {
53: LOG.trace("Skipping transient field {}", field);
54: return;
55: }
56: if (field.getType().isPrimitive()) {
57: throw new MetamodelInitializationException(
58: "Primitive types cannot be used for entity fields. Field " + field + " in class " + cls);
59: }
60:
61: final Class<?> fieldValueCls = getFieldValueType(field);
62: field.setAccessible(true);
63: final InferenceInfo inference = processInferenceInfo(field);
64:
65: if (isTypesField(field)) {
66: processTypesField(field, fieldValueCls, inference);
67: return;
68: }
69: if (isPropertiesField(field)) {
70: processPropertiesField(field, fieldValueCls, inference);
71: return;
72: }
73:
74: final PropertyAttributes propertyAtt = PropertyAttributes.create(field);
75: propertyAtt.resolve(field, metamodel, fieldValueCls);
76:
77: if (propertyAtt.isKnownOwlProperty()) {
78: createAttribute(field, inference, propertyAtt);
79: } else {
80: final boolean success = processIdentifierField(field);
81: if (!success) {
82: throw new MetamodelInitializationException(
83: "Unable to process field " + field + ". It is not transient but has no mapping information.");
84: }
85: }
86: }
87:
88: private Class<?> getFieldValueType(Field field) {
89: if (Collection.class.isAssignableFrom(field.getType())) {
90: return getSetOrListErasureType((ParameterizedType) field.getGenericType());
91: } else if (field.getType().isArray()) {
92: throw new MetamodelInitializationException("Array persistent attributes are not supported.");
93: } else {
94: return field.getType();
95: }
96: }
97:
98: private Class<?> getSetOrListErasureType(final ParameterizedType cls) {
99: final Type[] t = cls.getActualTypeArguments();
100:
101: if (t.length != 1) {
102: throw new OWLPersistenceException("Only collections with a single generic parameter are supported");
103: }
104: Type type = t[0];
105: if (!(type instanceof Class<?>)) {
106: throw new OWLPersistenceException("Only Classes might be valid parameters for generic lists and sets");
107: }
108: return (Class<?>) type;
109: }
110:
111: private InferenceInfo processInferenceInfo(Field field) {
112: final Inferred inferred = field.getAnnotation(Inferred.class);
113:
114: final InferenceInfo inference = new InferenceInfo(inferred);
115: if (inference.inferred) {
116: metamodel.addInferredClass(cls);
117: }
118: return inference;
119: }
120:
121: private boolean isTypesField(Field field) {
122: return field.getAnnotation(Types.class) != null;
123: }
124:
125: private void processTypesField(Field field, Class<?> fieldValueCls, InferenceInfo inference) {
126: Types tt = field.getAnnotation(Types.class);
127: mappingValidator.validateTypesField(field);
128: et.addDirectTypes(new TypesSpecificationImpl<>(et, tt.fetchType(), field, fieldValueCls, inference.inferred));
129: }
130:
131: private boolean isPropertiesField(Field field) {
132: return field.getAnnotation(Properties.class) != null;
133: }
134:
135: private void processPropertiesField(Field field, Class<?> fieldValueCls, InferenceInfo inference) {
136: Properties properties = field.getAnnotation(Properties.class);
137: mappingValidator.validatePropertiesField(field);
138: final PropertiesParametersResolver paramsResolver = new PropertiesParametersResolver(field);
139: et.addOtherProperties(
140: PropertiesSpecificationImpl.declaringType(et).fetchType(properties.fetchType()).javaField(field)
141: .javaType(fieldValueCls).inferred(inference.inferred)
142: .propertyIdType(paramsResolver.getPropertyIdentifierType())
143: .propertyValueType(paramsResolver.getPropertyValueType()).build());
144: }
145:
146: private void createAttribute(Field field, InferenceInfo inference, PropertyAttributes propertyAttributes) {
147: final Attribute<X, ?> a;
148: if (field.getType().isAssignableFrom(List.class)) {
149: final Sequence os = field.getAnnotation(Sequence.class);
150:
151: if (os == null) {
152: throw new MetamodelInitializationException("Expected Sequence annotation.");
153: }
154: a = ListAttributeImpl.iri(propertyAttributes.getIri()).declaringType(et).field(field)
155: .elementType(propertyAttributes.getType())
156: .attributeType(propertyAttributes.getPersistentAttributeType())
157: .cascadeTypes(propertyAttributes.getCascadeTypes())
158: .fetchType(propertyAttributes.getFetchType()).inferred(inference.inferred)
159: .includeExplicit(inference.includeExplicit)
160: .owlListClass(IRI.create(os.ClassOWLListIRI()))
161: .hasNextProperty(IRI.create(os.ObjectPropertyHasNextIRI()))
162: .hasContentsProperty(IRI.create(os.ObjectPropertyHasContentsIRI()))
163: .sequenceType(os.type())
164: .participationConstraints(propertyAttributes.getParticipationConstraints()).build();
165: } else if (field.getType().isAssignableFrom(Set.class)) {
166: a = SetAttributeImpl.iri(propertyAttributes.getIri()).declaringType(et).field(field)
167: .elementType(propertyAttributes.getType())
168: .attributeType(propertyAttributes.getPersistentAttributeType())
169: .fetchType(propertyAttributes.getFetchType())
170: .cascadeTypes(propertyAttributes.getCascadeTypes()).inferred(inference.inferred)
171: .includeExplicit(inference.includeExplicit)
172: .participationConstraints(propertyAttributes.getParticipationConstraints()).build();
173: } else if (field.getType().isAssignableFrom(Map.class)) {
174: throw new IllegalArgumentException("NOT YET SUPPORTED");
175: } else {
176: a = SingularAttributeImpl.iri(propertyAttributes.getIri()).name(field.getName()).identifier(false)
177: .declaringType(et).type(propertyAttributes.getType()).field(field)
178: .cascadeTypes(propertyAttributes.getCascadeTypes())
179: .attributeType(propertyAttributes.getPersistentAttributeType())
180: .fetchType(propertyAttributes.getFetchType()).inferred(inference.inferred)
181: .includeExplicit(inference.includeExplicit)
182: .constraints(propertyAttributes.getParticipationConstraints())
183: .nonEmpty(propertyAttributes.isNonEmpty()).build();
184: }
185: et.addDeclaredAttribute(field.getName(), a);
186: }
187:
188: private boolean processIdentifierField(Field field) {
189: final Id id = field.getAnnotation(Id.class);
190: if (id == null) {
191: return false;
192: }
193: if (!mappingValidator.isValidIdentifierType(field.getType())) {
194: throw new IllegalArgumentException("NOT YET SUPPORTED");
195: }
196: et.setIdentifier(new IRIIdentifierImpl(field, id.generated()));
197: return true;
198: }
199:
200: private static class InferenceInfo {
201: private final boolean inferred;
202: private final boolean includeExplicit;
203:
204: public InferenceInfo(Inferred inferredAnnotation) {
205:• this.inferred = inferredAnnotation != null;
206:• this.includeExplicit = inferredAnnotation == null || inferredAnnotation.includeExplicit();
207: }
208: }
209: }