Add a unit test for JACKSON-890
diff --git a/src/test/org/codehaus/jackson/map/jsontype/TestBackRefsWithPolymorphic.java b/src/test/org/codehaus/jackson/map/jsontype/TestBackRefsWithPolymorphic.java
new file mode 100644
index 0000000..b38401b
--- /dev/null
+++ b/src/test/org/codehaus/jackson/map/jsontype/TestBackRefsWithPolymorphic.java
@@ -0,0 +1,301 @@
+package org.codehaus.jackson.map.jsontype;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.codehaus.jackson.annotate.JsonBackReference;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonManagedReference;
+import org.codehaus.jackson.annotate.JsonTypeInfo;
+import org.codehaus.jackson.map.BaseMapTest;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.annotate.JsonDeserialize;
+
+import static org.codehaus.jackson.annotate.JsonTypeInfo.As.PROPERTY;
+import static org.codehaus.jackson.annotate.JsonTypeInfo.Id.CLASS;
+
+// Unit test for [JACKSON-890]
+public class TestBackRefsWithPolymorphic extends BaseMapTest
+{
+ private final String CLASS_NAME = getClass().getName();
+
+ private final String JSON =
+ "{\"@class\":\""+CLASS_NAME+"$PropertySheetImpl\",\"properties\":{\"p1name\":{\"@class\":"
+ +"\"" +CLASS_NAME+ "$StringPropertyImpl\",\"value\":\"p1value\",\"name\":\"p1name\",\"id\":0},"
+ +"\"p2name\":{\"@class\":\""+CLASS_NAME+"$StringPropertyImpl\",\"value\":\"p2value\","
+ +"\"name\":\"p2name\",\"id\":0}},\"id\":0}";
+
+ private final ObjectMapper MAPPER = new ObjectMapper();
+
+ public void testDeserialize() throws IOException
+ {
+ PropertySheet input = MAPPER.readValue(JSON, PropertySheet.class);
+ assertEquals(JSON, MAPPER.writeValueAsString(input));
+ }
+
+ public void testSerialize() throws IOException
+ {
+ PropertySheet sheet = new PropertySheetImpl();
+
+ sheet.addProperty(new StringPropertyImpl("p1name", "p1value"));
+ sheet.addProperty(new StringPropertyImpl("p2name", "p2value"));
+ assertEquals(JSON, MAPPER.writeValueAsString(sheet));
+ }
+
+ interface Entity
+ {
+
+ //~ Methods ------------------------------------------------------------
+
+ @JsonIgnore String getEntityType();
+
+ Long getId();
+
+ void setId(Long id);
+
+ @JsonIgnore void setPersistable();
+ }
+
+ @JsonDeserialize(as = NestedPropertySheetImpl.class)
+ interface NestedPropertySheet
+ extends Property<PropertySheet>
+ {
+ @Override
+ PropertySheet getValue();
+
+ void setValue(PropertySheet propertySheet);
+ }
+
+ @JsonDeserialize(as = AbstractProperty.class)
+ @JsonTypeInfo(
+ use = CLASS,
+ include = PROPERTY,
+ property = "@class"
+ )
+ interface Property<T>
+ extends Entity
+ {
+
+ //~ Methods ------------------------------------------------------------
+
+ String getName();
+
+ PropertySheet getParentSheet();
+
+ T getValue();
+
+ void setName(String name);
+
+ void setParentSheet(PropertySheet parentSheet);
+ }
+
+ @JsonDeserialize(as = PropertySheetImpl.class)
+ @JsonTypeInfo(
+ use = CLASS,
+ include = PROPERTY,
+ property = "@class"
+ )
+ @SuppressWarnings("rawtypes")
+ interface PropertySheet extends Entity
+ {
+
+ //~ Methods ------------------------------------------------------------
+
+ void addProperty(Property property);
+
+ Map<String, Property> getProperties();
+
+ void setProperties(Map<String, Property> properties);
+ }
+
+ @JsonDeserialize(as = StringPropertyImpl.class)
+ interface StringProperty
+ extends Property<String>
+ {
+ @Override String getValue();
+ void setValue(String value);
+ }
+
+ //~ Inner Classes ----------------------------------------------------------
+
+ static class AbstractEntity
+ implements Entity
+ {
+
+ //~ Instance fields ----------------------------------------------------
+
+ private long m_id;
+
+ //~ Methods ------------------------------------------------------------
+
+ @Override public String getEntityType()
+ {
+ return "";
+ }
+
+ @Override public Long getId()
+ {
+ return m_id;
+ }
+
+ @Override public void setId(Long id)
+ {
+ m_id = id;
+ }
+
+ @Override public void setPersistable() { }
+ }
+
+ abstract static class AbstractProperty<T>
+ extends AbstractEntity
+ implements Property<T>
+ {
+
+ //~ Instance fields ----------------------------------------------------
+
+ private String m_name;
+ private PropertySheet m_parentSheet;
+
+ //~ Constructors -------------------------------------------------------
+
+ protected AbstractProperty() { }
+
+ protected AbstractProperty(String name)
+ {
+ m_name = name;
+ }
+
+ //~ Methods ------------------------------------------------------------
+
+ @Override public String getName()
+ {
+ return m_name;
+ }
+
+ @JsonBackReference("propertySheet-properties")
+ @Override public PropertySheet getParentSheet()
+ {
+ return m_parentSheet;
+ }
+
+ @Override public void setName(String name) {
+ m_name = name;
+ }
+
+ @Override public void setParentSheet(PropertySheet parentSheet) {
+ m_parentSheet = parentSheet;
+ }
+ }
+
+ static class NestedPropertySheetImpl
+ extends AbstractProperty<PropertySheet>
+ implements NestedPropertySheet
+ {
+
+ //~ Instance fields ----------------------------------------------------
+
+ private PropertySheet m_propertySheet;
+
+ //~ Constructors -------------------------------------------------------
+
+ protected NestedPropertySheetImpl(
+ String name,
+ PropertySheet propertySheet)
+ {
+ super(name);
+ m_propertySheet = propertySheet;
+ }
+
+ NestedPropertySheetImpl() { }
+
+ //~ Methods ------------------------------------------------------------
+
+ @Override public PropertySheet getValue()
+ {
+ return m_propertySheet;
+ }
+
+ @Override public void setValue(PropertySheet propertySheet)
+ {
+ m_propertySheet = propertySheet;
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ static class PropertySheetImpl
+ extends AbstractEntity
+ implements PropertySheet
+ {
+
+ //~ Instance fields ----------------------------------------------------
+
+ private Map<String, Property> m_properties;
+
+ //~ Methods ------------------------------------------------------------
+
+ @Override public void addProperty(Property property)
+ {
+
+ if (m_properties == null) {
+ m_properties = new TreeMap<String, Property>();
+ }
+
+ property.setParentSheet(this);
+ m_properties.put(property.getName(), property);
+ }
+
+ @JsonDeserialize(
+ as = TreeMap.class,
+ keyAs = String.class,
+ contentAs = Property.class
+ )
+ @JsonManagedReference("propertySheet-properties")
+ @Override public Map<String, Property> getProperties()
+ {
+ return m_properties;
+ }
+
+ @Override public void setProperties(Map<String, Property> properties)
+ {
+ m_properties = properties;
+ }
+ }
+
+ static class StringPropertyImpl
+ extends AbstractProperty<String>
+ implements StringProperty
+ {
+
+ //~ Instance fields ----------------------------------------------------
+
+ private String m_value;
+
+ //~ Constructors -------------------------------------------------------
+
+ public StringPropertyImpl(
+ String name,
+ String value)
+ {
+ super(name);
+ m_value = value;
+ }
+
+ StringPropertyImpl() { }
+
+ //~ Methods ------------------------------------------------------------
+
+ @Override public String getValue()
+ {
+ return m_value;
+ }
+
+ @Override public void setValue(String value)
+ {
+ m_value = value;
+ }
+ }
+
+ static class YetAnotherClass
+ extends StringPropertyImpl { }
+}