/*
* Copyright (C) 2017-2017 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.oss.protocol.internal.response.result;
import com.datastax.oss.protocol.internal.PrimitiveCodec;
import com.datastax.oss.protocol.internal.PrimitiveSizes;
import com.datastax.oss.protocol.internal.ProtocolConstants;
import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableList;
import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableMap;
import java.util.List;
import java.util.Map;
A data type as returned in protocol responses.
This class aims to encode protocol-level information in the simplest way possible. Any extra
features should be handled in the upper layers of the driver.
/**
* A data type as returned in protocol responses.
*
* <p>This class aims to encode protocol-level information in the simplest way possible. Any extra
* features should be handled in the upper layers of the driver.
*/
public abstract class RawType {
public static <B> RawType decode(B source, PrimitiveCodec<B> decoder, int protocolVersion) {
int id = decoder.readUnsignedShort(source);
switch (id) {
case ProtocolConstants.DataType.CUSTOM:
String className = decoder.readString(source);
return new RawCustom(className);
case ProtocolConstants.DataType.LIST:
return new RawList(decode(source, decoder, protocolVersion));
case ProtocolConstants.DataType.SET:
return new RawSet(decode(source, decoder, protocolVersion));
case ProtocolConstants.DataType.MAP:
RawType key = decode(source, decoder, protocolVersion);
RawType value = decode(source, decoder, protocolVersion);
return new RawMap(key, value);
case ProtocolConstants.DataType.UDT:
String keyspace = decoder.readString(source);
String typeName = decoder.readString(source);
int fieldCount = decoder.readUnsignedShort(source);
NullAllowingImmutableMap.Builder<String, RawType> fields =
NullAllowingImmutableMap.builder(fieldCount);
for (int i = 0; i < fieldCount; i++) {
String fieldName = decoder.readString(source);
RawType fieldType = decode(source, decoder, protocolVersion);
fields.put(fieldName, fieldType);
}
return new RawUdt(keyspace, typeName, fields.build());
case ProtocolConstants.DataType.TUPLE:
fieldCount = decoder.readUnsignedShort(source);
NullAllowingImmutableList.Builder<RawType> fieldTypes =
NullAllowingImmutableList.builder(fieldCount);
for (int i = 0; i < fieldCount; i++) {
fieldTypes.add(decode(source, decoder, protocolVersion));
}
return new RawTuple(fieldTypes.build());
default:
RawType type = PRIMITIVES.get(id);
if (type == null) {
throw new IllegalArgumentException("Unknown type id: " + id);
}
return type;
}
}
See Also:
/** @see ProtocolConstants.DataType */
public final int id;
protected RawType(int id) {
this.id = id;
}
public abstract <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion);
public abstract int encodedSize(int protocolVersion);
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RawType rawType = (RawType) o;
return id == rawType.id;
}
@Override
public int hashCode() {
return id;
}
public static class RawPrimitive extends RawType {
private RawPrimitive(int id) {
super(id);
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
}
@Override
public int encodedSize(int protocolVersion) {
return PrimitiveSizes.SHORT;
}
}
public static class RawCustom extends RawType {
public final String className;
public RawCustom(String className) {
super(ProtocolConstants.DataType.CUSTOM);
this.className = className;
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
encoder.writeString(className, dest);
}
@Override
public int encodedSize(int protocolVersion) {
return PrimitiveSizes.SHORT + PrimitiveSizes.sizeOfString(className);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
RawCustom rawCustom = (RawCustom) o;
return className.equals(rawCustom.className);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + className.hashCode();
return result;
}
}
public static class RawList extends RawType {
public final RawType elementType;
public RawList(RawType elementType) {
super(ProtocolConstants.DataType.LIST);
this.elementType = elementType;
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
elementType.encode(dest, encoder, protocolVersion);
}
@Override
public int encodedSize(int protocolVersion) {
return PrimitiveSizes.SHORT + elementType.encodedSize(protocolVersion);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
RawList rawList = (RawList) o;
return elementType.equals(rawList.elementType);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + elementType.hashCode();
return result;
}
}
public static class RawSet extends RawType {
public final RawType elementType;
public RawSet(RawType elementType) {
super(ProtocolConstants.DataType.SET);
this.elementType = elementType;
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
elementType.encode(dest, encoder, protocolVersion);
}
@Override
public int encodedSize(int protocolVersion) {
return PrimitiveSizes.SHORT + elementType.encodedSize(protocolVersion);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
RawSet rawSet = (RawSet) o;
return elementType.equals(rawSet.elementType);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + elementType.hashCode();
return result;
}
}
public static class RawMap extends RawType {
public final RawType keyType;
public final RawType valueType;
public RawMap(RawType keyType, RawType valueType) {
super(ProtocolConstants.DataType.MAP);
this.keyType = keyType;
this.valueType = valueType;
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
keyType.encode(dest, encoder, protocolVersion);
valueType.encode(dest, encoder, protocolVersion);
}
@Override
public int encodedSize(int protocolVersion) {
return PrimitiveSizes.SHORT
+ keyType.encodedSize(protocolVersion)
+ valueType.encodedSize(protocolVersion);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
RawMap rawMap = (RawMap) o;
return keyType.equals(rawMap.keyType) && valueType.equals(rawMap.valueType);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + keyType.hashCode();
result = 31 * result + valueType.hashCode();
return result;
}
}
public static class RawUdt extends RawType {
public final String keyspace;
public final String typeName;
public final Map<String, RawType> fields;
public RawUdt(String keyspace, String typeName, Map<String, RawType> fields) {
super(ProtocolConstants.DataType.UDT);
this.keyspace = keyspace;
this.typeName = typeName;
this.fields = fields;
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
encoder.writeString(keyspace, dest);
encoder.writeString(typeName, dest);
encoder.writeUnsignedShort(fields.size(), dest);
for (Map.Entry<String, RawType> entry : fields.entrySet()) {
encoder.writeString(entry.getKey(), dest);
entry.getValue().encode(dest, encoder, protocolVersion);
}
}
@Override
public int encodedSize(int protocolVersion) {
int size =
PrimitiveSizes.SHORT
+ PrimitiveSizes.sizeOfString(keyspace)
+ PrimitiveSizes.sizeOfString(typeName)
+ PrimitiveSizes.SHORT;
for (Map.Entry<String, RawType> entry : fields.entrySet()) {
size += PrimitiveSizes.sizeOfString(entry.getKey());
size += entry.getValue().encodedSize(protocolVersion);
}
return size;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
RawUdt rawUdt = (RawUdt) o;
return keyspace.equals(rawUdt.keyspace)
&& typeName.equals(rawUdt.typeName)
&& fields.equals(rawUdt.fields);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + keyspace.hashCode();
result = 31 * result + typeName.hashCode();
result = 31 * result + fields.hashCode();
return result;
}
}
public static class RawTuple extends RawType {
public final List<RawType> fieldTypes;
public RawTuple(List<RawType> fieldTypes) {
super(ProtocolConstants.DataType.TUPLE);
this.fieldTypes = fieldTypes;
}
@Override
public <B> void encode(B dest, PrimitiveCodec<B> encoder, int protocolVersion) {
encoder.writeUnsignedShort(id, dest);
encoder.writeUnsignedShort(fieldTypes.size(), dest);
for (RawType fieldType : fieldTypes) {
fieldType.encode(dest, encoder, protocolVersion);
}
}
@Override
public int encodedSize(int protocolVersion) {
int size = PrimitiveSizes.SHORT + PrimitiveSizes.SHORT;
for (RawType fieldType : fieldTypes) {
size += fieldType.encodedSize(protocolVersion);
}
return size;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
RawTuple rawTuple = (RawTuple) o;
return fieldTypes.equals(rawTuple.fieldTypes);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + fieldTypes.hashCode();
return result;
}
}
Visible for tests /** Visible for tests */
public static final Map<Integer, RawType> PRIMITIVES;
static {
int[] primitiveIds = {
ProtocolConstants.DataType.ASCII,
ProtocolConstants.DataType.BIGINT,
ProtocolConstants.DataType.BLOB,
ProtocolConstants.DataType.BOOLEAN,
ProtocolConstants.DataType.COUNTER,
ProtocolConstants.DataType.DECIMAL,
ProtocolConstants.DataType.DOUBLE,
ProtocolConstants.DataType.FLOAT,
ProtocolConstants.DataType.INET,
ProtocolConstants.DataType.INT,
ProtocolConstants.DataType.TIMESTAMP,
ProtocolConstants.DataType.UUID,
ProtocolConstants.DataType.VARCHAR,
ProtocolConstants.DataType.VARINT,
ProtocolConstants.DataType.TIMEUUID,
ProtocolConstants.DataType.SMALLINT,
ProtocolConstants.DataType.TINYINT,
ProtocolConstants.DataType.DURATION,
ProtocolConstants.DataType.DATE,
ProtocolConstants.DataType.TIME
};
NullAllowingImmutableMap.Builder<Integer, RawType> builder =
NullAllowingImmutableMap.builder(primitiveIds.length);
for (int id : primitiveIds) {
builder.put(id, new RawPrimitive(id));
}
PRIMITIVES = builder.build();
}
}