Skip to content

Method: getFieldValue(Field, Object)

1: /*
2: * JOPA
3: * Copyright (C) 2024 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.utils;
19:
20: import cz.cvut.kbss.jopa.exception.IdentifierNotSetException;
21: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
22: import cz.cvut.kbss.jopa.model.annotations.Transient;
23: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
24: import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
25: import cz.cvut.kbss.jopa.model.metamodel.Identifier;
26: import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
27: import cz.cvut.kbss.ontodriver.exception.UnassignableIdentifierException;
28:
29: import java.lang.reflect.Field;
30: import java.lang.reflect.Modifier;
31: import java.net.URI;
32: import java.util.ArrayList;
33: import java.util.Arrays;
34: import java.util.List;
35: import java.util.Objects;
36:
37: /**
38: * Utility class for entity properties.
39: */
40: public class EntityPropertiesUtils {
41:
42: /**
43: * Private constructor
44: */
45: private EntityPropertiesUtils() {
46: throw new AssertionError("I am not for instantiation.");
47: }
48:
49: /**
50: * Extracts primary key from the specified {@code entity} and returns it.
51: *
52: * @param entity The entity to extract primary key from
53: * @param metamodel Metamodel
54: * @return IRI of the entity or null if it is not set
55: * @throws NullPointerException If {@code entity} or {@code metamodel} is null
56: * @throws OWLPersistenceException If {@code entity} is not an entity or if the identifier is of an unknown type
57: */
58: public static URI getIdentifier(Object entity, Metamodel metamodel) {
59: Objects.requireNonNull(entity);
60: Objects.requireNonNull(metamodel);
61:
62: final EntityType<?> type = metamodel.entity(entity.getClass());
63: return getIdentifier(entity, type);
64: }
65:
66: /**
67: * Sets value of the specified field.
68: *
69: * @param field Field to set value on
70: * @param instance Target instance (can be {@code null} for static fields)
71: * @param value The value to set (can be {@code null})
72: */
73: public static void setFieldValue(Field field, Object instance, Object value) {
74: Objects.requireNonNull(field);
75: if (!field.canAccess(instance)) {
76: field.setAccessible(true);
77: }
78: try {
79: field.set(instance, value);
80: } catch (IllegalAccessException e) {
81: throw new OWLPersistenceException("Unable to set field value.", e);
82: }
83: }
84:
85: /**
86: * Gets value of the specified field from the specified instance.
87: *
88: * @param field Field to get value of
89: * @param instance Instance that contains the field
90: * @return Field value
91: */
92: public static Object getFieldValue(Field field, Object instance) {
93: Objects.requireNonNull(field);
94:• if (!field.canAccess(instance)) {
95: field.setAccessible(true);
96: }
97: try {
98: return field.get(instance);
99: } catch (IllegalAccessException e) {
100: throw new OWLPersistenceException("Unable to extract field value.", e);
101: }
102: }
103:
104: /**
105: * Gets value of the specified attribute.
106: *
107: * @param attribute Attribute to extract value of
108: * @param instance Instance from which value will be extracted
109: * @return Attribute value
110: */
111: public static Object getAttributeValue(FieldSpecification<?, ?> attribute, Object instance) {
112: Objects.requireNonNull(attribute);
113: final Field field = attribute.getJavaField();
114: return getFieldValue(field, instance);
115: }
116:
117: /**
118: * Extracts entity's identifier according to the specified entity type.
119: *
120: * @param entity Entity
121: * @param et Entity type
122: * @param <T> Type of the entity
123: * @return Identifier of the specified entity, possibly null
124: */
125: public static <T> URI getIdentifier(T entity, EntityType<?> et) {
126: try {
127: final Object id = getFieldValue(et.getIdentifier().getJavaField(), entity);
128: if (id == null) {
129: return null;
130: }
131: return getValueAsURI(id);
132: } catch (IllegalArgumentException e) {
133: throw new OWLPersistenceException("Unable to extract entity identifier.", e);
134: }
135: }
136:
137: /**
138: * Sets the specified identifier on the specified entity.
139: *
140: * @param identifier The identifier to set
141: * @param entity Target entity
142: * @param et Entity type
143: * @param <T> Type of the entity
144: */
145: public static <T> void setIdentifier(Object identifier, T entity, EntityType<T> et) {
146: final Identifier<? super T, ?> id = et.getIdentifier();
147: final Field idField = id.getJavaField();
148: try {
149: final Object assignableId = IdentifierTransformer.transformToIdentifier(identifier, idField.getType());
150: setFieldValue(idField, entity, assignableId);
151: } catch (IllegalArgumentException e) {
152: throw new UnassignableIdentifierException(e);
153: }
154: }
155:
156: /**
157: * Transforms the specified value to URI (if possible).
158: *
159: * @param value The value to transform
160: * @return {@code URI}
161: * @throws NullPointerException If {@code value} is {@code null}
162: * @throws IllegalArgumentException If {@code value} cannot be transformed to URI
163: */
164: public static URI getValueAsURI(Object value) {
165: return IdentifierTransformer.valueAsUri(Objects.requireNonNull(value));
166: }
167:
168: /**
169: * Gets all instance fields of the specified class, including inherited ones.
170: *
171: * @param cls The class to search
172: * @return List of declared fields
173: */
174: public static List<Field> getAllFields(Class<?> cls) {
175: final List<Field> fields = new ArrayList<>(Arrays.asList(cls.getDeclaredFields()));
176: Class<?> tmp = cls.getSuperclass();
177: while (tmp != null) {
178: fields.addAll(Arrays.asList(tmp.getDeclaredFields()));
179: tmp = tmp.getSuperclass();
180: }
181: fields.removeIf(f -> Modifier.isStatic(f.getModifiers()));
182: return fields;
183: }
184:
185: /**
186: * Verifies, that the primary key (identifier) of the specified instance is generated.
187: * <p>
188: * If not, an exception is thrown.
189: *
190: * @param instance The instance to verify
191: * @param entityType Entity type of the instance, as specified by metamodel
192: * @throws cz.cvut.kbss.jopa.exception.IdentifierNotSetException If the identifier is not generated
193: */
194: public static void verifyIdentifierIsGenerated(Object instance, EntityType<?> entityType) {
195: if (!entityType.getIdentifier().isGenerated()) {
196: throw new IdentifierNotSetException(
197: "The id for entity " + instance + " is null and it is not specified as 'generated'.");
198: }
199: }
200:
201: /**
202: * Checks whether the specified field should not be persisted, i.e. whether it is transient in the persistence
203: * sense.
204: * <p>
205: * A field is transient if it is:
206: * <ul>
207: * <li>static
208: * <li>or final
209: * <li>or transient
210: * <li>or annotated with the {@link Transient} annotation
211: * </ul>
212: *
213: * @param field The field to investigate
214: * @return Whether the field is transient
215: */
216: public static boolean isFieldTransient(Field field) {
217: Objects.requireNonNull(field);
218: final int modifiers = field.getModifiers();
219: if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isTransient(modifiers)) {
220: return true;
221: }
222: final Transient transientAnnotation = field.getAnnotation(Transient.class);
223: return transientAnnotation != null;
224: }
225:
226: /**
227: * Returns true if the specified field is static.
228: *
229: * @param field The field to check
230: * @return True if field is static, false otherwise
231: */
232: public static boolean isFieldStatic(Field field) {
233: return Modifier.isStatic(field.getModifiers());
234: }
235: }