11package streams.serialization
22
3- import org.codehaus.jackson.JsonGenerator
4- import org.codehaus.jackson.JsonProcessingException
5- import org.codehaus.jackson.Version
6- import org.codehaus.jackson.map.JsonSerializer
7- import org.codehaus.jackson.map.ObjectMapper
8- import org.codehaus.jackson.map.SerializationConfig
9- import org.codehaus.jackson.map.SerializerProvider
10- import org.codehaus.jackson.map.module.SimpleModule
3+ import com.fasterxml.jackson.core.JsonGenerator
4+ import com.fasterxml.jackson.core.JsonProcessingException
5+ import com.fasterxml.jackson.databind.JsonSerializer
6+ import com.fasterxml.jackson.databind.ObjectMapper
7+ import com.fasterxml.jackson.databind.SerializationFeature
8+ import com.fasterxml.jackson.databind.SerializerProvider
9+ import com.fasterxml.jackson.databind.module.SimpleModule
10+ import com.fasterxml.jackson.module.kotlin.convertValue
11+ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
12+ import com.fasterxml.jackson.module.kotlin.readValue
13+ import org.neo4j.driver.internal.value.PointValue
1114import org.neo4j.graphdb.spatial.Point
1215import org.neo4j.values.storable.CoordinateReferenceSystem
16+ import streams.events.*
17+ import streams.utils.StreamsUtils
1318import java.io.IOException
1419import java.time.temporal.TemporalAccessor
1520
@@ -29,6 +34,18 @@ fun Point.toStreamsPoint(): StreamsPoint {
2934 }
3035}
3136
37+ fun PointValue.toStreamsPoint (): StreamsPoint {
38+ val point = this .asPoint()
39+ val crsType = point.srid()
40+ return when (crsType) {
41+ CoordinateReferenceSystem .Cartesian .code -> StreamsPointCartesian (CoordinateReferenceSystem .Cartesian .name, point.x(), point.y())
42+ CoordinateReferenceSystem .Cartesian_3D .code -> StreamsPointCartesian (CoordinateReferenceSystem .Cartesian_3D .name, point.x(), point.y(), point.z())
43+ CoordinateReferenceSystem .WGS84 .code -> StreamsPointWgs (CoordinateReferenceSystem .WGS84 .name, point.x(), point.y())
44+ CoordinateReferenceSystem .WGS84_3D .code -> StreamsPointWgs (CoordinateReferenceSystem .WGS84_3D .name, point.x(), point.y(), point.z())
45+ else -> throw IllegalArgumentException (" Point type $crsType not supported" )
46+ }
47+ }
48+
3249class PointSerializer : JsonSerializer <Point >() {
3350 @Throws(IOException ::class , JsonProcessingException ::class )
3451 override fun serialize (value : Point ? , jgen : JsonGenerator ,
@@ -40,6 +57,17 @@ class PointSerializer : JsonSerializer<Point>() {
4057 }
4158}
4259
60+ class PointValueSerializer : JsonSerializer <PointValue >() {
61+ @Throws(IOException ::class , JsonProcessingException ::class )
62+ override fun serialize (value : PointValue ? , jgen : JsonGenerator ,
63+ provider : SerializerProvider ) {
64+ if (value == null ) {
65+ return
66+ }
67+ jgen.writeObject(value.toStreamsPoint())
68+ }
69+ }
70+
4371class TemporalAccessorSerializer : JsonSerializer <TemporalAccessor >() {
4472 @Throws(IOException ::class , JsonProcessingException ::class )
4573 override fun serialize (value : TemporalAccessor ? , jgen : JsonGenerator ,
@@ -54,14 +82,15 @@ class TemporalAccessorSerializer : JsonSerializer<TemporalAccessor>() {
5482
5583object JSONUtils {
5684
57- private val OBJECT_MAPPER : ObjectMapper = ObjectMapper ()
85+ private val OBJECT_MAPPER : ObjectMapper = jacksonObjectMapper ()
5886
5987 init {
60- val module = SimpleModule (" Neo4jKafkaSerializer" , Version (1 , 0 , 0 , " " ))
61- module.addSerializer(Point ::class .java, PointSerializer ())
88+ val module = SimpleModule (" Neo4jKafkaSerializer" )
89+ StreamsUtils .ignoreExceptions({ module.addSerializer(Point ::class .java, PointSerializer ()) }, NoClassDefFoundError ::class .java) // in case is loaded from
90+ StreamsUtils .ignoreExceptions({ module.addSerializer(PointValue ::class .java, PointValueSerializer ()) }, NoClassDefFoundError ::class .java) // in case is loaded from
6291 module.addSerializer(TemporalAccessor ::class .java, TemporalAccessorSerializer ())
6392 OBJECT_MAPPER .registerModule(module)
64- OBJECT_MAPPER .disable(SerializationConfig . Feature .FAIL_ON_EMPTY_BEANS )
93+ OBJECT_MAPPER .disable(SerializationFeature .FAIL_ON_EMPTY_BEANS )
6594 }
6695
6796 fun getObjectMapper (): ObjectMapper {
@@ -81,7 +110,50 @@ object JSONUtils {
81110 return OBJECT_MAPPER .writeValueAsBytes(any)
82111 }
83112
84- fun <T > readValue (value : ByteArray , clazz : Class <T >): T {
85- return OBJECT_MAPPER .readValue(value, clazz)
113+ inline fun <reified T > readValue (value : ByteArray ): T {
114+ return getObjectMapper().readValue(value, T ::class .java)
115+ }
116+
117+ inline fun <reified T > readValue (value : Any ): T {
118+ val strValue = when (value) {
119+ is String -> value
120+ else -> getObjectMapper().writeValueAsString(value)
121+ }
122+ return getObjectMapper().readValue(strValue)
123+ }
124+
125+ inline fun <reified T > convertValue (value : Any ): T {
126+ return getObjectMapper().convertValue(value)
127+ }
128+
129+ @Suppress(" UNCHECKED_CAST" )
130+ fun asStreamsTransactionEvent (obj : Any ): StreamsTransactionEvent {
131+ val value = when (obj) {
132+ is Map <* , * > -> obj as Map <String , Map <String , Any >>
133+ is String -> readValue(obj)
134+ is ByteArray -> readValue(obj)
135+ else -> convertValue(obj)
136+ }
137+ val meta = convertValue<Meta >(value.getValue(" meta" ))
138+
139+ val schema = convertValue<Schema >(value.getValue(" schema" ))
140+
141+ val payloadMap = value.getValue(" payload" )
142+ val type = payloadMap.getValue(" type" ).toString()
143+ val id = payloadMap.getValue(" id" ).toString()
144+
145+ val payload = if (type == " node" ) {
146+ val before = if (payloadMap[" before" ] != null ) convertValue<NodeChange >(payloadMap[" before" ]!! ) else null
147+ val after = if (payloadMap[" after" ] != null ) convertValue<NodeChange >(payloadMap[" after" ]!! ) else null
148+ NodePayload (id, before, after)
149+ } else {
150+ val label= payloadMap.getValue(" label" ).toString()
151+ val start = convertValue<RelationshipNodeChange >(payloadMap.getValue(" start" ))
152+ val end = convertValue<RelationshipNodeChange >(payloadMap.getValue(" end" ))
153+ val before = if (payloadMap[" before" ] != null ) convertValue<RelationshipChange >(payloadMap[" before" ]!! ) else null
154+ val after = if (payloadMap[" after" ] != null ) convertValue<RelationshipChange >(payloadMap[" after" ]!! ) else null
155+ RelationshipPayload (id, start, end, before, after, label)
156+ }
157+ return StreamsTransactionEvent (meta, payload, schema)
86158 }
87159}
0 commit comments