001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.metaschema.databind.model; 007 008import java.lang.reflect.Field; 009import java.lang.reflect.Type; 010 011import edu.umd.cs.findbugs.annotations.NonNull; 012 013public interface IFeatureJavaField extends IValuedMutable { 014 015 /** 016 * Gets the bound Java field associated with this instance. 017 * 018 * @return the Java field 019 */ 020 @NonNull 021 Field getField(); 022 023 /** 024 * Get the actual Java type of the underlying bound object. 025 * <p> 026 * This may be the same as the what is returned by {@link #getItemType()}, or 027 * may be a Java collection class. 028 * 029 * @return the raw type of the bound object 030 */ 031 @SuppressWarnings("null") 032 @NonNull 033 default Type getType() { 034 return getField().getGenericType(); 035 } 036 037 /** 038 * Get the item type of the bound object. An item type is the primitive or 039 * specialized type that represents that data associated with this binding. 040 * 041 * @return the item type of the bound object 042 */ 043 @NonNull 044 default Class<?> getItemType() { 045 return (Class<?>) getType(); 046 } 047 048 @Override 049 default Object getValue(@NonNull Object parent) { 050 Field field = getField(); 051 boolean accessable = field.canAccess(parent); 052 field.setAccessible(true); // NOPMD - intentional 053 Object retval; 054 try { 055 Object result = field.get(parent); 056 retval = result; 057 } catch (IllegalArgumentException | IllegalAccessException ex) { 058 throw new IllegalArgumentException( 059 String.format("Unable to get the value of field '%s' in class '%s'.", field.getName(), 060 field.getDeclaringClass().getName()), 061 ex); 062 } finally { 063 field.setAccessible(accessable); // NOPMD - intentional 064 } 065 return retval; 066 } 067 068 @Override 069 default void setValue(@NonNull Object parentObject, Object value) { 070 Field field = getField(); 071 boolean accessable = field.canAccess(parentObject); 072 field.setAccessible(true); // NOPMD - intentional 073 try { 074 field.set(parentObject, value); 075 } catch (IllegalArgumentException | IllegalAccessException ex) { 076 throw new IllegalArgumentException( 077 String.format( 078 "Unable to set the value of field '%s' in class '%s'." + 079 " Perhaps this is a data type adapter problem on the declared class?", 080 field.getName(), 081 field.getDeclaringClass().getName()), 082 ex); 083 } finally { 084 field.setAccessible(accessable); // NOPMD - intentional 085 } 086 } 087 088}