Skip to content

Commit c85438b

Browse files
committed
Start work on supporting referential type as 1st class concept (and maybe general handling, in future)
1 parent a782d36 commit c85438b

File tree

10 files changed

+240
-13
lines changed

10 files changed

+240
-13
lines changed

src/main/java/com/fasterxml/jackson/databind/JavaType.java

+3
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ public boolean isConcrete() {
326326
@Override
327327
public JavaType getContentType() { return null; }
328328

329+
@Override // since 2.6
330+
public JavaType getReferencedType() { return null; }
331+
329332
@Override
330333
public int containedTypeCount() { return 0; }
331334

src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
public final class ArrayType
1313
extends TypeBase
1414
{
15-
private static final long serialVersionUID = 9040058063449087477L;
15+
private static final long serialVersionUID = 1L;
1616

1717
/**
1818
* Type of elements in the array.
@@ -25,8 +25,8 @@ public final class ArrayType
2525
* it is essentially immutable and thus can be shared.
2626
*/
2727
protected final Object _emptyArray;
28-
29-
private ArrayType(JavaType componentType, Object emptyInstance,
28+
29+
protected ArrayType(JavaType componentType, Object emptyInstance,
3030
Object valueHandler, Object typeHandler, boolean asStatic)
3131
{
3232
super(emptyInstance.getClass(), componentType.hashCode(),

src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414
public class CollectionLikeType extends TypeBase
1515
{
16-
private static final long serialVersionUID = 4611641304150899138L;
16+
private static final long serialVersionUID = 1L;
1717

1818
/**
1919
* Type of elements in collection

src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
public final class CollectionType
99
extends CollectionLikeType
1010
{
11-
private static final long serialVersionUID = -7834910259750909424L;
11+
private static final long serialVersionUID = 1L;
1212

1313
/*
1414
/**********************************************************

src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*/
1515
public class MapLikeType extends TypeBase
1616
{
17-
private static final long serialVersionUID = 416067702302823522L;
17+
private static final long serialVersionUID = 1L;
1818

1919
/**
2020
* Type of keys of Map.

src/main/java/com/fasterxml/jackson/databind/type/MapType.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
public final class MapType extends MapLikeType
99
{
10-
private static final long serialVersionUID = -811146779148281500L;
10+
private static final long serialVersionUID = 1L;
1111

1212
/*
1313
/**********************************************************
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package com.fasterxml.jackson.databind.type;
2+
3+
import com.fasterxml.jackson.databind.JavaType;
4+
5+
/**
6+
* Specialized {@link SimpleType} for types that are referential types,
7+
* that is, values that can be dereferenced to another value (or null),
8+
* of different type.
9+
* Referenced type is accessible using {@link #getContentType()}.
10+
*
11+
* @since 2.6
12+
*/
13+
public class ReferenceType extends SimpleType
14+
{
15+
private static final long serialVersionUID = 1L;
16+
17+
protected final JavaType _referencedType;
18+
19+
protected ReferenceType(Class<?> cls, JavaType refType,
20+
Object valueHandler, Object typeHandler, boolean asStatic)
21+
{
22+
super(cls, refType.hashCode(),
23+
valueHandler, typeHandler, asStatic);
24+
_referencedType = refType;
25+
}
26+
27+
public static ReferenceType construct(Class<?> cls, JavaType refType,
28+
Object valueHandler, Object typeHandler)
29+
{
30+
return new ReferenceType(cls, refType, null, null, false);
31+
}
32+
33+
@Override
34+
public ReferenceType withTypeHandler(Object h)
35+
{
36+
if (h == _typeHandler) {
37+
return this;
38+
}
39+
return new ReferenceType(_class, _referencedType, _valueHandler, h, _asStatic);
40+
}
41+
42+
@Override
43+
public ReferenceType withContentTypeHandler(Object h)
44+
{
45+
if (h == _referencedType.<Object>getTypeHandler()) {
46+
return this;
47+
}
48+
return new ReferenceType(_class, _referencedType.withTypeHandler(h),
49+
_valueHandler, _typeHandler, _asStatic);
50+
}
51+
52+
@Override
53+
public ReferenceType withValueHandler(Object h) {
54+
if (h == _valueHandler) {
55+
return this;
56+
}
57+
return new ReferenceType(_class, _referencedType, h, _typeHandler,_asStatic);
58+
}
59+
60+
@Override
61+
public ReferenceType withContentValueHandler(Object h) {
62+
if (h == _referencedType.<Object>getValueHandler()) {
63+
return this;
64+
}
65+
return new ReferenceType(_class, _referencedType.withValueHandler(h),
66+
_valueHandler, _typeHandler, _asStatic);
67+
}
68+
69+
@Override
70+
public ReferenceType withStaticTyping() {
71+
if (_asStatic) {
72+
return this;
73+
}
74+
return new ReferenceType(_class, _referencedType.withStaticTyping(),
75+
_valueHandler, _typeHandler, true);
76+
}
77+
78+
@Override
79+
protected String buildCanonicalName()
80+
{
81+
StringBuilder sb = new StringBuilder();
82+
sb.append(_class.getName());
83+
sb.append('<');
84+
sb.append(_referencedType.toCanonical());
85+
return sb.toString();
86+
}
87+
88+
/*
89+
/**********************************************************
90+
/* Narrow/widen
91+
/**********************************************************
92+
*/
93+
94+
@Override
95+
protected JavaType _narrow(Class<?> subclass)
96+
{
97+
// Should we check that there is a sub-class relationship?
98+
return new ReferenceType(subclass, _referencedType,
99+
_valueHandler, _typeHandler, _asStatic);
100+
}
101+
102+
/*
103+
/**********************************************************
104+
/* Extended API
105+
/**********************************************************
106+
*/
107+
108+
@Override
109+
public JavaType getReferencedType() {
110+
return _referencedType;
111+
}
112+
113+
@Override
114+
public boolean isReferenceType() {
115+
return true;
116+
}
117+
118+
/*
119+
/**********************************************************
120+
/* Public API overrides
121+
/**********************************************************
122+
*/
123+
124+
@Override
125+
public int containedTypeCount() {
126+
return 1;
127+
}
128+
129+
@Override
130+
public JavaType containedType(int index) {
131+
return (index == 0) ? _referencedType : null;
132+
}
133+
134+
@Override
135+
public String containedTypeName(int index) {
136+
return (index == 0) ? "T" : null;
137+
}
138+
139+
@Override
140+
public Class<?> getParameterSource() {
141+
// Hmmh. For now, assume it's the raw type
142+
return _class;
143+
}
144+
145+
@Override
146+
public StringBuilder getErasedSignature(StringBuilder sb) {
147+
return _classSignature(_class, sb, true);
148+
}
149+
150+
@Override
151+
public StringBuilder getGenericSignature(StringBuilder sb)
152+
{
153+
_classSignature(_class, sb, false);
154+
sb.append('<');
155+
sb = _referencedType.getGenericSignature(sb);
156+
sb.append(';');
157+
return sb;
158+
}
159+
160+
/*
161+
/**********************************************************
162+
/* Standard methods
163+
/**********************************************************
164+
*/
165+
166+
@Override
167+
public String toString()
168+
{
169+
return new StringBuilder(40)
170+
.append("[reference type, class ")
171+
.append(buildCanonicalName())
172+
.append('<')
173+
.append(_referencedType)
174+
.append('>')
175+
.append(']')
176+
.toString();
177+
}
178+
179+
@Override
180+
public boolean equals(Object o)
181+
{
182+
if (o == this) return true;
183+
if (o == null) return false;
184+
if (o.getClass() != getClass()) return false;
185+
186+
ReferenceType other = (ReferenceType) o;
187+
188+
// Otherwise actually mostly worry about referenced type
189+
return _referencedType.equals(other._referencedType);
190+
}
191+
}

src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java

+17-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
* need not know anything further, since we have no way of dealing
1111
* with generic types other than Collections and Maps.
1212
*/
13-
public final class SimpleType
13+
public class SimpleType // note: until 2.6 was final
1414
extends TypeBase
1515
{
16-
private static final long serialVersionUID = -800374828948534376L;
16+
private static final long serialVersionUID = 1L;
1717

1818
/**
1919
* In case there are resolved type parameters, this field stores reference
@@ -76,6 +76,20 @@ protected SimpleType(Class<?> cls,
7676
_typeParametersFor = parametersFrom;
7777
}
7878

79+
/**
80+
* Pass-through constructor used by {@link ReferencedType}
81+
*
82+
* @since 2.6
83+
*/
84+
protected SimpleType(Class<?> cls, int extraHash,
85+
Object valueHandler, Object typeHandler, boolean asStatic)
86+
{
87+
super(cls, extraHash, valueHandler, typeHandler, asStatic);
88+
_typeNames = null;
89+
_typeParameters = null;
90+
_typeParametersFor = cls;
91+
}
92+
7993
/**
8094
* Method used by core Jackson classes: NOT to be used by application code.
8195
*<p>
@@ -235,7 +249,7 @@ public StringBuilder getGenericSignature(StringBuilder sb)
235249
sb.append(';');
236250
return sb;
237251
}
238-
252+
239253
/*
240254
/**********************************************************
241255
/* Standard methods

src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.fasterxml.jackson.databind.type;
22

33
import java.util.*;
4+
import java.util.concurrent.atomic.AtomicReference;
45
import java.lang.reflect.*;
56

67
import com.fasterxml.jackson.core.type.TypeReference;
@@ -531,7 +532,10 @@ public MapLikeType constructMapLikeType(Class<?> mapClass, Class<?> keyClass, Cl
531532
public JavaType constructSimpleType(Class<?> rawType, JavaType[] parameterTypes) {
532533
return constructSimpleType(rawType, rawType, parameterTypes);
533534
}
534-
535+
536+
/**
537+
* Method for constructing a type instance with specified parameterization.
538+
*/
535539
public JavaType constructSimpleType(Class<?> rawType, Class<?> parameterTarget,
536540
JavaType[] parameterTypes)
537541
{
@@ -549,6 +553,14 @@ public JavaType constructSimpleType(Class<?> rawType, Class<?> parameterTarget,
549553
return new SimpleType(rawType, names, parameterTypes, null, null, false, parameterTarget);
550554
}
551555

556+
/**
557+
* @since 2.6
558+
*/
559+
public JavaType constructReferenceType(Class<?> rawType, JavaType refType)
560+
{
561+
return new ReferenceType(rawType, refType, null, null, false);
562+
}
563+
552564
/**
553565
* Method that will force construction of a simple type, without trying to
554566
* check for more specialized types.
@@ -791,9 +803,15 @@ protected JavaType _fromClass(Class<?> clz, TypeBindings context)
791803
} else if (Collection.class.isAssignableFrom(clz)) {
792804
result = _collectionType(clz);
793805
} else {
806+
// 28-Apr-2015, tatu: New class of types, referential...
807+
if (AtomicReference.class.isAssignableFrom(clz)) {
808+
JavaType[] pts = findTypeParameters(clz, AtomicReference.class);
809+
JavaType rt = (pts == null || pts.length != 1) ? unknownType() : pts[0];
810+
result = constructReferenceType(clz, rt);
811+
794812
// 29-Sep-2014, tatu: We may want to pre-resolve well-known generic types
795-
if (Map.Entry.class.isAssignableFrom(clz)) {
796-
JavaType[] pts = this.findTypeParameters(clz, Map.Entry.class);
813+
} else if (Map.Entry.class.isAssignableFrom(clz)) {
814+
JavaType[] pts = findTypeParameters(clz, Map.Entry.class);
797815
JavaType kt, vt;
798816
if (pts == null || pts.length != 2) {
799817
kt = vt = unknownType();

src/test/java/com/fasterxml/jackson/databind/convert/TestUpdateValue.java

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static class DataADeserializer extends StdDeserializer<DataA> {
6767
super(DataA.class);
6868
}
6969

70+
@Override
7071
public DataA deserialize(JsonParser jp, DeserializationContext ctxt)
7172
throws JsonProcessingException, IOException {
7273
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {

0 commit comments

Comments
 (0)