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 { }
+}