Starting to work on resolving more of non-conflicting getters
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
index f36e420..0326d3a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java
@@ -2,10 +2,7 @@
import java.util.*;
-import com.fasterxml.jackson.databind.AnnotationIntrospector;
-import com.fasterxml.jackson.databind.PropertyMetadata;
-import com.fasterxml.jackson.databind.PropertyName;
-import com.fasterxml.jackson.databind.util.BeanUtil;
+import com.fasterxml.jackson.databind.*;
/**
* Helper class used for aggregating information about a single
@@ -213,49 +210,72 @@
@Override
public AnnotatedMethod getGetter()
{
- if (_getters == null) {
+ Linked<AnnotatedMethod> curr = _getters;
+ // If zero easy
+ if (curr == null) {
return null;
}
- // If multiple, verify that they do not conflict...
- AnnotatedMethod getter = _getters.value;
- Linked<AnnotatedMethod> next = _getters.next;
+ Linked<AnnotatedMethod> next = curr.next;
+ // ditto, if one
+ if (next == null) {
+ return curr.value;
+ }
+
+ // But if multiple, verify that they do not conflict...
for (; next != null; next = next.next) {
- /* [JACKSON-255] Allow masking, i.e. report exception only if
- * declarations in same class, or there's no inheritance relationship
- * (sibling interfaces etc)
+
+ /* [JACKSON-255] Allow masking, i.e. do not report exception if one
+ * is in super-class from the other
*/
- AnnotatedMethod nextGetter = next.value;
- Class<?> getterClass = getter.getDeclaringClass();
- Class<?> nextClass = nextGetter.getDeclaringClass();
+ Class<?> getterClass = curr.value.getDeclaringClass();
+ Class<?> nextClass = next.value.getDeclaringClass();
if (getterClass != nextClass) {
if (getterClass.isAssignableFrom(nextClass)) { // next is more specific
- getter = nextGetter;
+ curr = next;
continue;
}
- if (nextClass.isAssignableFrom(getterClass)) { // getter more specific
+ if (nextClass.isAssignableFrom(getterClass)) { // current more specific
continue;
}
}
- /* [Issue#238]: Also, regular getters have precedence over "is-getters", so
- * latter can be skipped to resolve otherwise conflict.
- * This is bit ugly as we have to re-process naming (as determination of type
- * is not retained), but should work.
+ /* 30-May-2014, tatu: Three levels of precedence:
+ *
+ * 1. Regular getters ("getX")
+ * 2. Is-getters ("isX")
+ * 3. Implicit, possible getters ("x")
*/
- boolean thisIsGetter = BeanUtil.okNameForIsGetter(getter, getter.getName()) != null;
- boolean nextIsGetter = BeanUtil.okNameForIsGetter(nextGetter, nextGetter.getName()) != null;
-
- if (thisIsGetter != nextIsGetter) {
- if (thisIsGetter) {
- getter = nextGetter;
- }
+ int priNext = _getterPriority(next.value);
+ int priCurr = _getterPriority(curr.value);
+
+ if (priNext != priCurr) {
+ if (priNext < priCurr) {
+ curr = next;
+ }
continue;
}
throw new IllegalArgumentException("Conflicting getter definitions for property \""+getName()+"\": "
- +getter.getFullName()+" vs "+nextGetter.getFullName());
+ +curr.value.getFullName()+" vs "+next.value.getFullName());
}
- return getter;
+
+ // One more thing; to avoid having to do it again...
+ _getters = curr.withoutNext();
+ return curr.value;
}
+ protected int _getterPriority(AnnotatedMethod m)
+ {
+ final String name = m.getName();
+ // [#238]: Also, regular getters have precedence over "is-getters"
+ if (name.startsWith("get") && name.length() > 3) {
+ // should we check capitalization?
+ return 1;
+ }
+ if (name.startsWith("is") && name.length() > 2) {
+ return 2;
+ }
+ return 3;
+ }
+
@Override
public AnnotatedMethod getSetter()
{
@@ -971,6 +991,13 @@
isMarkedIgnored = ignored;
}
+ public Linked<T> withoutNext() {
+ if (next == null) {
+ return this;
+ }
+ return new Linked<T>(value, null, name, isNameExplicit, isVisible, isMarkedIgnored);
+ }
+
public Linked<T> withValue(T newValue) {
if (newValue == value) {
return this;
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdJdkSerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdJdkSerializers.java
index 1080ce8..76ea407 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdJdkSerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdJdkSerializers.java
@@ -52,7 +52,7 @@
sers.put(Class.class, ClassSerializer.class);
// And then some stranger types... not 100% they are needed but:
- sers.put(Void.TYPE, NullSerializer.class);
+ sers.put(Void.TYPE, NullSerializer.instance);
return sers.entrySet();
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java b/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java
index e8fbbc6..d512cb6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java
@@ -82,9 +82,9 @@
public static String okNameForMutator(AnnotatedMethod am, String prefix)
{
- String name = am.getName();
+ String name = am.getName();
if (name.startsWith(prefix)) {
- return manglePropertyName(name.substring(prefix.length()));
+ return manglePropertyName(name.substring(prefix.length()));
}
return null;
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
index 5a6ca22..5cd7d90 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
@@ -54,10 +54,10 @@
public String _name() { return "foo"; }
public String getName() { return "Bob"; }
- public void setStuff() { ; // ok
+ public void setStuff(String value) { ; // ok
}
- public void _stuff() {
+ public void _stuff(String value) {
throw new UnsupportedOperationException();
}
}