org.boon.core.reflection.BeanUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boon Show documentation
Show all versions of boon Show documentation
Simple opinionated Java for the novice to expert level Java Programmer.
Low Ceremony. High Productivity. A real boon to Java to developers!
/*
* Copyright 2013-2014 Richard M. Hightower
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* __________ _____ __ .__
* \______ \ ____ ____ ____ /\ / \ _____ | | _|__| ____ ____
* | | _// _ \ / _ \ / \ \/ / \ / \\__ \ | |/ / |/ \ / ___\
* | | ( <_> | <_> ) | \ /\ / Y \/ __ \| <| | | \/ /_/ >
* |______ /\____/ \____/|___| / \/ \____|__ (____ /__|_ \__|___| /\___ /
* \/ \/ \/ \/ \/ \//_____/
* ____. ___________ _____ ______________.___.
* | |____ ___ _______ \_ _____/ / _ \ / _____/\__ | |
* | \__ \\ \/ /\__ \ | __)_ / /_\ \ \_____ \ / | |
* /\__| |/ __ \\ / / __ \_ | \/ | \/ \ \____ |
* \________(____ /\_/ (____ / /_______ /\____|__ /_______ / / ______|
* \/ \/ \/ \/ \/ \/
*/
package org.boon.core.reflection;
import org.boon.*;
import org.boon.core.Conversions;
import org.boon.core.Typ;
import org.boon.core.Type;
import org.boon.core.reflection.fields.FieldAccess;
import org.boon.core.reflection.fields.MapField;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static org.boon.Boon.className;
import static org.boon.Boon.sputs;
import static org.boon.Exceptions.*;
import static org.boon.Str.lines;
import static org.boon.StringScanner.isDigits;
import static org.boon.primitive.CharScanner.isDigit;
/**
* Created by rick on 12/20/13.
*/
public class BeanUtils {
/**
* This returns getPropertyFieldFieldAccessMap(clazz, true, true);
*
* @param clazz gets the properties or fields of this class.
* @return
*/
private static Map getPropertyFieldAccessMap( Class> clazz ) {
return Reflection.getPropertyFieldAccessMapFieldFirst( clazz );
}
public static FieldAccess getField( Class clazz, String name ) {
Map fields = getPropertyFieldAccessMap( clazz );
if ( fields != null) {
return fields.get(name);
} else {
return null;
}
}
public static FieldAccess getField( Object object, String name ) {
Map fields = getFieldsFromObject( object );
if ( fields != null) {
return fields.get(name);
} else {
return null;
}
}
public static Map getFieldsFromObject( Class> cls ) {
return getPropertyFieldAccessMap( cls );
}
/**
* Get fields from object or Map.
* Allows maps to act like they have fields.
*
* @param object
* @return
*/
public static Map getFieldsFromObject( Object object ) {
try {
Map fields;
fields = getPropertyFieldAccessMap( object.getClass() );
if ( object instanceof Map ) {
fields = getFieldsFromMap( fields, ( Map ) object );
}
return fields;
} catch (Exception ex) {
requireNonNull(object, "Item cannot be null" );
return handle(Map.class, ex, "Unable to get fields from object", className(object));
}
}
/**
* Get fields from map.
*
* @param fields
* @param map
* @return
*/
private static Map getFieldsFromMap( Map fields, Map map ) {
for ( Map.Entry entry : map.entrySet() ) {
fields.put( entry.getKey(), new MapField( entry.getKey() ) );
}
return fields;
}
/**
* Get property value, loads nested properties
*
* @param root
* @param properties
* @return
*/
public static void setPropertyValue( final Object root, final Object newValue, final String... properties ) {
Object object = root;
int index = 0;
try {
for ( String property : properties ) {
Map fields = getFieldsFromObject( object );
FieldAccess field = fields.get( property );
if ( isDigits( property ) ) {
/* We can index numbers and names. */
object = idx ( object, Integer.parseInt ( property ) );
} else {
if ( field == null ) {
die( sputs(
"We were unable to access property=", property,
"\nThe properties passed were=", properties,
"\nThe root object is =", root.getClass().getName(),
"\nThe current object is =", object.getClass().getName()
)
);
}
if ( index == properties.length - 1 ) {
field.setValue( object, newValue );
} else {
object = field.getObject( object );
}
}
index++;
}
} catch (Exception ex) {
requireNonNull(root, "Root cannot be null");
handle(ex, "Unable to set property for root object", className(root),
"for property path", properties, "with new value", newValue,
"last object in the tree was",
className(object), "current property index", index);
}
}
/**
* Get property value, loads nested properties
*
* @param root
* @param properties
* @return
*/
public static void setPropertyValue( final Class> root, final Object newValue, final String... properties ) {
Object object = root;
int index = 0;
Map fields = getFieldsFromObject( root );
try {
for ( String property : properties ) {
FieldAccess field = fields.get( property );
if ( isDigits( property ) ) {
/* We can index numbers and names. */
object = idx ( object, Integer.parseInt ( property ) );
} else {
if ( field == null ) {
die( sputs(
"We were unable to access property=", property,
"\nThe properties passed were=", properties,
"\nThe root object is =", root.getClass().getName(),
"\nThe current object is =", object.getClass().getName()
)
);
}
if ( index == properties.length - 1 ) {
if (object instanceof Class) {
field.setStaticValue( newValue );
} else {
field.setValue( object, newValue );
}
} else {
object = field.getObject( object );
if (object != null) {
fields = getFieldsFromObject( root );
}
}
}
index++;
}
} catch (Exception ex) {
requireNonNull(root, "Root cannot be null");
handle(ex, "Unable to set property for root object", className(root),
"for property path", properties, "with new value", newValue,
"last object in the tree was",
className(object), "current property index", index);
}
}
/**
* Get property value, loads nested properties
*
* @param root
* @param properties
* @return
*/
public static Object getPropertyValue( final Object root, final String... properties ) {
Object object = root;
for ( String property : properties ) {
if (object == null) {
return null;
}
if (property.equals("this")) {
if (!(object instanceof Map)) {
continue;
} else {
Object aThis = ((Map) object).get("this");
if (aThis!=null) {
object = aThis;
continue;
} else {
continue;
}
}
}
if (object instanceof Map) {
object = ((Map) object).get(property);
continue;
}
char c = property.charAt(0);
if ( isDigit(c) ) {
/* We can index numbers and names. */
object = idx ( object, Integer.parseInt ( property ) );
} else {
if (object instanceof Collection) {
object = getFieldValuesFromCollection((Collection)object, property);
object = Conversions.unifyListOrArray(object);
continue;
}
Map fields =
getPropertyFieldAccessMap( object.getClass() );
FieldAccess field = fields.get( property );
if ( field == null ) {
return null;
}
object = field.getValue( object );
}
}
return object;
}
private static Object _getPropertyValue( final Object root, final String property ) {
Object object = root;
if (object == null) {
return null;
} else if (object instanceof Collection) {
object = getFieldValuesFromCollection((Collection)object, property);
object = Conversions.unifyList((List) object);
return object;
} else {
Map fields =
getPropertyFieldAccessMap(object.getClass());
FieldAccess field = fields.get(property);
if (field == null) {
return null;
}
object = field.getValue(object);
return object;
}
}
/**
* Get property value, loads nested properties
*
* @param root
* @param property
* @return
*/
public static Class> getPropertyType( final Object root, final String property ) {
Exceptions.requireNonNull( root );
Exceptions.requireNonNull( property );
Map fields = getPropertyFieldAccessMap( root.getClass() );
FieldAccess field = fields.get( property );
return field.type();
}
@SuppressWarnings ( "unchecked" )
public static T idxGeneric( Class t, Object object, final String path ) {
Exceptions.requireNonNull( object );
Exceptions.requireNonNull( path );
String[] properties = propertyPathAsStringArray(path);
return ( T ) getPropByPath( object, properties );
}
public static List idxList( Class cls, Object items, String... path ) {
return ( List ) getPropByPath( items, path );
}
/**
* This method handles walking lists of lists.
*
* @param item
* @param path
* @return
*/
public static Object getPropByPath( Object item, String... path ) {
Object o = item;
for ( int index = 0; index < path.length; index++ ) {
String propName = path[ index ];
if ( o == null ) {
return null;
} else if ( o.getClass().isArray() || o instanceof Collection ) {
o = getCollectionProp(o, propName, index, path);
break;
} else {
o = getProp( o, propName );
}
}
return Conversions.unifyListOrArray(o);
}
/**
* Get property value
*
* @param object
* @param path in dotted notation
* @return
*/
public static Object idx( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyValue( object, properties );
}
/**
* Get property value
*
* @deprecated use atIndex or idx.
* @param object
* @param path in dotted notation
* @return
*/
public static Object indexOf(Object object, String path) {
return atIndex(object, path);
}
/**
* Get property value
*
* @param object
* @param path in dotted notation
* @return
*/
public static Object atIndex(Object object, String path) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyValue( object, properties );
}
static Map splitsPathsCache = new ConcurrentHashMap<>();
private static String[] propertyPathAsStringArray(String path) {
String[] split = splitsPathsCache.get(path);
if (split!=null) {
return split;
}
split = StringScanner.splitByCharsNoneEmpty(path, '.', '[', ']', '/');
splitsPathsCache.put(path, split);
return split;
}
public static Object findProperty(Object context, String propertyPath) {
int index = propertyPath.indexOf('|');
Object defaultValue = null;
if (index!=-1) {
String[] splitByPipe = Str.splitByPipe(propertyPath);
defaultValue = splitByPipe[1];
propertyPath = splitByPipe[0];
} else {
defaultValue = null;
}
Object object = null;
Iterator iterator = Conversions.iterator(context);
while (iterator.hasNext()) {
Object ctx = iterator.next();
object = idx(ctx, propertyPath);
if (object != null) {
return object;
}
}
return defaultValue;
}
/**
* Set property value to simulate dependency injection.
*
* @param object
* @param path in dotted notation
* @return
*/
public static void injectIntoProperty( Object object, String path, Object value ) {
String[] properties = propertyPathAsStringArray(path);
setPropertyValue( object, value, properties );
}
/**
* Set property value
*
* @param object
* @param path in dotted notation
* @return
*/
public static void idx( Object object, String path, Object value ) {
String[] properties = propertyPathAsStringArray(path);
setPropertyValue( object, value, properties );
}
/**
* Set a static value
*
* @param cls
* @param path in dotted notation
* @return
*/
public static void idx( Class> cls, String path, Object value ) {
String[] properties = propertyPathAsStringArray(path);
setPropertyValue( cls, value, properties );
}
/**
* @param object
* @param path
* @return
*/
public static Object byPath(Object object, final String path) {
try {
String[] properties = propertyPathAsStringArray(path);
return getPropByPath( object, properties );
} catch (Exception ex) {
Exceptions.requireNonNull( object );
Exceptions.requireNonNull( path );
return Exceptions.handle(Object.class, ex, object, path);
}
}
/**
* This is an amazing little recursive method. It walks a fanout of
* nested collection to pull out the leaf nodes
*/
private static Object getCollectionProp( Object o, String propName, int index, String[] path ) {
o = getFieldValuesFromCollection(o, propName);
if ( index + 1 == path.length ) {
return o;
} else {
index++;
return getCollectionProp(o, path[index], index, path);
}
}
/**
* This is one is forgiving of null paths.
* This works with getters first, i.e., properties.
*
* @param object
* @param property
* @return
*/
public static Object getProp( Object object, final String property ) {
if ( object == null ) {
return null;
}
if ( isDigits( property ) ) {
/* We can index numbers and names. */
object = idx ( object, Integer.parseInt ( property ) );
}
Class> cls = object.getClass();
/** Tries the getters first. */
Map fields = Reflection.getPropertyFieldAccessors( cls );
if ( !fields.containsKey( property ) ) {
fields = Reflection.getAllAccessorFields( cls );
}
if ( !fields.containsKey( property ) ) {
return null;
} else {
return fields.get( property ).getValue( object );
}
}
/**
* Get an int property.
*/
public static int getPropertyInt( final Object root, final String... properties ) {
Exceptions.requireNonNull( root );
Exceptions.requireNonNull( properties );
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.intgr ) {
return field.getInt( object );
} else {
return Conversions.toInt( field.getValue( object ) );
}
}
/**
* @param root
* @param properties
* @return
*/
private static Object baseForGetProperty( Object root, String[] properties ) {
Object object = root;
Map fields = null;
for ( int index = 0; index < properties.length - 1; index++ ) {
if (object == null) {
return null;
}
String property = properties[ index ];
if (property.equals("this")) {
continue;
}
fields = getPropertyFieldAccessMap( object.getClass() );
FieldAccess field = fields.get( property );
if ( isDigits( property ) ) {
/* We can index numbers and names. */
object = idx ( object, Integer.parseInt ( property ) );
} else {
if ( field == null ) {
return null;
}
object = field.getObject( object );
}
}
return object;
}
/**
* @param root
* @param properties
* @return
*/
private static Class> baseForGetProperty( Class> root, String[] properties ) {
Class cls = root;
Map fields = null;
for ( int index = 0; index < properties.length - 1; index++ ) {
fields = getPropertyFieldAccessMap( cls );
String property = properties[ index ];
FieldAccess field = fields.get( property );
cls = field.type();
}
return cls;
}
/**
* Get property value
*
* @param object
* @param path in dotted notation
* @return
*/
public static int idxInt( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyInt( object, properties );
}
/**
* Get property value
*
* @param object
* @param path in dotted notation
* @return
*/
public static String idxStr( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyString(object, properties);
}
private static String getPropertyString(Object root, String[] properties) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.string ) {
return (String) field.getObject( object );
} else {
return Conversions.toString(field.getValue(object));
}
}
/**
* @param root
* @param properties
* @return
*/
public static byte getPropertyByte( final Object root, final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.bt ) {
return field.getByte( object );
} else {
return Conversions.toByte( field.getValue( object ) );
}
}
/**
* @param object
* @param path
* @return
*/
public static byte idxByte( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyByte( object, properties );
}
/**
* @param root
* @param properties
* @return
*/
public static float getPropertyFloat( final Object root, final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.flt ) {
return field.getFloat( object );
} else {
return Conversions.toFloat( field.getValue( object ) );
}
}
/**
* @param object
* @param path
* @return
*/
public static float idxFloat( Object object, String path ) {
Exceptions.requireNonNull( object );
Exceptions.requireNonNull( path );
String[] properties = propertyPathAsStringArray(path);
return getPropertyFloat( object, properties );
}
/**
* @param root
* @param properties
* @return
*/
public static short getPropertyShort( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.shrt ) {
return field.getShort( object );
} else {
return Conversions.toShort( field.getValue( object ) );
}
}
/**
* Get Property Path Type
* @param root
* @param properties
* @return
*/
public static Class> getPropertyPathType( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
return field.type();
}
/**
* Get Property Path Type
* @param root
* @param properties
* @return
*/
public static FieldAccess getPropertyPathField( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
return field;
}
/**
* Get Property Path Type
* @param root
* @param properties
* @return
*/
public static FieldAccess getPropertyPathField( final Class root,
final String... properties ) {
Class cls = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( cls );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
return field;
}
/**
* @param object
* @param path
* @return
*/
public static short idxShort( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyShort( object, properties );
}
/**
* @param object
* @param path
* @return
*/
public static Class idxType( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyPathType( object, properties );
}
/**
* @param object
* @param path
* @return
*/
public static FieldAccess idxField( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyPathField( object, properties );
}
/**
* @param cls
* @param path
* @return
*/
public static FieldAccess idxField( Class> cls, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyPathField( cls, properties );
}
/**
* @param root
* @param properties
* @return
*/
public static char getPropertyChar( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.chr ) {
return field.getChar( object );
} else {
return Conversions.toChar( field.getValue( object ) );
}
}
/**
* @param object
* @param path
* @return
*/
public static char idxChar( Object object, String path ) {
String[] properties = propertyPathAsStringArray(path);
return getPropertyChar( object, properties );
}
/**
* @param root
* @param properties
* @return
*/
public static double getPropertyDouble( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.dbl ) {
return field.getDouble( object );
} else {
return Conversions.toDouble( field.getValue( object ) );
}
}
/**
* @param object
* @param path
* @return
*/
public static double idxDouble( Object object, String path ) {
Exceptions.requireNonNull( object );
Exceptions.requireNonNull( path );
String[] properties = propertyPathAsStringArray(path);
return getPropertyDouble( object, properties );
}
/**
* @param root
* @param properties
* @return
*/
public static long getPropertyLong( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.lng ) {
return field.getLong( object );
} else {
return Conversions.toLong( field.getValue( object ) );
}
}
/**
* @param object
* @param path
* @return
*/
public static long idxLong( Object object, String path ) {
Exceptions.requireNonNull( object );
Exceptions.requireNonNull( path );
String[] properties = propertyPathAsStringArray(path);
return getPropertyLong( object, properties );
}
/**
* @param root
* @param properties
* @return
*/
public static boolean getPropertyBoolean( final Object root,
final String... properties ) {
Object object = baseForGetProperty( root, properties );
Map fields = getFieldsFromObject( object );
final String lastProperty = properties[ properties.length - 1 ];
FieldAccess field = fields.get( lastProperty );
if ( field.type() == Typ.bln ) {
return field.getBoolean( object );
} else {
return Conversions.toBoolean( field.getValue( object ) );
}
}
public static boolean idxBoolean( Object object, String path ) {
Exceptions.requireNonNull( object );
Exceptions.requireNonNull( path );
String[] properties = propertyPathAsStringArray(path);
return getPropertyBoolean( object, properties );
}
public static Map collectionToMap( String propertyKey, Collection values ) {
LinkedHashMap map = new LinkedHashMap( values.size() );
Iterator iterator = values.iterator();
for ( V v : values ) {
String key = idxGeneric( Typ.string, v, propertyKey );
map.put( key, v );
}
return map;
}
public static void copyProperties( Object object, Map properties ) {
Set> props = properties.entrySet();
for ( Map.Entry entry : props ) {
setPropertyValue( object, entry.getValue(), entry.getKey() );
}
}
public static Object getFieldValuesFromCollection(Collection collection, final String key) {
if (collection.size() == 0) {
return Collections.EMPTY_LIST;
}
List list = new ArrayList( collection.size() );
Object firstItem;
if (collection instanceof List) {
firstItem = ((List) collection).get(0);
} else {
firstItem = collection.iterator().next();
}
if (firstItem instanceof Map) {
for (Object item : collection) {
Map map = (Map) item;
list.add( map.get(key) );
}
return list;
} else if (firstItem instanceof Collection) {
for (Object item : collection) {
list.add(_getPropertyValue(item, key));
}
return list;
} else {
Map fields =
getPropertyFieldAccessMap( Typ.getComponentType(collection) );
for (Object item : collection) {
FieldAccess field = fields.get(key);
list.add(field.getValue(item));
}
return list;
}
}
public static Object getFieldValuesFromCollection(Object object, final String key) {
if ( object == null ) {
return null;
}
if (object instanceof Collection ) {
Collection collection = (Collection) object;
if (collection.size() == 0) {
return Collections.EMPTY_LIST;
}
List list = new ArrayList( collection.size() );
Object firstItem = collection.iterator().next();
if (firstItem instanceof Map) {
for (Object item : collection) {
Map map = (Map) item;
list.add( map.get(key) );
}
return list;
} else {
Map fields =
getPropertyFieldAccessMap( Typ.getComponentType(collection) );
for (Object item : collection) {
FieldAccess field = fields.get(key);
if (field == null) {
list.add(idx(item, key));
} else {
list.add(field.getValue(item));
}
}
return list;
}
} else if ( object.getClass().isArray() ) {
int len = Array.getLength(object);
List list = new ArrayList( len );
Map fields =
getPropertyFieldAccessMap( object.getClass().getComponentType());
for (int index = 0; index < len; index++) {
list.add( fields.get(key).getValue(Array.get(object, index)));
}
return list;
}
else {
return atIndex(object, key);
}
}
public static T copy( T item ) {
if ( item instanceof Cloneable ) {
return (T) ClassMeta.classMeta(item.getClass()).invokeUntyped(item, "clone", ( Class[] ) null);
} else {
return fieldByFieldCopy( item );
}
}
public static T fieldByFieldCopy( T item ) {
final Class aClass = (Class) item.getClass();
Map fields = Reflection.getAllAccessorFields( aClass );
T clone = Reflection.newInstance( aClass );
for ( FieldAccess field : fields.values() ) {
try {
/* If the field is static or write only continue. */
if (field.isStatic() || field.isWriteOnly()) {
continue;
}
/* if the field is primitive then just inject it
and allow for conversion if needed. */
if (field.isPrimitive()) {
field.setValue(clone, field.getValue(item));
continue;
}
Object value = field.getObject(item);
if (value == null ) {
field.setObject(clone, null);
continue;
}
/* If the field is not a basic type and not a primitive then
then recursively copy a version into the field field.
*/
if (!field.isPrimitive() && !Typ.isBasicType(field.type())) {
field.setObject(clone, copy(value));
continue;
}
/* It was a basic type so just copy a reference to it. */
/* It is a basic type. */
if (Typ.isBasicType(field.type())) {
field.setObject(clone, value);
continue;
}
if (Typ.isCollection(field.type())) {
Collection