com.datastax.dse.driver.internal.core.graph.GraphSON1SerdeTP Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.datastax.dse.driver.internal.core.graph;
import com.datastax.dse.driver.api.core.data.geometry.Geometry;
import com.datastax.dse.driver.api.core.data.geometry.LineString;
import com.datastax.dse.driver.api.core.data.geometry.Point;
import com.datastax.dse.driver.api.core.data.geometry.Polygon;
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList;
import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
import com.datastax.oss.driver.shaded.guava.common.net.InetAddresses;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
import org.apache.tinkerpop.shaded.jackson.core.JsonParseException;
import org.apache.tinkerpop.shaded.jackson.core.JsonParser;
import org.apache.tinkerpop.shaded.jackson.core.Version;
import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext;
import org.apache.tinkerpop.shaded.jackson.databind.JsonDeserializer;
import org.apache.tinkerpop.shaded.jackson.databind.JsonSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer;
import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
public class GraphSON1SerdeTP {
//////////////////////// DESERIALIZERS ////////////////////////
/**
* Default deserializer used by the driver for {@link InetAddress} instances. The actual subclass
* returned by this deserializer depends on the type of address: {@link Inet4Address IPV4} or
* {@link Inet6Address IPV6}.
*/
static class DefaultInetAddressDeserializer extends StdDeserializer {
private static final long serialVersionUID = 1L;
private final Class inetClass;
DefaultInetAddressDeserializer(Class inetClass) {
super(inetClass);
this.inetClass = inetClass;
}
@Override
public T deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
String ip = parser.readValueAs(String.class);
try {
InetAddress inet = InetAddresses.forString(ip);
return inetClass.cast(inet);
} catch (ClassCastException e) {
throw new JsonParseException(
parser,
String.format("Inet address cannot be cast to %s: %s", inetClass.getSimpleName(), ip),
e);
} catch (IllegalArgumentException e) {
throw new JsonParseException(parser, String.format("Expected inet address, got %s", ip), e);
}
}
}
/**
* Default deserializer used by the driver for geospatial types. It deserializes such types into
* {@link Geometry} instances. The actual subclass depends on the type being deserialized.
*/
static class DefaultGeometryDeserializer extends StdDeserializer {
private static final long serialVersionUID = 1L;
private final Class geometryClass;
DefaultGeometryDeserializer(Class geometryClass) {
super(geometryClass);
this.geometryClass = geometryClass;
}
@Override
public T deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
String wkt = parser.readValueAs(String.class);
Geometry geometry;
if (wkt.startsWith("POINT")) geometry = Point.fromWellKnownText(wkt);
else if (wkt.startsWith("LINESTRING")) geometry = LineString.fromWellKnownText(wkt);
else if (wkt.startsWith("POLYGON")) geometry = Polygon.fromWellKnownText(wkt);
else throw new JsonParseException(parser, "Unknown geometry type: " + wkt);
return geometryClass.cast(geometry);
}
}
/** Base class for serializing the {@code java.time.*} types to ISO-8061 formats. */
abstract static class AbstractJavaTimeSerializer extends StdSerializer {
private static final long serialVersionUID = 1L;
AbstractJavaTimeSerializer(final Class clazz) {
super(clazz);
}
@Override
public void serialize(
final T value, final JsonGenerator gen, final SerializerProvider serializerProvider)
throws IOException {
gen.writeString(value.toString());
}
}
/** Base class for deserializing the {@code java.time.*} types from ISO-8061 formats. */
abstract static class AbstractJavaTimeJacksonDeserializer extends StdDeserializer {
private static final long serialVersionUID = 1L;
AbstractJavaTimeJacksonDeserializer(final Class clazz) {
super(clazz);
}
abstract T parse(final String val);
@Override
public T deserialize(
final JsonParser jsonParser, final DeserializationContext deserializationContext)
throws IOException {
return parse(jsonParser.getText());
}
}
static final class DurationJacksonSerializer
extends AbstractJavaTimeSerializer {
private static final long serialVersionUID = 1L;
DurationJacksonSerializer() {
super(java.time.Duration.class);
}
}
static final class DurationJacksonDeserializer
extends AbstractJavaTimeJacksonDeserializer {
private static final long serialVersionUID = 1L;
DurationJacksonDeserializer() {
super(java.time.Duration.class);
}
@Override
public java.time.Duration parse(final String val) {
return java.time.Duration.parse(val);
}
}
static final class InstantJacksonSerializer
extends AbstractJavaTimeSerializer {
private static final long serialVersionUID = 1L;
InstantJacksonSerializer() {
super(java.time.Instant.class);
}
}
static final class InstantJacksonDeserializer
extends AbstractJavaTimeJacksonDeserializer {
private static final long serialVersionUID = 1L;
InstantJacksonDeserializer() {
super(java.time.Instant.class);
}
@Override
public java.time.Instant parse(final String val) {
return java.time.Instant.parse(val);
}
}
static final class LocalDateJacksonSerializer
extends AbstractJavaTimeSerializer {
private static final long serialVersionUID = 1L;
LocalDateJacksonSerializer() {
super(java.time.LocalDate.class);
}
}
static final class LocalDateJacksonDeserializer
extends AbstractJavaTimeJacksonDeserializer {
private static final long serialVersionUID = 1L;
LocalDateJacksonDeserializer() {
super(java.time.LocalDate.class);
}
@Override
public java.time.LocalDate parse(final String val) {
return java.time.LocalDate.parse(val);
}
}
static final class LocalTimeJacksonSerializer
extends AbstractJavaTimeSerializer {
private static final long serialVersionUID = 1L;
LocalTimeJacksonSerializer() {
super(java.time.LocalTime.class);
}
}
static final class LocalTimeJacksonDeserializer
extends AbstractJavaTimeJacksonDeserializer {
private static final long serialVersionUID = 1L;
LocalTimeJacksonDeserializer() {
super(java.time.LocalTime.class);
}
@Override
public java.time.LocalTime parse(final String val) {
return java.time.LocalTime.parse(val);
}
}
//////////////////////// SERIALIZERS ////////////////////////
/** Default serializer used by the driver for {@link LegacyGraphNode} instances. */
static class DefaultGraphNodeSerializer extends StdSerializer {
private static final long serialVersionUID = 1L;
DefaultGraphNodeSerializer() {
super(LegacyGraphNode.class);
}
@Override
public void serialize(
LegacyGraphNode value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeTree(value.getDelegate());
}
}
/**
* Default serializer used by the driver for geospatial types. It serializes {@link Geometry}
* instances into their Well-Known Text (WKT) equivalent.
*/
static class DefaultGeometrySerializer extends StdSerializer {
private static final long serialVersionUID = 1L;
DefaultGeometrySerializer() {
super(Geometry.class);
}
@Override
public void serialize(
Geometry value, JsonGenerator jsonGenerator, SerializerProvider serializers)
throws IOException {
jsonGenerator.writeString(value.asWellKnownText());
}
}
/** The default Jackson module used by DSE Graph. */
static class GraphSON1DefaultModule extends SimpleModule {
private static final long serialVersionUID = 1L;
GraphSON1DefaultModule(String name, Version version) {
super(name, version, createDeserializers(), createSerializers());
}
private static Map, JsonDeserializer> createDeserializers() {
return ImmutableMap., JsonDeserializer>builder()
// Inet (there is no built-in deserializer for InetAddress and subclasses)
.put(InetAddress.class, new DefaultInetAddressDeserializer<>(InetAddress.class))
.put(Inet4Address.class, new DefaultInetAddressDeserializer<>(Inet4Address.class))
.put(Inet6Address.class, new DefaultInetAddressDeserializer<>(Inet6Address.class))
// Geospatial types
.put(Geometry.class, new DefaultGeometryDeserializer<>(Geometry.class))
.put(Point.class, new DefaultGeometryDeserializer<>(Point.class))
.put(LineString.class, new DefaultGeometryDeserializer<>(LineString.class))
.put(Polygon.class, new DefaultGeometryDeserializer<>(Polygon.class))
.build();
}
private static List> createSerializers() {
return ImmutableList.>builder()
.add(new DefaultGraphNodeSerializer())
.add(new DefaultGeometrySerializer())
.build();
}
}
/** Serializers and deserializers for JSR 310 {@code java.time.*}. */
static class GraphSON1JavaTimeModule extends SimpleModule {
private static final long serialVersionUID = 1L;
GraphSON1JavaTimeModule(String name, Version version) {
super(name, version, createDeserializers(), createSerializers());
}
private static Map, JsonDeserializer> createDeserializers() {
return ImmutableMap., JsonDeserializer>builder()
.put(java.time.Duration.class, new DurationJacksonDeserializer())
.put(java.time.Instant.class, new InstantJacksonDeserializer())
.put(java.time.LocalDate.class, new LocalDateJacksonDeserializer())
.put(java.time.LocalTime.class, new LocalTimeJacksonDeserializer())
.build();
}
private static List> createSerializers() {
return ImmutableList.>builder()
.add(new DurationJacksonSerializer())
.add(new InstantJacksonSerializer())
.add(new LocalDateJacksonSerializer())
.add(new LocalTimeJacksonSerializer())
.build();
}
}
}