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