All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.dse.driver.internal.core.graph.binary.AbstractSimpleGraphBinaryCustomSerializer Maven / Gradle / Ivy

/*
 * Copyright DataStax, Inc.
 *
 * Licensed 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.binary;

import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
import java.io.IOException;
import org.apache.tinkerpop.gremlin.structure.io.Buffer;
import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
import org.apache.tinkerpop.gremlin.structure.io.binary.types.CustomTypeSerializer;

/**
 * A base custom type serializer for DSE types that handles most of the boiler plate code associated
 * with GraphBinary's custom types.
 *
 * 

The full format of a custom type in GraphBinary is the following: * *

{type_code}{custom_type_name}{custom_type_info_length}{custom_type_info_bytes}{value_flag}{value_length}{value_bytes} * *

This class is made to handle * {type_code}{custom_type_name}{custom_type_info_length}{custom_type_info_bytes}{value_flag} for * DSE types. * *

Implementing classes are still in charge of encoding {value_length}{value_bytes} in the {@link * #readCustomValue(int, Buffer, GraphBinaryReader)} implementations. * *

Implementing classes must override {@link CustomTypeSerializer#getTypeName()} with their own * type name. * * @param the java type the implementing classes will encode and decode. */ abstract class AbstractSimpleGraphBinaryCustomSerializer implements CustomTypeSerializer { AbstractSimpleGraphBinaryCustomSerializer() { super(); } protected static final String INCORRECT_VALUE_LENGTH_ERROR_MESSAGE = "{value_length} read for this value does not correspond to the size of a '%s' value. [%s] bytes required but got [%s]"; protected abstract T readCustomValue(int valueLength, Buffer buffer, GraphBinaryReader context) throws IOException; protected abstract void writeCustomValue(T value, Buffer buffer, GraphBinaryWriter context) throws IOException; protected void checkValueSize(int lengthRequired, int lengthFound) { Preconditions.checkArgument( lengthFound == lengthRequired, INCORRECT_VALUE_LENGTH_ERROR_MESSAGE, getTypeName(), lengthRequired, lengthFound); } @Override public DataType getDataType() { return DataType.CUSTOM; } @Override public T read(Buffer buffer, GraphBinaryReader context) throws IOException { // the type serializer registry will take care of deserializing {custom_type_name} // read {custom_type_info_length} and verify it is 0. // See #write(T, ByteBuf, GraphBinaryWriter) for why it is set to 0 if (context.readValue(buffer, Integer.class, false) != 0) { throw new IOException("{custom_type_info} should not be provided for this custom type"); } return readValue(buffer, context, true); } @Override public T readValue(Buffer buffer, GraphBinaryReader context, boolean nullable) throws IOException { if (nullable) { // read {value_flag} final byte valueFlag = buffer.readByte(); // if value is null and the value is nullable if ((valueFlag & 1) == 1) { return null; } // Note: we don't error out if the valueFlag == "value is null" and nullable == false because // the serializer // should have errored out at write time if that was the case. } // Read the byte length of the value bytes final int valueLength = buffer.readInt(); if (valueLength <= 0) { throw new IOException(String.format("Unexpected value length: %d", valueLength)); } if (valueLength > buffer.readableBytes()) { throw new IOException( String.format( "Not enough readable bytes: %d bytes required for value (%d bytes available)", valueLength, buffer.readableBytes())); } // subclasses are responsible for reading {value} return readCustomValue(valueLength, buffer, context); } @Override public void write(final T value, final Buffer buffer, final GraphBinaryWriter context) throws IOException { // the type serializer registry will take care of serializing {custom_type_name} // write "{custom_type_info_length}" to 0 because we don't need it for the DSE types context.writeValue(0, buffer, false); writeValue(value, buffer, context, true); } @Override public void writeValue( final T value, final Buffer buffer, final GraphBinaryWriter context, final boolean nullable) throws IOException { if (value == null) { if (!nullable) { throw new IOException("Unexpected null value when nullable is false"); } // writes {value_flag} to "1" which means "the value is null" context.writeValueFlagNull(buffer); return; } if (nullable) { // writes {value_flag} to "0" which means "value is not null" context.writeValueFlagNone(buffer); } // sub classes will be responsible for writing {value_length} and {value_bytes} writeCustomValue(value, buffer, context); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy