Case is ignored when converting values to true or false.
27 | * {
33 |
34 | public Boolean convert(Object value) {
35 |
36 | Boolean converted = null;
37 | if (value instanceof Number) {
38 | // numbers
39 | if (((Number)value).intValue() > 0) {
40 | converted = Boolean.TRUE;
41 | } else {
42 | converted = Boolean.FALSE;
43 | }
44 | } else {
45 | // strings and all others
46 | String stringValue = value.toString();
47 | if (stringValue != null) {
48 | stringValue = stringValue.toLowerCase();
49 | if ("0".equals(stringValue) || "".equals(stringValue)) {
50 | converted = Boolean.FALSE;
51 | } else if ("1".equals(stringValue)) {
52 | converted = Boolean.TRUE;
53 | } else {
54 | for (int i=0; i
91 | * By default any object whose string representation is one of the values
92 | * {"yes", "y", "true", "on", "1"} is converted to Boolean.TRUE, and
93 | * string representations {"no", "n", "false", "off", "0"} are converted
94 | * to Boolean.FALSE. The recognised true/false strings can be changed using the constructor
95 | * in this class and registering it with the {@link ConversionUtils}:
96 | *
97 | * String[] trueStrings = {"oui", "o"};
98 | * String[] falseStrings = {"non", "n"};
99 | * Converter bc = new BooleanConverter(trueStrings, falseStrings);
100 | *
101 | * @param trueStrings these strings map to true
102 | * @param falseStrings these strings map to false
103 | */
104 | public BooleanConverter(String[] trueStrings, String[] falseStrings) {
105 | this.falseStrings = copyStrings(falseStrings);
106 | this.trueStrings = copyStrings(trueStrings);
107 | }
108 |
109 | /**
110 | * This method creates a copy of the provided array, and ensures that
111 | * all the strings in the newly created array contain only lower-case
112 | * letters.
113 | *
114 | * Using this method to copy string arrays means that changes to the
115 | * src array do not modify the dst array.
116 | */
117 | private static String[] copyStrings(String[] src) {
118 | String[] dst = new String[src.length];
119 | for(int i=0; i encoders) {
43 | String encoded = null;
44 | if (encoders != null) {
45 | for (ObjectEncoder encoder : encoders) {
46 | try {
47 | encoded = encoder.encodeObject(object);
48 | } catch (Exception e) {
49 | // nothing to do here but skip to the next one
50 | encoded = null;
51 | }
52 | if (encoded != null) {
53 | break; // break out of the loop because we are done
54 | }
55 | }
56 | }
57 | if (encoded == null) {
58 | encoded = checkObjectSpecial(object);
59 | }
60 | return encoded;
61 | }
62 |
63 | /**
64 | * This will ensure that no objects that are known to be impossible to serialize properly will
65 | * cause problems with the transcoders by allowing them to go into loops
66 | *
67 | * @param object
68 | * @return a null if the current object is not special, an empty string to indicate the
69 | * object should be skipped over with no output, and any string value to indicate the
70 | * return value to use instead of attempting to encode the object
71 | */
72 | public static String checkObjectSpecial(Object object) {
73 | String special = null;
74 | if (object != null) {
75 | Class> type = object.getClass();
76 | if (Class.class.isAssignableFrom(type)) {
77 | // class objects are serialized as the full name
78 | special = ((Class>)object).getName();
79 | } else if (Type.class.isAssignableFrom(type)) {
80 | // type just does to string
81 | special = ((Type)object).toString();
82 | } else if (Package.class.isAssignableFrom(type)) {
83 | // package uses name only
84 | special = ((Package)object).getName();
85 | } else if (ClassLoader.class.isAssignableFrom(type)) {
86 | // classloaders are skipped over entirely
87 | special = "";
88 | } else if (InputStream.class.isAssignableFrom(type)) {
89 | // skip IS
90 | special = "";
91 | } else if (OutputStream.class.isAssignableFrom(type)) {
92 | // skip OS
93 | special = "";
94 | } else if (InputStream.class.isAssignableFrom(type)) {
95 | // skip IS
96 | special = "";
97 | } else if (Writer.class.isAssignableFrom(type)) {
98 | // skip writer
99 | special = "";
100 | } else if (Reader.class.isAssignableFrom(type)) {
101 | // turn reader into string
102 | Reader reader = ((Reader)object);
103 | StringBuilder sb = new StringBuilder();
104 | try {
105 | while (reader.ready()) {
106 | int c = reader.read();
107 | if (c <= -1) {
108 | break;
109 | }
110 | sb.append((char) c);
111 | }
112 | special = sb.toString();
113 | } catch (IOException e) {
114 | special = "Could not read from Reader ("+reader.toString()+"): " + e.getMessage();
115 | }
116 | }
117 | }
118 | return special;
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # reflectutils
2 | A set of reflection utilities and miscellaneous utilities related to working with classes and their fields with no dependencies which is compatible with java 1.5 and generics (and the higher versions of Java as well).
3 |
4 | # Features:
5 | These are built to be compatible with Apache Commons BeanUtils (http://commons.apache.org/proper/commons-beanutils/) and the nesting structure works the same, refer to the apache BeanUtils? project docs for details. Support for Apache DynaClass? / DynaBean? is included. Current users of beanutils should be able to drop in these utilities and gain the functionality with minimal code changes.
6 |
7 | Handles field operations for properties (getters and setters), partial properties (only getter or only setter), and fields. This is configurable to use the fields only, properties only, or the hybrid approach (default). This improves upon the BeanUtils? limitation of handling only properties or the Google utilities limitation of handling only fields.
8 |
9 | Getting and setting fields supports simple, nested, indexed, and mapped values
10 |
11 | **Simple:** Get/set a field in a bean (or map), Example: "title", "id"
12 | **Nested:** Get/set a field in a bean which is contained in another bean, Example: "someBean.title", "someBean.id"
13 | **Indexed:** Get/set a list/array item by index in a bean, Example: "myList1?", "anArray2?"
14 | **Mapped:** Get/set a map entry by key in a bean, Example: "myMap(key)", "someMap(thing)"
15 |
16 | Includes support for dealing with annotations and working with fields which have annotations on them. Methods for finding fields with an annotation and finding all annotations in a class or on a fields are included.
17 |
18 | Includes support for deep cloning, deep copying, and populating objects using auto-conversion. Also includes support for fuzzy copies where object data can be copied from one object to another without the objects being the same type.
19 |
20 | Also includes an extendable conversion system for converting between java types. This system also handles conversions between arrays, maps, collections, enums, and scalars and improves upon the apache system by handling more types and handling object holders. Support for construction of any class and a set of utilities for determining what types of objects you are working with are also included. A method for executing a specific constructor can be used if more control is needed.
21 |
22 | Includes transcoders (encoder/decoder) for conversion of class data to and from JSON and XML. The transcoders are clean and simple and work with any type of object. They will default to converting the incoming data into maps of simple java objects but these can be converted to the correct objects using the reflection utilities if desired.
23 |
24 | The utilities cache reflection data for high performance operation but uses weak/soft caching to avoid holding open ClassLoaders? and causing the caches to exist in memory permanently. The ability to override the caching mechanism with your own is supported.
25 |
26 | The utilities are modular and are meant to be extendable and overridable. All methods are protected or public so that the various utility classes can be easily overridden if needed.
27 |
28 | Sample code:
29 | Examples operate on the class at the bottom (TestEntity). There are more samples in the javadocs.
30 |
31 | Getting a value from an object field
32 | TestEntity thing = new TestEntity();
33 | Object value = ReflectUtils.getInstance().getFieldValue(thing, "entityId");
34 | // value will be "33"
35 | Setting a value on an object field
36 | TestEntity thing = new TestEntity();
37 | ReflectUtils.getInstance().setFieldValue(thing, "entityId", 33);
38 | // value of thing.getEntityId() will be "33", value is autoconverted into the right type
39 | Setting a nested value on an object field
40 | Object thing = new HashMap(); // using a hashmap for simplicity here, could easily be nested POJOs
41 | ReflectUtils.getInstance().setFieldValue(thing, "person.contactInfo.name", "aaronz");
42 | // the value of the name field which is on the object in the contactInfo field which is on the object in the person field on the thing object is set to "aaronz"
43 | Constructing classes
44 | List l = ReflectUtils.getInstance().constructClass(List.class);
45 | Class> clazz = TestEntity.class;
46 | Object o = ReflectUtils.getInstance().constructClass(clazz);
47 | // o will be an instance of TestEntity
48 | TestEntity?.class (comes directly from the test cases)
49 |
50 | public class TestEntity {
51 | private Long id = new Long(3);
52 | private String entityId = "33";
53 | @TestAnnote
54 | private String extra = null;
55 | private Boolean bool = null;
56 | private String[] sArray = {"1","2"};
57 |
58 | public String getPrefix() {
59 | return "crud";
60 | }
61 | public String createEntity(Object entity) {
62 | return "1";
63 | }
64 | @TestAnnote
65 | public String getEntityId() {
66 | return entityId;
67 | }
68 | public void setEntityId(String entityId) {
69 | this.entityId = entityId;
70 | }
71 | public Long getId() {
72 | return id;
73 | }
74 | public void setId(Long id) {
75 | this.id = id;
76 | }
77 | @TestAnnoteField1
78 | public String getExtra() {
79 | return extra;
80 | }
81 | @TestAnnoteField2("TEST")
82 | public void setExtra(String extra) {
83 | this.extra = extra;
84 | }
85 | public String[] getSArray() {
86 | return sArray;
87 | }
88 | public void setSArray(String[] array) {
89 | sArray = array;
90 | }
91 | public Boolean getBool() {
92 | return bool;
93 | }
94 | public void setBool(Boolean bool) {
95 | this.bool = bool;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/org/azeckoski/reflectutils/converters/ScalarConverter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * $Id: ScalarConverter.java 2 2008-10-01 10:04:26Z azeckoski $
3 | * $URL: http://reflectutils.googlecode.com/svn/trunk/src/main/java/org/azeckoski/reflectutils/converters/ScalarConverter.java $
4 | * ScalarConverter.java - genericdao - Sep 10, 2008 3:53:32 PM - azeckoski
5 | **************************************************************************
6 | * Copyright (c) 2008 Aaron Zeckoski
7 | * Licensed under the Apache License, Version 2.0
8 | *
9 | * A copy of the Apache License has been included in this
10 | * distribution and is available at: http://www.apache.org/licenses/LICENSE-2.0.txt
11 | *
12 | * Aaron Zeckoski (azeckoski @ gmail.com) (aaronz @ vt.edu) (aaron @ caret.cam.ac.uk)
13 | */
14 |
15 | package org.azeckoski.reflectutils.converters;
16 |
17 | import java.lang.reflect.Array;
18 | import java.util.Collection;
19 | import java.util.Map;
20 |
21 | import org.azeckoski.reflectutils.ArrayUtils;
22 | import org.azeckoski.reflectutils.ConstructorUtils;
23 | import org.azeckoski.reflectutils.ConversionUtils;
24 | import org.azeckoski.reflectutils.DeepUtils;
25 | import org.azeckoski.reflectutils.converters.api.VariableConverter;
26 |
27 |
28 | /**
29 | * This is a special variable converter designed to handle the special case of converting
30 | * from a non-scalar (collection, array, list, etc.) to a scalar object
31 | *
32 | * @author Aaron Zeckoski (azeckoski @ gmail.com)
33 | */
34 | public class ScalarConverter implements VariableConverter {
35 |
36 | /* (non-Javadoc)
37 | * @see org.azeckoski.reflectutils.converters.api.VariableConverter#canConvert(java.lang.Object, java.lang.Class)
38 | */
39 | public boolean canConvert(Object value, Class> toType) {
40 | boolean convertible = false;
41 | if (value != null) {
42 | Class> fromType = value.getClass();
43 | if ( ConstructorUtils.isClassObjectHolder(fromType) ) {
44 | // converting from a non-scalar
45 | if (! ConstructorUtils.isClassObjectHolder(toType) ) {
46 | // to a scalar
47 | convertible = true;
48 | }
49 | }
50 | }
51 | return convertible;
52 | }
53 |
54 | protected ConversionUtils getConversionUtils() {
55 | return ConversionUtils.getInstance();
56 | }
57 |
58 | protected ConstructorUtils getConstructorUtils() {
59 | return ConstructorUtils.getInstance();
60 | }
61 |
62 | protected DeepUtils getDeepUtils() {
63 | return DeepUtils.getInstance();
64 | }
65 |
66 | /* (non-Javadoc)
67 | * @see org.azeckoski.reflectutils.converters.api.VariableConverter#convert(java.lang.Object, java.lang.Class)
68 | */
69 | @SuppressWarnings("unchecked")
70 | public T convert(Object value, Class toType) {
71 | // we know that fromType is a holder and toType is a scalar
72 | T convert = null;
73 | Class> fromType = value.getClass();
74 | Object toConvert = value;
75 |
76 | if ( ConstructorUtils.isClassArray(fromType) ) {
77 | // from array
78 | int length = Array.getLength(toConvert);
79 | if (length > 0) {
80 | Class> componentType = fromType.getComponentType();
81 | if ( String.class.equals(toType)
82 | && ConstructorUtils.isClassSimple(componentType)) {
83 | return (T) ArrayUtils.arrayToString((Object[]) value);
84 | } else {
85 | // get the first one
86 | toConvert = Array.get(toConvert, 0);
87 | }
88 | } else {
89 | // empty so use empty string
90 | toConvert = "";
91 | }
92 | } else if ( ConstructorUtils.isClassCollection(fromType) ) {
93 | // from collection
94 | Collection> collection = (Collection) toConvert;
95 | int length = collection.size();
96 | // to scalar
97 | if (length > 0) {
98 | // get the first one (random)
99 | toConvert = collection.iterator().next();
100 | } else {
101 | // empty so use empty string
102 | toConvert = "";
103 | }
104 | } else if ( ConstructorUtils.isClassMap(fromType) ) {
105 | // from map
106 | Map map = (Map) toConvert;
107 | int length = map.size();
108 | // to scalar
109 | if (length > 0) {
110 | // check if the keys are strings and the toType is non-simple
111 | boolean stringKeys = false;
112 | for (Object key : map.keySet()) {
113 | if (String.class.equals(key.getClass())) {
114 | stringKeys = true;
115 | } else {
116 | stringKeys = false;
117 | break;
118 | }
119 | }
120 | if (stringKeys
121 | && ! ConstructorUtils.isClassSimple(toType) ) {
122 | // this is a bean so populate it with the map data
123 | convert = getConstructorUtils().constructClass(toType);
124 | getDeepUtils().populate(convert, map); // put the values from the map into the object
125 | return convert; // EXIT
126 | } else {
127 | // just get the first one (random)
128 | toConvert = map.values().iterator().next();
129 | }
130 | } else {
131 | // empty so use empty string
132 | toConvert = "";
133 | }
134 | } else {
135 | // should not happen
136 | throw new IllegalArgumentException("Failure converting to scalar value, the given input does not seem to be an object holder ("+fromType+"): " + value);
137 | }
138 |
139 | // now convert the object from the holder
140 | convert = getConversionUtils().convert(toConvert, toType);
141 | return convert;
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/java/overview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
A set of reflection utilities and miscellaneous utilities related to working with classes and their fields with no dependencies which is compatible with java 1.5 and generics.
Features:
These are built to be compatible with Apache Commons BeanUtils and the nesting structure works the same, refer to the apache BeanUtils project docs for details. Support for Apache DynaClass / DynaBean is included. Current users of beanutils should be able to drop in these utilities and gain the functionality with minimal code changes.
Handles field operations for properties (getters and setters), partial properties (only getter or only setter), and fields. This is configurable to use the fields only, properties only, or the hybrid approach (default). This improves upon the BeanUtils limitation of handling only properties or the Google utilities limitation of handling only fields.
Getting and setting fields supports simple, nested, indexed, and mapped values
- Simple: Get/set a field in a bean (or map), Example: "title", "id"
- Nested: Get/set a field in a bean which is contained in another bean, Example: "someBean.title", "someBean.id"
- Indexed: Get/set a list/array item by index in a bean, Example: "myList1", "anArray2"
- Mapped: Get/set a map entry by key in a bean, Example: "myMap(key)", "someMap(thing)"
Includes support for dealing with annotations and working with fields which have annotations on them. Methods for finding fields with an annotation and finding all annotations in a class or on a fields are included.
Includes support for deep cloning, deep copying, and populating objects using auto-conversion. Also includes support for fuzzy copies where object data can be copied from one object to another without the objects being the same type.
Also includes an extendable conversion system for converting between java types. This system also handles conversions between arrays, maps, collections, enums, and scalars and improves upon the apache system by handling more types and handling object holders. Support for construction of any class and a set of utilities for determining what types of objects you are working with are also included. A method for executing a specific constructor can be used if more control if needed.
Includes transcoders (encoder/decoder) for conversion of class data to and from JSON and XML. The transcoders are clean and simple and work with any type of object. They will default to converting the incoming data into maps of simple java objects but these can be converted to the correct objects using the reflection utilities if desired.
The utilities cache reflection data for high performance operation but uses weak/soft caching to avoid holding open ClassLoaders and causing the caches to exist in memory permanently. The ability to override the caching mechanism with your own is supported.
The utilities are modular and are meant to be extendable and overridable. All methods are protected or public so that the various utility classes can be easily overridden if needed.
Sample code:
Examples operate on the class at the bottom (TestEntity). There are more samples in the guide.
- Getting a value from an object field
TestEntity thing = new TestEntity();
5 | Object value = ReflectUtils.getInstance().getFieldValue(thing, "entityId");
6 | // value will be "33"
- Setting a value on an object field
TestEntity thing = new TestEntity();
7 | ReflectUtils.getInstance().setFieldValue(thing, "entityId", 33);
8 | // value of thing.getEntityId() will be "33", value is autoconverted into the right type
- Setting a nested value on an object field
Object thing = new HashMap(); // using a hashmap for simplicity here, could easily be nested POJOs
9 | ReflectUtils.getInstance().setFieldValue(thing, "person.contactInfo.name", "aaronz");
10 | // the value of the name field which is on the object in the contactInfo field which is on the object in the person field on the thing object is set to "aaronz"
List l = ReflectUtils.getInstance().constructClass(List.class);
11 | Class<?> clazz = TestEntity.class;
12 | Object o = ReflectUtils.getInstance().constructClass(clazz);
13 | // o will be an instance of TestEntity
14 |
TestEntity.class (comes directly from the test cases)
public class TestEntity {
15 | private Long id = new Long(3);
16 | private String entityId = "33";
17 | \@TestAnnote
18 | private String extra = null;
19 | private Boolean bool = null;
20 | private String[] sArray = {"1","2"};
21 |
22 | public String getPrefix() {
23 | return "crud";
24 | }
25 | public String createEntity(Object entity) {
26 | return "1";
27 | }
28 | \@TestAnnote
29 | public String getEntityId() {
30 | return entityId;
31 | }
32 | public void setEntityId(String entityId) {
33 | this.entityId = entityId;
34 | }
35 | public Long getId() {
36 | return id;
37 | }
38 | public void setId(Long id) {
39 | this.id = id;
40 | }
41 | \@TestAnnoteField1
42 | public String getExtra() {
43 | return extra;
44 | }
45 | \@TestAnnoteField2("TEST")
46 | public void setExtra(String extra) {
47 | this.extra = extra;
48 | }
49 | public String[] getSArray() {
50 | return sArray;
51 | }
52 | public void setSArray(String[] array) {
53 | sArray = array;
54 | }
55 | public Boolean getBool() {
56 | return bool;
57 | }
58 | public void setBool(Boolean bool) {
59 | this.bool = bool;
60 | }
61 | }
62 |
63 |
64 | You are encouraged to look at the test cases (available in the source code) which illustrate uses of the utilities
65 | far better than the documentation.
66 |
67 |
68 |
--------------------------------------------------------------------------------
/src/main/java/org/azeckoski/reflectutils/beanutils/FieldAdapter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * $Id: FieldAdapter.java 2 2008-10-01 10:04:26Z azeckoski $
3 | * $URL: http://reflectutils.googlecode.com/svn/trunk/src/main/java/org/azeckoski/reflectutils/beanutils/FieldAdapter.java $
4 | * FieldAdapter.java - genericdao - Sep 20, 2008 8:15:36 AM - azeckoski
5 | **************************************************************************
6 | * Copyright (c) 2008 Aaron Zeckoski
7 | * Licensed under the Apache License, Version 2.0
8 | *
9 | * A copy of the Apache License has been included in this
10 | * distribution and is available at: http://www.apache.org/licenses/LICENSE-2.0.txt
11 | *
12 | * Aaron Zeckoski (azeckoski @ gmail.com) (aaronz @ vt.edu) (aaron @ caret.cam.ac.uk)
13 | */
14 |
15 | package org.azeckoski.reflectutils.beanutils;
16 |
17 | import java.util.List;
18 | import java.util.Map;
19 |
20 | import org.azeckoski.reflectutils.ClassFields.FieldsFilter;
21 | import org.azeckoski.reflectutils.exceptions.FieldGetValueException;
22 | import org.azeckoski.reflectutils.exceptions.FieldSetValueException;
23 | import org.azeckoski.reflectutils.exceptions.FieldnameNotFoundException;
24 |
25 |
26 | /**
27 | * Interface that allows us to adapt to special class types like the apache dynabeans without
28 | * requiring them to be a dependency unless they happen to be in the ClassLoader
29 | *
30 | * @author Aaron Zeckoski (azeckoski @ gmail.com)
31 | */
32 | public interface FieldAdapter {
33 |
34 | /**
35 | * @param obj any object
36 | * @return true if this object is part of the set this adapter is made to handle, false otherwise
37 | */
38 | public boolean isAdaptableObject(Object obj);
39 |
40 | /**
41 | * @param beanClass any class
42 | * @return true if this class is adaptable, false otherwise
43 | */
44 | public boolean isAdaptableClass(Class> beanClass);
45 |
46 | /**
47 | * @return a new instance of the adapted class type based on a sample
48 | */
49 | public Object newInstance(Object bean);
50 |
51 | /**
52 | * @param bean any bean of the adaptable class type
53 | * @return the list of property names for that bean
54 | */
55 | public List getPropertyNames(Object bean);
56 |
57 | /**
58 | * Finds the type for a field based on the containing object and the field name
59 | * @param obj any object
60 | * @param name the name of a field in this object (can be nested, indexed, mapped, etc.)
61 | * @return the type of the field (will be {@link Object} if the type is indeterminate)
62 | * @throws FieldnameNotFoundException if the name is invalid for this obj
63 | * @throws IllegalArgumentException if the params are null
64 | */
65 | public Class> getFieldType(Object obj, String name);
66 |
67 | /**
68 | * Get the values of all fields on an object but optionally filter the fields used
69 | * @param obj any object
70 | * @param filter (optional) indicates the fields to return the values for, can be null for defaults
71 | * WARNING: getting the field values from settable only fields works as expected (i.e. you will an empty map)
72 | * @return a map of field name -> value
73 | * @throws IllegalArgumentException if the obj is null
74 | */
75 | public Map getFieldValues(Object obj, FieldsFilter filter);
76 |
77 | /**
78 | * For getting a value out of a bean based on a field name,
79 | * mostly for internal usage, use getFieldValue
80 | *
81 | * WARNING: Cannot handle a nested/mapped/indexed name
82 | *
83 | * @throws FieldnameNotFoundException if this field name is invalid for this object
84 | * @throws IllegalArgumentException if there is failure
85 | */
86 | public Object getSimpleValue(Object obj, String name);
87 |
88 | /**
89 | * For getting an indexed value out of an object based on field name,
90 | * mostly for internal usage, use getFieldValue
91 | *
92 | * WARNING: Cannot handle a nested/mapped/indexed name
93 | *
94 | * @throws FieldnameNotFoundException if this field name is invalid for this object
95 | * @throws IllegalArgumentException if there is a failure
96 | * @throws FieldGetValueException if there is an internal failure getting the field
97 | */
98 | public Object getIndexedValue(Object obj, String name, int index);
99 |
100 | /**
101 | * For getting a mapped value out of an object based on field name,
102 | * mostly for internal usage, use getFieldValue
103 | *
104 | * WARNING: Cannot handle a nested/mapped/indexed name
105 | * @throws FieldnameNotFoundException if this field name is invalid for this object
106 | * @throws IllegalArgumentException if there are invalid arguments
107 | * @throws FieldGetValueException if there is an internal failure getting the field
108 | */
109 | public Object getMappedValue(Object obj, String name, String key);
110 |
111 | /**
112 | * Set a value on a field of an object, the types must match and the name must be identical
113 | *
114 | * WARNING: Cannot handle a nested/mapped/indexed name
115 | * @throws FieldnameNotFoundException if this field name is invalid for this object
116 | * @throws IllegalArgumentException if there is failure
117 | * @throws FieldSetValueException if there is an internal failure setting the field
118 | */
119 | public void setSimpleValue(Object obj, String name, Object value);
120 |
121 | /**
122 | * For getting an indexed value out of an object based on field name,
123 | * mostly for internal usage, use getFieldValue
124 | *
125 | * WARNING: Cannot handle a nested/mapped/indexed name
126 | * @throws FieldnameNotFoundException if this field name is invalid for this object
127 | * @throws IllegalArgumentException if there is failure
128 | * @throws FieldSetValueException if there is an internal failure setting the field
129 | */
130 | public void setIndexedValue(Object obj, String name, int index, Object value);
131 |
132 | /**
133 | * For getting a mapped value out of an object based on field name,
134 | * mostly for internal usage, use getFieldValue
135 | *
136 | * WARNING: Cannot handle a nested/mapped/indexed name
137 | * @throws FieldnameNotFoundException if this field name is invalid for this object
138 | * @throws IllegalArgumentException if there is failure
139 | * @throws FieldSetValueException if there is an internal failure setting the field
140 | */
141 | public void setMappedValue(Object obj, String name, String key, Object value);
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/org/azeckoski/reflectutils/beanutils/Resolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.azeckoski.reflectutils.beanutils;
18 |
19 | /**
20 | * Property Name Expression Resolver.
21 | *
22 | * Methods such as PropertyUtilsBean's setNestedProperty() method
23 | * use a Resolver to process a property name
24 | * expression and resolve nested, indexed and mapped
25 | * property names. The following code provides an example usage
26 | * demonstrating all the methods:
27 | *
28 | *
29 | * // Iterate through a nested property expression
30 | * while (resolver.hasNested(name)) {
31 | *
32 | * // isolate a single property from a nested expresion
33 | * String next = resolver.next(name);
34 | *
35 | * // Process...
36 | * String property = resolver.getProperty(next);
37 | * if (resolver.isIndexed(next)) {
38 | *
39 | * int index = resolver.getIndex(next);
40 | * bean = getIndexedProperty(bean, property, index);
41 | *
42 | * } else if (resolver.isMapped(next)) {
43 | *
44 | * String key = resolver.getKey(next);
45 | * bean = getMappedProperty(bean, property, key);
46 | *
47 | * } else {
48 | *
49 | * bean = getSimpleProperty(bean, property);
50 | *
51 | * }
52 | *
53 | * // remove the processed property from the expression
54 | * name = resolver.remove(name);
55 | * }
56 | *
57 | *
58 | * In order to create an implementation, it is important to understand how
59 | * BeanUtils/PropertyUtils uses the resolver. The following are
60 | * the main methods that use it:
61 | *
62 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean}
63 | *
64 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#getIndexedProperty(Object, String)}
65 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#getMappedProperty(Object, String)}
66 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#getNestedProperty(Object, String)}
67 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#getPropertyDescriptor(Object, String)}
68 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#getSimpleProperty(Object, String)}
69 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#setIndexedProperty(Object, String, Object)}
70 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#setMappedProperty(Object, String, Object)}
71 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#setNestedProperty(Object, String, Object)}
72 | * - {@link org.apache.commons.beanutils.PropertyUtilsBean#setSimpleProperty(Object, String, Object)}
73 | *
74 | * - {@link org.apache.commons.beanutils.BeanUtilsBean}
75 | *
76 | * - {@link org.apache.commons.beanutils.BeanUtilsBean#copyProperty(Object, String, Object)}
77 | * - {@link org.apache.commons.beanutils.BeanUtilsBean#setProperty(Object, String, Object)}
78 | *
79 | * - {@link org.apache.commons.beanutils.locale.LocaleBeanUtilsBean}
80 | *
81 | * - {@link org.apache.commons.beanutils.locale.LocaleBeanUtilsBean#setProperty(Object,
82 | * String, Object, String)}
83 | *
84 | *
85 | *
86 | * @version $Revision: 2 $ $Date: 2008-10-01 05:04:26 -0500 (Wed, 01 Oct 2008) $
87 | * @see org.apache.commons.beanutils.PropertyUtilsBean#setResolver(Resolver)
88 | * @since 1.8.0
89 | */
90 | public interface Resolver {
91 |
92 | /**
93 | * Extract the index value from the property expression or -1.
94 | *
95 | * @param expression The property expression
96 | * @return The index value or -1 if the property is not indexed
97 | * @throws IllegalArgumentException If the indexed property is illegally
98 | * formed or has an invalid (non-numeric) value
99 | */
100 | int getIndex(String expression);
101 |
102 | /**
103 | * Extract the map key from the property expression or null.
104 | *
105 | * @param expression The property expression
106 | * @return The index value
107 | * @throws IllegalArgumentException If the mapped property is illegally formed
108 | */
109 | String getKey(String expression);
110 |
111 | /**
112 | * Return the property name from the property expression.
113 | *
114 | * @param expression The property expression
115 | * @return The property name
116 | */
117 | String getProperty(String expression);
118 |
119 | /**
120 | * Indicates whether or not the expression
121 | * contains nested property expressions or not.
122 | *
123 | * @param expression The property expression
124 | * @return The next property expression
125 | */
126 | boolean hasNested(String expression);
127 |
128 | /**
129 | * Indicate whether the expression is for an indexed property or not.
130 | *
131 | * @param expression The property expression
132 | * @return true if the expresion is indexed,
133 | * otherwise false
134 | */
135 | boolean isIndexed(String expression);
136 |
137 | /**
138 | * Indicate whether the expression is for a mapped property or not.
139 | *
140 | * @param expression The property expression
141 | * @return true if the expresion is mapped,
142 | * otherwise false
143 | */
144 | boolean isMapped(String expression);
145 |
146 | /**
147 | * Extract the next property expression from the
148 | * current expression.
149 | *
150 | * @param expression The property expression
151 | * @return The next property expression
152 | */
153 | String next(String expression);
154 |
155 | /**
156 | * Remove the last property expresson from the
157 | * current expression.
158 | *
159 | * @param expression The property expression
160 | * @return The new expression value, with first property
161 | * expression removed - null if there are no more expressions
162 | */
163 | String remove(String expression);
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/src/main/java/org/azeckoski/reflectutils/beanutils/DynaBeanAdapter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * $Id: DynaBeanAdapter.java 2 2008-10-01 10:04:26Z azeckoski $
3 | * $URL: http://reflectutils.googlecode.com/svn/trunk/src/main/java/org/azeckoski/reflectutils/beanutils/DynaBeanAdapter.java $
4 | * DynaBeanAdapter.java - genericdao - Sep 20, 2008 10:08:01 AM - azeckoski
5 | **************************************************************************
6 | * Copyright (c) 2008 Aaron Zeckoski
7 | * Licensed under the Apache License, Version 2.0
8 | *
9 | * A copy of the Apache License has been included in this
10 | * distribution and is available at: http://www.apache.org/licenses/LICENSE-2.0.txt
11 | *
12 | * Aaron Zeckoski (azeckoski @ gmail.com) (aaronz @ vt.edu) (aaron @ caret.cam.ac.uk)
13 | */
14 |
15 | package org.azeckoski.reflectutils.beanutils;
16 |
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 | import java.util.List;
20 | import java.util.Map;
21 |
22 | import org.azeckoski.reflectutils.ClassFields.FieldsFilter;
23 | import org.azeckoski.reflectutils.exceptions.FieldnameNotFoundException;
24 |
25 | import org.apache.commons.beanutils.DynaBean;
26 | import org.apache.commons.beanutils.DynaClass;
27 | import org.apache.commons.beanutils.DynaProperty;
28 |
29 |
30 | /**
31 | * This allows dynabeans to work with the field utils,
32 | * should only be loaded by reflection if the DynaBean class can be found
33 | *
34 | * @author Aaron Zeckoski (azeckoski @ gmail.com)
35 | */
36 | public class DynaBeanAdapter implements FieldAdapter {
37 |
38 | public boolean isAdaptableObject(Object obj) {
39 | boolean adaptable = false;
40 | if (obj instanceof DynaBean) {
41 | adaptable = true;
42 | }
43 | return adaptable;
44 | }
45 |
46 | public boolean isAdaptableClass(Class> beanClass) {
47 | boolean adaptable = false;
48 | if (DynaBean.class.isAssignableFrom(beanClass)) {
49 | adaptable = true;
50 | }
51 | return adaptable;
52 | }
53 |
54 | /* (non-Javadoc)
55 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#getFieldType(java.lang.Object, java.lang.String)
56 | */
57 | public Class> getFieldType(Object obj, String name) {
58 | DynaClass dynaClass = ((DynaBean) obj).getDynaClass();
59 | DynaProperty dynaProperty = dynaClass.getDynaProperty(name);
60 | if (dynaProperty == null) {
61 | throw new FieldnameNotFoundException("DynaBean: Could not find this fieldName ("+name+") on the target object: " + obj, name, null);
62 | }
63 | return dynaProperty.getType();
64 | }
65 |
66 | /* (non-Javadoc)
67 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#getFieldValues(java.lang.Object, org.azeckoski.reflectutils.ClassFields.FieldsFilter)
68 | */
69 | public Map getFieldValues(Object obj, FieldsFilter filter) {
70 | Map values = new HashMap();
71 | DynaProperty[] descriptors =
72 | ((DynaBean) obj).getDynaClass().getDynaProperties();
73 | for (int i = 0; i < descriptors.length; i++) {
74 | String name = descriptors[i].getName();
75 | // cannot filter the values for dynabeans -AZ
76 | Object o = getSimpleValue(obj, name);
77 | values.put(name, o);
78 | }
79 | return values;
80 | }
81 |
82 | /* (non-Javadoc)
83 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#getSimpleValue(java.lang.Object, java.lang.String)
84 | */
85 | public Object getSimpleValue(Object obj, String name) {
86 | DynaProperty descriptor =
87 | ((DynaBean) obj).getDynaClass().getDynaProperty(name);
88 | if (descriptor == null) {
89 | throw new FieldnameNotFoundException(name);
90 | }
91 | Object value = (((DynaBean) obj).get(name));
92 | return value;
93 | }
94 |
95 | /* (non-Javadoc)
96 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#getIndexedValue(java.lang.Object, java.lang.String, int)
97 | */
98 | public Object getIndexedValue(Object obj, String name, int index) {
99 | DynaProperty descriptor =
100 | ((DynaBean) obj).getDynaClass().getDynaProperty(name);
101 | if (descriptor == null) {
102 | throw new FieldnameNotFoundException(name);
103 | }
104 | Object value = ((DynaBean) obj).get(name, index);
105 | return value;
106 | }
107 |
108 | /* (non-Javadoc)
109 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#getMappedValue(java.lang.Object, java.lang.String, java.lang.String)
110 | */
111 | public Object getMappedValue(Object obj, String name, String key) {
112 | DynaProperty descriptor =
113 | ((DynaBean) obj).getDynaClass().getDynaProperty(name);
114 | if (descriptor == null) {
115 | throw new FieldnameNotFoundException(name);
116 | }
117 | Object value = ((DynaBean) obj).get(name, key);
118 | return value;
119 | }
120 |
121 | /* (non-Javadoc)
122 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#setIndexedValue(java.lang.Object, java.lang.String, int, java.lang.Object)
123 | */
124 | public void setIndexedValue(Object obj, String name, int index, Object value) {
125 | DynaProperty descriptor =
126 | ((DynaBean) obj).getDynaClass().getDynaProperty(name);
127 | if (descriptor == null) {
128 | throw new FieldnameNotFoundException(name);
129 | }
130 | ((DynaBean) obj).set(name, index, value);
131 | }
132 |
133 | /* (non-Javadoc)
134 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#setMappedValue(java.lang.Object, java.lang.String, java.lang.String, java.lang.Object)
135 | */
136 | public void setMappedValue(Object obj, String name, String key, Object value) {
137 | DynaProperty descriptor =
138 | ((DynaBean) obj).getDynaClass().getDynaProperty(name);
139 | if (descriptor == null) {
140 | throw new FieldnameNotFoundException(name);
141 | }
142 | ((DynaBean) obj).set(name, key, value);
143 | }
144 |
145 | /* (non-Javadoc)
146 | * @see org.azeckoski.reflectutils.beanutils.FieldAdapter#setSimpleValue(java.lang.Object, java.lang.String, java.lang.Object)
147 | */
148 | public void setSimpleValue(Object obj, String name, Object value) {
149 | DynaProperty descriptor =
150 | ((DynaBean) obj).getDynaClass().getDynaProperty(name);
151 | if (descriptor == null) {
152 | throw new FieldnameNotFoundException(name);
153 | }
154 | ((DynaBean) obj).set(name, value);
155 | }
156 |
157 | public Object newInstance(Object bean) {
158 | try {
159 | return ((DynaBean) bean).getDynaClass().newInstance();
160 | } catch (Exception e) {
161 | throw new RuntimeException("Could not instantiate DynaBean: " + bean, e);
162 | } // make new dynabean
163 | }
164 |
165 | public List getPropertyNames(Object bean) {
166 | List names = new ArrayList();
167 | DynaProperty origDescriptors[] =
168 | ((DynaBean) bean).getDynaClass().getDynaProperties();
169 | for (DynaProperty dynaProperty : origDescriptors) {
170 | String name = dynaProperty.getName();
171 | names.add(name);
172 | }
173 | return names;
174 | }
175 |
176 | }
177 |
--------------------------------------------------------------------------------