Skip to content

Commit 3018f40

Browse files
committed
scala 2.11/2.12 compile issues
1 parent 3d8555d commit 3018f40

File tree

3 files changed

+293
-1
lines changed

3 files changed

+293
-1
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package com.fasterxml.jackson.module.scala.deser
2+
3+
import java.util
4+
import com.fasterxml.jackson.core.JsonParser
5+
import com.fasterxml.jackson.databind._
6+
import com.fasterxml.jackson.databind.`type`.CollectionLikeType
7+
import com.fasterxml.jackson.databind.deser.std.{CollectionDeserializer, ContainerDeserializerBase, StdValueInstantiator}
8+
import com.fasterxml.jackson.databind.deser.{ContextualDeserializer, Deserializers, ValueInstantiator}
9+
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer
10+
11+
import scala.collection.mutable
12+
import scala.collection.mutable.ListBuffer
13+
import scala.language.higherKinds
14+
15+
abstract class GenericFactoryDeserializerResolver[CC[_], CF[X[_]]] extends Deserializers.Base {
16+
type Collection[A] = CC[A]
17+
type Factory = CF[CC]
18+
type Builder[A] = mutable.Builder[A, _ <: Collection[A]]
19+
20+
// Subclasses need to implement the following:
21+
val CLASS_DOMAIN: Class[_]
22+
val factories: Iterable[(Class[_], Factory)]
23+
def builderFor[A](cf: Factory, valueType: JavaType): Builder[A]
24+
25+
def builderFor[A](cls: Class[_], valueType: JavaType): Builder[A] = factories
26+
.find(_._1.isAssignableFrom(cls))
27+
.map(_._2)
28+
.map(builderFor[A](_, valueType))
29+
.getOrElse(throw new IllegalStateException(s"Could not find deserializer for ${cls.getCanonicalName}. File issue on github:fasterxml/jackson-scala-module."))
30+
31+
override def findCollectionLikeDeserializer(collectionType: CollectionLikeType,
32+
config: DeserializationConfig,
33+
beanDesc: BeanDescription,
34+
elementTypeDeserializer: TypeDeserializer,
35+
elementDeserializer: JsonDeserializer[_]): JsonDeserializer[_] = {
36+
if (!CLASS_DOMAIN.isAssignableFrom(collectionType.getRawClass)) None.orNull
37+
else {
38+
val deser = elementDeserializer.asInstanceOf[JsonDeserializer[AnyRef]]
39+
val instantiator = new Instantiator(config, collectionType, collectionType.getContentType)
40+
new Deserializer(collectionType, deser, elementTypeDeserializer, instantiator)
41+
}
42+
}
43+
44+
protected def sortFactories(factories: IndexedSeq[(Class[_], Factory)]): Seq[(Class[_], Factory)] = {
45+
val cs = factories.toArray
46+
val output = new ListBuffer[(Class[_], Factory)]()
47+
48+
val remaining = cs.map(_ => 1)
49+
val adjMatrix = Array.ofDim[Int](cs.length, cs.length)
50+
51+
// Build the adjacency matrix. Only mark the in-edges.
52+
for (i <- cs.indices; j <- cs.indices) {
53+
val (ic, _) = cs(i)
54+
val (jc, _) = cs(j)
55+
56+
if (i != j && ic.isAssignableFrom(jc)) {
57+
adjMatrix(i)(j) = 1
58+
}
59+
}
60+
61+
// While we haven't removed every node, remove all nodes with 0 degree in-edges.
62+
while (output.length < cs.length) {
63+
val startLength = output.length
64+
65+
for (i <- cs.indices) {
66+
if (remaining(i) == 1 && dotProduct(adjMatrix(i), remaining) == 0) {
67+
output += factories(i)
68+
remaining(i) = 0
69+
}
70+
}
71+
72+
// If we couldn't remove any nodes, it means we've found a cycle. Realistically this should never happen.
73+
if (output.length == startLength) {
74+
throw new IllegalStateException("Companions contain a cycle.")
75+
}
76+
}
77+
78+
output.toSeq
79+
}
80+
81+
private def dotProduct(a: Array[Int], b: Array[Int]): Int = {
82+
if (a.length != b.length) throw new IllegalArgumentException()
83+
84+
a.indices.map(i => a(i) * b(i)).sum
85+
}
86+
87+
private class BuilderWrapper[A](val builder: Builder[A]) extends util.AbstractCollection[A] {
88+
var size = 0
89+
90+
override def add(e: A): Boolean = { builder += e; size += 1; true }
91+
92+
// Required by AbstractCollection, but not implemented
93+
override def iterator(): util.Iterator[A] = None.orNull
94+
95+
def setInitialValue(init: Collection[A]): Unit = init.asInstanceOf[Iterable[A]].foreach(add)
96+
}
97+
98+
private class Instantiator(config: DeserializationConfig, collectionType: JavaType, valueType: JavaType)
99+
extends StdValueInstantiator(config, collectionType) {
100+
101+
override def canCreateUsingDefault = true
102+
103+
override def createUsingDefault(ctxt: DeserializationContext) =
104+
new BuilderWrapper[AnyRef](builderFor[AnyRef](collectionType.getRawClass, valueType))
105+
}
106+
107+
private class Deserializer[A](collectionType: JavaType, containerDeserializer: CollectionDeserializer)
108+
extends ContainerDeserializerBase[CC[A]](collectionType)
109+
with ContextualDeserializer {
110+
111+
def this(collectionType: JavaType, valueDeser: JsonDeserializer[Object], valueTypeDeser: TypeDeserializer, valueInstantiator: ValueInstantiator) = {
112+
this(collectionType, new CollectionDeserializer(collectionType, valueDeser, valueTypeDeser, valueInstantiator))
113+
}
114+
115+
override def createContextual(ctxt: DeserializationContext, property: BeanProperty): Deserializer[A] = {
116+
val newDelegate = containerDeserializer.createContextual(ctxt, property)
117+
new Deserializer(collectionType, newDelegate)
118+
}
119+
120+
override def getContentType: JavaType = containerDeserializer.getContentType
121+
122+
override def getContentDeserializer: JsonDeserializer[AnyRef] = containerDeserializer.getContentDeserializer
123+
124+
override def deserialize(jp: JsonParser, ctxt: DeserializationContext): CC[A] = {
125+
containerDeserializer.deserialize(jp, ctxt) match {
126+
case wrapper: BuilderWrapper[_] => wrapper.builder.result().asInstanceOf[CC[A]]
127+
}
128+
}
129+
130+
override def deserialize(jp: JsonParser, ctxt: DeserializationContext, intoValue: CC[A]): CC[A] = {
131+
val bw = newBuilderWrapper(ctxt)
132+
bw.setInitialValue(intoValue.asInstanceOf[CC[AnyRef]])
133+
containerDeserializer.deserialize(jp, ctxt, bw) match {
134+
case wrapper: BuilderWrapper[_] => wrapper.builder.result().asInstanceOf[CC[A]]
135+
}
136+
}
137+
138+
override def getEmptyValue(ctxt: DeserializationContext): Object = {
139+
val bw = newBuilderWrapper(ctxt)
140+
bw.builder.result().asInstanceOf[Object]
141+
}
142+
143+
private def newBuilderWrapper(ctxt: DeserializationContext): BuilderWrapper[AnyRef] = {
144+
containerDeserializer.getValueInstantiator.createUsingDefault(ctxt).asInstanceOf[BuilderWrapper[AnyRef]]
145+
}
146+
}
147+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package com.fasterxml.jackson.module.scala.deser
2+
3+
import java.util
4+
import com.fasterxml.jackson.core.JsonParser
5+
import com.fasterxml.jackson.databind._
6+
import com.fasterxml.jackson.databind.`type`.CollectionLikeType
7+
import com.fasterxml.jackson.databind.deser.std.{CollectionDeserializer, ContainerDeserializerBase, StdValueInstantiator}
8+
import com.fasterxml.jackson.databind.deser.{ContextualDeserializer, Deserializers, ValueInstantiator}
9+
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer
10+
11+
import scala.collection.mutable
12+
import scala.collection.mutable.ListBuffer
13+
14+
abstract class GenericFactoryDeserializerResolver[CC[_], CF[X[_]]] extends Deserializers.Base {
15+
type Collection[A] = CC[A]
16+
type Factory = CF[CC]
17+
type Builder[A] = mutable.Builder[A, _ <: Collection[A]]
18+
19+
// Subclasses need to implement the following:
20+
val CLASS_DOMAIN: Class[_]
21+
val factories: Iterable[(Class[_], Factory)]
22+
def builderFor[A](cf: Factory, valueType: JavaType): Builder[A]
23+
24+
def builderFor[A](cls: Class[_], valueType: JavaType): Builder[A] = factories
25+
.find(_._1.isAssignableFrom(cls))
26+
.map(_._2)
27+
.map(builderFor[A](_, valueType))
28+
.getOrElse(throw new IllegalStateException(s"Could not find deserializer for ${cls.getCanonicalName}. File issue on github:fasterxml/jackson-scala-module."))
29+
30+
override def findCollectionLikeDeserializer(collectionType: CollectionLikeType,
31+
config: DeserializationConfig,
32+
beanDesc: BeanDescription,
33+
elementTypeDeserializer: TypeDeserializer,
34+
elementDeserializer: JsonDeserializer[_]): JsonDeserializer[_] = {
35+
if (!CLASS_DOMAIN.isAssignableFrom(collectionType.getRawClass)) None.orNull
36+
else {
37+
val deser = elementDeserializer.asInstanceOf[JsonDeserializer[AnyRef]]
38+
val instantiator = new Instantiator(config, collectionType, collectionType.getContentType)
39+
new Deserializer(collectionType, deser, elementTypeDeserializer, instantiator)
40+
}
41+
}
42+
43+
protected def sortFactories(factories: IndexedSeq[(Class[_], Factory)]): Seq[(Class[_], Factory)] = {
44+
val cs = factories.toArray
45+
val output = new ListBuffer[(Class[_], Factory)]()
46+
47+
val remaining = cs.map(_ => 1)
48+
val adjMatrix = Array.ofDim[Int](cs.length, cs.length)
49+
50+
// Build the adjacency matrix. Only mark the in-edges.
51+
for (i <- cs.indices; j <- cs.indices) {
52+
val (ic, _) = cs(i)
53+
val (jc, _) = cs(j)
54+
55+
if (i != j && ic.isAssignableFrom(jc)) {
56+
adjMatrix(i)(j) = 1
57+
}
58+
}
59+
60+
// While we haven't removed every node, remove all nodes with 0 degree in-edges.
61+
while (output.length < cs.length) {
62+
val startLength = output.length
63+
64+
for (i <- cs.indices) {
65+
if (remaining(i) == 1 && dotProduct(adjMatrix(i), remaining) == 0) {
66+
output += factories(i)
67+
remaining(i) = 0
68+
}
69+
}
70+
71+
// If we couldn't remove any nodes, it means we've found a cycle. Realistically this should never happen.
72+
if (output.length == startLength) {
73+
throw new IllegalStateException("Companions contain a cycle.")
74+
}
75+
}
76+
77+
output.toSeq
78+
}
79+
80+
private def dotProduct(a: Array[Int], b: Array[Int]): Int = {
81+
if (a.length != b.length) throw new IllegalArgumentException()
82+
83+
a.indices.map(i => a(i) * b(i)).sum
84+
}
85+
86+
private class BuilderWrapper[A](val builder: Builder[A]) extends util.AbstractCollection[A] {
87+
var size = 0
88+
89+
override def add(e: A): Boolean = { builder += e; size += 1; true }
90+
91+
// Required by AbstractCollection, but not implemented
92+
override def iterator(): util.Iterator[A] = None.orNull
93+
94+
def setInitialValue(init: Collection[A]): Unit = init.asInstanceOf[Iterable[A]].foreach(add)
95+
}
96+
97+
private class Instantiator(config: DeserializationConfig, collectionType: JavaType, valueType: JavaType)
98+
extends StdValueInstantiator(config, collectionType) {
99+
100+
override def canCreateUsingDefault = true
101+
102+
override def createUsingDefault(ctxt: DeserializationContext) =
103+
new BuilderWrapper[AnyRef](builderFor[AnyRef](collectionType.getRawClass, valueType))
104+
}
105+
106+
private class Deserializer[A](collectionType: JavaType, containerDeserializer: CollectionDeserializer)
107+
extends ContainerDeserializerBase[CC[A]](collectionType)
108+
with ContextualDeserializer {
109+
110+
def this(collectionType: JavaType, valueDeser: JsonDeserializer[Object], valueTypeDeser: TypeDeserializer, valueInstantiator: ValueInstantiator) = {
111+
this(collectionType, new CollectionDeserializer(collectionType, valueDeser, valueTypeDeser, valueInstantiator))
112+
}
113+
114+
override def createContextual(ctxt: DeserializationContext, property: BeanProperty): Deserializer[A] = {
115+
val newDelegate = containerDeserializer.createContextual(ctxt, property)
116+
new Deserializer(collectionType, newDelegate)
117+
}
118+
119+
override def getContentType: JavaType = containerDeserializer.getContentType
120+
121+
override def getContentDeserializer: JsonDeserializer[AnyRef] = containerDeserializer.getContentDeserializer
122+
123+
override def deserialize(jp: JsonParser, ctxt: DeserializationContext): CC[A] = {
124+
containerDeserializer.deserialize(jp, ctxt) match {
125+
case wrapper: BuilderWrapper[_] => wrapper.builder.result().asInstanceOf[CC[A]]
126+
}
127+
}
128+
129+
override def deserialize(jp: JsonParser, ctxt: DeserializationContext, intoValue: CC[A]): CC[A] = {
130+
val bw = newBuilderWrapper(ctxt)
131+
bw.setInitialValue(intoValue.asInstanceOf[CC[AnyRef]])
132+
containerDeserializer.deserialize(jp, ctxt, bw) match {
133+
case wrapper: BuilderWrapper[_] => wrapper.builder.result().asInstanceOf[CC[A]]
134+
}
135+
}
136+
137+
override def getEmptyValue(ctxt: DeserializationContext): Object = {
138+
val bw = newBuilderWrapper(ctxt)
139+
bw.builder.result().asInstanceOf[Object]
140+
}
141+
142+
private def newBuilderWrapper(ctxt: DeserializationContext): BuilderWrapper[AnyRef] = {
143+
containerDeserializer.getValueInstantiator.createUsingDefault(ctxt).asInstanceOf[BuilderWrapper[AnyRef]]
144+
}
145+
}
146+
}

src/main/scala/com/fasterxml/jackson/module/scala/deser/GenericFactoryDeserializerResolver.scala renamed to src/main/scala-2.13/com/fasterxml/jackson/module/scala/deser/GenericFactoryDeserializerResolver.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.jsontype.TypeDeserializer
1010

1111
import scala.collection.mutable
1212
import scala.collection.mutable.ListBuffer
13-
import scala.language.higherKinds
1413

1514
abstract class GenericFactoryDeserializerResolver[CC[_], CF[X[_]]] extends Deserializers.Base {
1615
type Collection[A] = CC[A]

0 commit comments

Comments
 (0)