package com.fasterxml.jackson.databind.objectid;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
public class TestObjectIdWithPolymorphic extends BaseMapTest
{
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id")
static abstract class Base
{
public int value;
public Base next;
public Base() { this(0); }
public Base(int v) {
value = v;
}
}
static class Impl extends Base
{
public int extra;
public Impl() { this(0, 0); }
public Impl(int v, int e) {
super(v);
extra = e;
}
}
// [JACKSON-811] types
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public static class Base811 {
public int id;
public Base811 owner;
protected Base811() {}
public Base811(Process owner) {
this.owner = owner;
if (owner == null) {
id = 0;
} else {
id = ++owner.childIdCounter;
owner.children.add(this);
}
}
}
public static class Process extends Base811 {
protected int childIdCounter = 0;
protected List<Base811> children = new ArrayList<Base811>();
public Process() { super(null); }
}
public static abstract class Activity extends Base811 {
protected Activity parent;
public Activity(Process owner, Activity parent) {
super(owner);
this.parent = parent;
}
protected Activity() {
super();
}
}
public static class Scope extends Activity {
public final List<FaultHandler> faultHandlers = new ArrayList<FaultHandler>();
public Scope(Process owner, Activity parent) {
super(owner, parent);
}
protected Scope() {
super();
}
}
public static class FaultHandler extends Base811 {
public final List<Catch> catchBlocks = new ArrayList<Catch>();
public FaultHandler(Process owner) {
super(owner);
}
protected FaultHandler() {}
}
public static class Catch extends Scope {
public Catch(Process owner, Activity parent) {
super(owner, parent);
}
protected Catch() {};
}
/*
/*****************************************************
/* Unit tests for polymorphic type handling
/*****************************************************
*/
private final ObjectMapper mapper = new ObjectMapper();
public void testPolymorphicRoundtrip() throws Exception
{
// create simple 2 node loop:
Impl in1 = new Impl(123, 456);
in1.next = new Impl(111, 222);
in1.next.next = in1;
String json = mapper.writeValueAsString(in1);
// then bring back...
Base result0 = mapper.readValue(json, Base.class);
assertNotNull(result0);
assertSame(Impl.class, result0.getClass());
Impl result = (Impl) result0;
assertEquals(123, result.value);
assertEquals(456, result.extra);
Impl result2 = (Impl) result.next;
assertEquals(111, result2.value);
assertEquals(222, result2.extra);
assertSame(result, result2.next);
}
public void testIssue811() throws Exception
{
ObjectMapper om = new ObjectMapper();
om.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
om.enable(SerializationFeature.INDENT_OUTPUT);
om.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, "@class");
Process p = new Process();
Scope s = new Scope(p, null);
FaultHandler fh = new FaultHandler(p);
Catch c = new Catch(p, s);
fh.catchBlocks.add(c);
s.faultHandlers.add(fh);
String json = om.writeValueAsString(p);
Process restored = om.readValue(json, Process.class);
assertNotNull(restored);
assertEquals(0, p.id);
assertEquals(3, p.children.size());
assertSame(p, p.children.get(0).owner);
assertSame(p, p.children.get(1).owner);
assertSame(p, p.children.get(2).owner);
}
}