diff --git a/src/com/esotericsoftware/yamlbeans/Beans.java b/src/com/esotericsoftware/yamlbeans/Beans.java
index 7aa2a59..454be78 100644
--- a/src/com/esotericsoftware/yamlbeans/Beans.java
+++ b/src/com/esotericsoftware/yamlbeans/Beans.java
@@ -16,15 +16,11 @@
package com.esotericsoftware.yamlbeans;
-import com.esotericsoftware.yamlbeans.YamlConfig.ConstructorParameters;
-
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
@@ -35,6 +31,8 @@
import java.util.Set;
import java.util.TreeSet;
+import com.esotericsoftware.yamlbeans.YamlConfig.ConstructorParameters;
+
/** Utility for dealing with beans and public fields.
* @author Nathan Sweet */
class Beans {
@@ -62,16 +60,6 @@ static public DeferredConstruction getDeferredConstruction (Class type, YamlConf
return null;
}
- static private boolean canInitializeProperty (Class type, PropertyDescriptor property, YamlConfig config) {
- if (property.getWriteMethod() != null) return true;
-
- // Check if the property can be initialized through the constructor.
- DeferredConstruction deferredConstruction = getDeferredConstruction(type, config);
- if (deferredConstruction != null && deferredConstruction.hasParameter(property.getName())) return true;
-
- return false;
- }
-
static public Object createObject (Class type, boolean privateConstructors) throws InvocationTargetException {
// Use no-arg constructor.
Constructor constructor = null;
@@ -117,16 +105,34 @@ static public Object createObject (Class type, boolean privateConstructors) thro
}
}
- static public Set getProperties (Class type, boolean beanProperties, boolean privateFields, YamlConfig config)
- throws IntrospectionException {
+ static public Set getProperties (Class type, boolean beanProperties, boolean privateFields, YamlConfig config) {
if (type == null) throw new IllegalArgumentException("type cannot be null.");
+ Class[] noArgs = new Class[0], oneArg = new Class[1];
Set properties = new TreeSet();
- if (beanProperties) {
- for (PropertyDescriptor property : Introspector.getBeanInfo(type).getPropertyDescriptors())
- if (property.getReadMethod() != null && canInitializeProperty(type, property, config))
- properties.add(new MethodProperty(type, property));
- }
for (Field field : getAllFields(type)) {
+ String name = field.getName();
+
+ if (beanProperties) {
+ DeferredConstruction deferredConstruction = getDeferredConstruction(type, config);
+ boolean constructorProperty = deferredConstruction != null && deferredConstruction.hasParameter(name);
+
+ String nameUpper = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ Method getMethod = null, setMethod = null;
+ try {
+ oneArg[0] = field.getType();
+ setMethod = type.getMethod("set" + nameUpper, oneArg);
+ } catch (Exception ignored) {
+ }
+ try {
+ getMethod = type.getMethod("get" + nameUpper, noArgs);
+ } catch (Exception ignored) {
+ }
+ if (getMethod != null && (setMethod != null || constructorProperty)) {
+ properties.add(new MethodProperty(name, setMethod, getMethod));
+ continue;
+ }
+ }
+
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) continue;
if (!Modifier.isPublic(modifiers)) {
@@ -138,27 +144,39 @@ static public Set getProperties (Class type, boolean beanProperties, b
return properties;
}
- static public Property getProperty (Class type, String name, boolean beanProperties, boolean privateFields, YamlConfig config)
- throws IntrospectionException {
+ static public Property getProperty (Class type, String name, boolean beanProperties, boolean privateFields, YamlConfig config) {
if (type == null) throw new IllegalArgumentException("type cannot be null.");
if (name == null || name.length() == 0) throw new IllegalArgumentException("name cannot be null or empty.");
- if (beanProperties) {
- for (PropertyDescriptor property : Introspector.getBeanInfo(type).getPropertyDescriptors()) {
- if (property.getName().equals(name)) {
- if (property.getReadMethod() != null && canInitializeProperty(type, property, config))
- return new MethodProperty(type, property);
- break;
+ Class[] noArgs = new Class[0], oneArg = new Class[1];
+ for (Field field : getAllFields(type)) {
+ if (!field.getName().equals(name)) continue;
+
+ if (beanProperties) {
+ DeferredConstruction deferredConstruction = getDeferredConstruction(type, config);
+ boolean constructorProperty = deferredConstruction != null && deferredConstruction.hasParameter(name);
+
+ String nameUpper = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ Method getMethod = null, setMethod = null;
+ try {
+ oneArg[0] = field.getType();
+ setMethod = type.getMethod("set" + nameUpper, oneArg);
+ } catch (Exception ignored) {
+ }
+ try {
+ getMethod = type.getMethod("get" + nameUpper, noArgs);
+ } catch (Exception ignored) {
}
+ if (getMethod != null && (setMethod != null || constructorProperty))
+ return new MethodProperty(name, setMethod, getMethod);
}
- }
- for (Field field : getAllFields(type)) {
+
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) continue;
if (!Modifier.isPublic(modifiers)) {
if (!privateFields) continue;
field.setAccessible(true);
}
- if (field.getName().equals(name)) return new FieldProperty(field);
+ return new FieldProperty(field);
}
return null;
}
@@ -174,11 +192,12 @@ static private ArrayList getAllFields (Class type) {
}
static public class MethodProperty extends Property {
- private final PropertyDescriptor property;
+ private final Method setMethod, getMethod;
- public MethodProperty (Class declaringClass, PropertyDescriptor property) throws IntrospectionException {
- super(declaringClass, property);
- this.property = property;
+ public MethodProperty (String name, Method setMethod, Method getMethod) {
+ super(getMethod.getDeclaringClass(), name, getMethod.getReturnType());
+ this.setMethod = setMethod;
+ this.getMethod = getMethod;
}
public void set (Object object, Object value) throws Exception {
@@ -186,11 +205,11 @@ public void set (Object object, Object value) throws Exception {
((DeferredConstruction)object).storeProperty(this, value);
return;
}
- property.getWriteMethod().invoke(object, value);
+ setMethod.invoke(object, value);
}
public Object get (Object object) throws Exception {
- return property.getReadMethod().invoke(object);
+ return getMethod.invoke(object);
}
}
@@ -226,21 +245,6 @@ static public abstract class Property implements Comparable {
this.type = type;
}
- Property (Class declaringClass, PropertyDescriptor property) throws IntrospectionException {
- this.declaringClass = declaringClass;
- this.name = property.getName();
- try {
- // The PropertyDescriptor returns the wrong type if the getter is an implementation of a interface method with a
- // generic return value.
- type = property.getReadMethod().getDeclaringClass()
- .getDeclaredMethod(property.getReadMethod().getName(), new Class[0]).getReturnType();
- } catch (Exception ex) {
- IntrospectionException introspectionEx = new IntrospectionException("Error getting ");
- introspectionEx.initCause(ex);
- throw introspectionEx;
- }
- }
-
public int hashCode () {
final int prime = 31;
int result = 1;
diff --git a/src/com/esotericsoftware/yamlbeans/YamlConfig.java b/src/com/esotericsoftware/yamlbeans/YamlConfig.java
index 3a12ef0..1dbffcb 100644
--- a/src/com/esotericsoftware/yamlbeans/YamlConfig.java
+++ b/src/com/esotericsoftware/yamlbeans/YamlConfig.java
@@ -16,12 +16,6 @@
package com.esotericsoftware.yamlbeans;
-import com.esotericsoftware.yamlbeans.Beans.Property;
-import com.esotericsoftware.yamlbeans.emitter.EmitterConfig;
-import com.esotericsoftware.yamlbeans.scalar.DateSerializer;
-import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
-
-import java.beans.IntrospectionException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -31,6 +25,11 @@
import java.util.IdentityHashMap;
import java.util.Map;
+import com.esotericsoftware.yamlbeans.Beans.Property;
+import com.esotericsoftware.yamlbeans.emitter.EmitterConfig;
+import com.esotericsoftware.yamlbeans.scalar.DateSerializer;
+import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
+
/** Stores configuration for reading and writing YAML.
* @author Nathan Sweet */
public class YamlConfig {
@@ -80,20 +79,13 @@ public void setPropertyElementType (Class type, String propertyName, Class eleme
if (type == null) throw new IllegalArgumentException("type cannot be null.");
if (propertyName == null) throw new IllegalArgumentException("propertyName cannot be null.");
if (elementType == null) throw new IllegalArgumentException("propertyType cannot be null.");
- Property property = null;
- Exception cause = null;
- try {
- property = Beans.getProperty(type, propertyName, beanProperties, privateFields, this);
- } catch (IntrospectionException ex) {
- cause = ex;
- }
- if (property == null) {
- throw new IllegalArgumentException("The class " + type.getName() + " does not have a property named: " + propertyName,
- cause);
- }
- if (!Collection.class.isAssignableFrom(property.getType()) && !Map.class.isAssignableFrom(property.getType()))
+ Property property = Beans.getProperty(type, propertyName, beanProperties, privateFields, this);
+ if (property == null)
+ throw new IllegalArgumentException("The class " + type.getName() + " does not have a property named: " + propertyName);
+ if (!Collection.class.isAssignableFrom(property.getType()) && !Map.class.isAssignableFrom(property.getType())) {
throw new IllegalArgumentException("The '" + propertyName + "' property on the " + type.getName()
+ " class must be a Collection or Map: " + property.getType());
+ }
propertyToElementType.put(property, elementType);
}
@@ -103,21 +95,14 @@ public void setPropertyDefaultType (Class type, String propertyName, Class defau
if (type == null) throw new IllegalArgumentException("type cannot be null.");
if (propertyName == null) throw new IllegalArgumentException("propertyName cannot be null.");
if (defaultType == null) throw new IllegalArgumentException("defaultType cannot be null.");
- Property property = null;
- Exception cause = null;
- try {
- property = Beans.getProperty(type, propertyName, beanProperties, privateFields, this);
- } catch (IntrospectionException ex) {
- cause = ex;
- }
- if (property == null) {
- throw new IllegalArgumentException("The class " + type.getName() + " does not have a property named: " + propertyName,
- cause);
- }
+ Property property = Beans.getProperty(type, propertyName, beanProperties, privateFields, this);
+ if (property == null)
+ throw new IllegalArgumentException("The class " + type.getName() + " does not have a property named: " + propertyName);
propertyToDefaultType.put(property, defaultType);
}
- /** If true, bean properties with both a getter and setter will be used. Default is true. */
+ /** If true, bean properties with both a getter and setter will be used. Note the getter and setter methods must be named the
+ * same as the field they get or set. Default is true. */
public void setBeanProperties (boolean beanProperties) {
this.beanProperties = beanProperties;
}
diff --git a/src/com/esotericsoftware/yamlbeans/YamlWriter.java b/src/com/esotericsoftware/yamlbeans/YamlWriter.java
index 6e62de8..665c5a2 100644
--- a/src/com/esotericsoftware/yamlbeans/YamlWriter.java
+++ b/src/com/esotericsoftware/yamlbeans/YamlWriter.java
@@ -16,20 +16,6 @@
package com.esotericsoftware.yamlbeans;
-import com.esotericsoftware.yamlbeans.Beans.Property;
-import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
-import com.esotericsoftware.yamlbeans.emitter.Emitter;
-import com.esotericsoftware.yamlbeans.emitter.EmitterException;
-import com.esotericsoftware.yamlbeans.parser.AliasEvent;
-import com.esotericsoftware.yamlbeans.parser.DocumentEndEvent;
-import com.esotericsoftware.yamlbeans.parser.DocumentStartEvent;
-import com.esotericsoftware.yamlbeans.parser.Event;
-import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
-import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
-import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
-import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
-
-import java.beans.IntrospectionException;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
@@ -44,6 +30,19 @@
import java.util.Map.Entry;
import java.util.Set;
+import com.esotericsoftware.yamlbeans.Beans.Property;
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.AliasEvent;
+import com.esotericsoftware.yamlbeans.parser.DocumentEndEvent;
+import com.esotericsoftware.yamlbeans.parser.DocumentStartEvent;
+import com.esotericsoftware.yamlbeans.parser.Event;
+import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
+import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
+import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
+import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
+
/** Serializes Java objects as YAML.
* @author Nathan Sweet */
public class YamlWriter {
@@ -243,12 +242,7 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
}
}
- Set properties;
- try {
- properties = Beans.getProperties(valueClass, config.beanProperties, config.privateFields, config);
- } catch (IntrospectionException ex) {
- throw new YamlException("Error inspecting class: " + valueClass.getName(), ex);
- }
+ Set properties = Beans.getProperties(valueClass, config.beanProperties, config.privateFields, config);
emitter.emit(new MappingStartEvent(anchor, tag, !showTag, false));
for (Property property : properties) {
try {
@@ -299,14 +293,9 @@ private void countObjectReferences (Object object) throws YamlException {
return;
}
- // Value must be a bean.
+ // Value must be an object.
- Set properties;
- try {
- properties = Beans.getProperties(object.getClass(), config.beanProperties, config.privateFields, config);
- } catch (IntrospectionException ex) {
- throw new YamlException("Error inspecting class: " + object.getClass().getName(), ex);
- }
+ Set properties = Beans.getProperties(object.getClass(), config.beanProperties, config.privateFields, config);
for (Property property : properties) {
if (Beans.isScalar(property.getType())) continue;
Object propertyValue;