1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind.model;
7   
8   import java.lang.reflect.Field;
9   import java.lang.reflect.Type;
10  
11  import edu.umd.cs.findbugs.annotations.NonNull;
12  
13  @FunctionalInterface
14  public interface IFeatureJavaField extends IValuedMutable {
15  
16    /**
17     * Gets the bound Java field associated with this instance.
18     *
19     * @return the Java field
20     */
21    @NonNull
22    Field getField();
23  
24    /**
25     * Get the actual Java type of the underlying bound object.
26     * <p>
27     * This may be the same as the what is returned by {@link #getItemType()}, or
28     * may be a Java collection class.
29     *
30     * @return the raw type of the bound object
31     */
32    @SuppressWarnings("null")
33    @NonNull
34    default Type getType() {
35      return getField().getGenericType();
36    }
37  
38    /**
39     * Get the item type of the bound object. An item type is the primitive or
40     * specialized type that represents that data associated with this binding.
41     *
42     * @return the item type of the bound object
43     */
44    @NonNull
45    default Class<?> getItemType() {
46      return (Class<?>) getType();
47    }
48  
49    @Override
50    default Object getValue(@NonNull Object parent) {
51      Field field = getField();
52      // boolean accessable = field.canAccess(parent);
53      // field.setAccessible(true); // NOPMD - intentional
54      Object retval;
55      try {
56        Object result = field.get(parent);
57        retval = result;
58      } catch (IllegalArgumentException | IllegalAccessException ex) {
59        throw new IllegalArgumentException(
60            String.format("Unable to get the value of field '%s' in class '%s'.", field.getName(),
61                field.getDeclaringClass().getName()),
62            ex);
63        // } finally {
64        // field.setAccessible(accessable); // NOPMD - intentional
65      }
66      return retval;
67    }
68  
69    @Override
70    default void setValue(@NonNull Object parentObject, Object value) {
71      Field field = getField();
72      // boolean accessable = field.canAccess(parentObject);
73      // field.setAccessible(true); // NOPMD - intentional
74      try {
75        field.set(parentObject, value);
76      } catch (IllegalArgumentException | IllegalAccessException ex) {
77        throw new IllegalArgumentException(
78            String.format(
79                "Unable to set the value of field '%s' in class '%s'." +
80                    " Perhaps this is a data type adapter problem on the declared class?",
81                field.getName(),
82                field.getDeclaringClass().getName()),
83            ex);
84        // } finally {
85        // field.setAccessible(accessable); // NOPMD - intentional
86      }
87    }
88  
89  }