/**
* Copyright 2024 Beijing Baolande Software Corporation
*
* 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.
*
* Runtime Library Exception to the Apache 2.0 License:
*
* As an exception, if you use this Software to compile your source code and
* portions of this Software are embedded into the binary product as a result,
* you may redistribute such product without providing attribution as would
* otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.
*/
package redis_sdk.client.api
public interface ResponseBuilder<T> {
func build(message: RedisMessage): T
}
public class ResponseBuilderHelper {
/**
* 解构Option<RedisMessage>
*/
public static func getRedisMessageOrThrow(message: Option<RedisMessage>, messageType: RedisMessageType): RedisMessage {
if (let Some(redisMessage) <- message) {
return redisMessage
} else {
throw RedisException("Incompatible type, nil message, expected ${messageType}")
}
}
/**
* 判断ArrayList是否嵌套ArraysRedisMessage
*/
public static func isArraysFirstElement(children: ArrayList<RedisMessage>): Bool {
if (children.size > 0) {
let firstElement = children.get(0)
if (let Some(firstElement) <- firstElement) {
if (let Some(child) <- (firstElement as ArraysRedisMessage)) {
return true
}
}
}
return false
}
/**
* 从HashMap<String, Any>中获取值
*/
public static func getValueFromMap<T>(data: HashMap<String, Any>, keyName: String): T {
try {
return (data.get(keyName).getOrThrow() as T).getOrThrow()
} catch (ex: Exception) {
throw RedisException("Failure to obtain ${keyName}: ${ex.message}", ex)
}
}
/**
* 从HashMap<String, Any>中获取值
*/
public static func getNillableValueFromMap<T>(data: HashMap<String, Any>, keyName: String): ?T {
try {
if (let Some(value) <- data.get(keyName)) {
return (value as T).getOrThrow()
} else {
return None
}
} catch (ex: Exception) {
throw RedisException("Failure to obtain ${keyName}: ${ex.message}", ex)
}
}
/**
* 解析为简单类型:Int64、String、Boolean、Float64
*/
public static func unwrapToSimpleType<T>(redisMessage: RedisMessage): T {
if (let Some(integerMessage) <- (redisMessage as IntegerRedisMessage)) {
if (let Some(value) <- (integerMessage.getValue() as T)) {
return value
}
} else if (let Some(stringMessage) <- (redisMessage as StringRedisMessage)) {
if (let Some(value) <- (stringMessage.getValue() as T)) {
return value
}
} else if (let Some(bulkStringMesage) <- (redisMessage as BulkStringRedisMessage)) {
let bulkStringMesageVal = bulkStringMesage.getStringValue()
if (let Some(bulkStringMesageVal) <- bulkStringMesageVal) {
if (let Some(value) <- (bulkStringMesageVal as T)) {
return value
} else if (let Some(v) <- (1.1f64 as T)) {
return (Float64.parse(bulkStringMesageVal) as T).getOrThrow()
}
} else {
throw RedisException("Incompatible type, nil/null BulkString is not the expect type")
}
} else if (let Some(boolMessage) <- (redisMessage as BooleanRedisMessage)) {
if (let Some(value) <- (boolMessage.getValue() as T)) {
return value
}
} else if (let Some(dobuleMessage) <- (redisMessage as DoubleRedisMessage)) {
if (let Some(value) <- (dobuleMessage.getValue() as T)) {
return value
}
} else if (let Some(bigNumberMessage) <- (redisMessage as BigNumberRedisMessage)) {
if (let Some(value) <- (bigNumberMessage.getValue() as T)) {
return value
}
} else if (let Some(errorMesage) <- (redisMessage as ErrorRedisMessage)) {
throw RedisException(errorMesage.getValue())
}
throw RedisException("Incompatible type, ${redisMessage.getType()} is not the expect type")
}
/**
* 解析为允许None值的简单类型:Int64、String、Boolean、Float64
*/
public static func unwrapToNillableSimpleType<T>(redisMessage: RedisMessage): ?T {
if (let Some(integerMessage) <- (redisMessage as IntegerRedisMessage)) {
if (let Some(value) <- (integerMessage.getValue() as T)) {
return value
}
} else if (let Some(stringMessage) <- (redisMessage as StringRedisMessage)) {
if (let Some(value) <- (stringMessage.getValue() as T)) {
return value
}
} else if (let Some(bulkStringMesage) <- (redisMessage as BulkStringRedisMessage)) {
let bulkStringMesageVal = bulkStringMesage.getStringValue()
if (let Some(bulkStringMesageVal) <- bulkStringMesageVal) {
if (let Some(value) <- (bulkStringMesageVal as T)) {
return value
} else if (let Some(v) <- (1.1f64 as T)) {
return Float64.parse(bulkStringMesageVal) as T
}
} else {
if (let Some(test) <- ("abc" as T)) {
return None<T>
} else if (let Some(v) <- (1.1f64 as T)) {
return None<T>
} else if (let Some(test) <- (1 as T)) {
return None<T>
} else {
throw RedisException("Incompatible type, ${redisMessage.getType()} is not the expect type")
}
throw RedisException("Incompatible type, nil/null BulkString is not the expect type")
}
} else if (let Some(nullMessage) <- (redisMessage as NullRedisMessage)) {
return None<T>
} else if (let Some(boolMessage) <- (redisMessage as BooleanRedisMessage)) {
if (let Some(value) <- (boolMessage.getValue() as T)) {
return value
}
} else if (let Some(dobuleMessage) <- (redisMessage as DoubleRedisMessage)) {
if (let Some(value) <- (dobuleMessage.getValue() as T)) {
return value
}
} else if (let Some(bigNumberMessage) <- (redisMessage as BigNumberRedisMessage)) {
if (let Some(value) <- (bigNumberMessage.getValue() as T)) {
return value
}
} else if (let Some(errorMesage) <- (redisMessage as ErrorRedisMessage)) {
throw RedisException(errorMesage.getValue())
}
throw RedisException("Incompatible type, ${redisMessage.getType()} is not the expect type")
}
public static func unwrapToNillableAnySimpleType(redisMessage: RedisMessage): ?Any {
if (let Some(integerMessage) <- (redisMessage as IntegerRedisMessage)) {
return integerMessage.getValue()
} else if (let Some(stringMessage) <- (redisMessage as StringRedisMessage)) {
return stringMessage.getValue()
} else if (let Some(bulkStringMesage) <- (redisMessage as BulkStringRedisMessage)) {
if (let Some(bulkStringMesage) <- bulkStringMesage.getStringValue()) {
return bulkStringMesage
} else {
return None
}
} else if (let Some(nullMessage) <- (redisMessage as NullRedisMessage)) {
return None
} else if (let Some(boolMessage) <- (redisMessage as BooleanRedisMessage)) {
return boolMessage.getValue()
} else if (let Some(dobuleMessage) <- (redisMessage as DoubleRedisMessage)) {
return dobuleMessage.getValue()
} else if (let Some(bigNumberMessage) <- (redisMessage as BigNumberRedisMessage)) {
return bigNumberMessage.getValue()
} else if (let Some(errorMesage) <- (redisMessage as ErrorRedisMessage)) {
throw RedisException(errorMesage.getValue())
}
throw RedisException("Incompatible type, ${redisMessage.getType()} is not the expect type")
}
}
public class StringResponseBuilder <: ResponseBuilder<String> {
public func build(message: RedisMessage): String {
if (let Some(message) <- (message as StringRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as BulkStringRedisMessage)) {
if (let Some(value) <- message.getStringValue()) {
return value
} else {
throw RedisException("Nil Reply")
}
} else if (let Some(message) <- (message as VerbatimRedisMessage)) {
if (message.getEncoding() == "txt") {
return message.getStringContent()
} else {
return message.getEncoding() + ":" + message.getStringContent()
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class AggressiveObjectObjectBuilder <: ResponseBuilder<?Any> {
public func build(message: RedisMessage): ?Any {
if (let Some(item) <- (message as ArraysRedisMessage)) {
if (let Some(arraysMessage) <- item.getValue()) {
if (arraysMessage.isEmpty()) {
return HashMap<String, String>()
}
if (let Some(item) <- ((arraysMessage.get(0) as MapRedisMessage))) {
let list: ArrayList<KeyValueMessagePair> = ResponseBuilderFactory
.listOfKeyValueBuilder
.build(message)
var runningScriptMap: HashMap<String, Any> = HashMap<String, Any>()
var resultMap = HashMap<String, ?Any>()
for (kv in list) {
resultMap.add(
ResponseBuilderFactory.stringBuilder.build(kv.getKey()),
this.build(kv.getValue())
)
}
return resultMap
} else {
var resultArrays = ArrayList<?Any>()
for (obj in arraysMessage) {
resultArrays.add(this.build(obj))
}
return resultArrays
}
}
} else {
return ResponseBuilderHelper.unwrapToNillableAnySimpleType(message)
}
}
}
public class ByteArrayResponseBuilder <: ResponseBuilder<Array<Byte>> {
public func build(message: RedisMessage): Array<Byte> {
if (let Some(message) <- (message as BulkStringRedisMessage)) {
if (let Some(messgeByte) <- message.getByteArray()) {
return messgeByte
}
throw RedisException("Incompatible type, nil/null BulkString is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class ListOfBoolBuilder <: ResponseBuilder<ArrayList<Bool>> {
public func build(message: RedisMessage): ArrayList<Bool> {
let response = ResponseBuilderFactory.listOfIntegerBuilder.build(message)
let result = ArrayList<Bool>()
for (item in response) {
match (item) {
case 1 => result.add(true)
case _ => result.add(false)
}
}
return result
}
}
public class NillableStringResponseBuilder <: ResponseBuilder<?String> {
public func build(message: RedisMessage): ?String {
if (let Some(message) <- (message as StringRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as BulkStringRedisMessage)) {
return message.getStringValue()
} else if (let Some(nullMessage) <- (message as NullRedisMessage)) {
return None<String>
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class NillableByteArrayResponseBuilder <: ResponseBuilder<?Array<Byte>> {
public func build(message: RedisMessage): ?Array<Byte> {
if (let Some(message) <- (message as BulkStringRedisMessage)) {
return message.getByteArray()
} else if (let Some(nullMessage) <- (message as NullRedisMessage)) {
return None<Array<Byte>>
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class IntegerResponseBuilder <: ResponseBuilder<Int64> {
public func build(message: RedisMessage): Int64 {
if (let Some(message) <- (message as IntegerRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class DoubleResponseBuilder <: ResponseBuilder<Float64> {
public func build(message: RedisMessage): Float64 {
if (let Some(message) <- (message as DoubleRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as BulkStringRedisMessage)) {
if (let Some(value) <- message.getStringValue()) {
return Float64.parse(value)
}
throw RedisException("Incompatible type, nil/null BulkString is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class NillableDoubleResponseBuilder <: ResponseBuilder<?Float64> {
public func build(message: RedisMessage): ?Float64 {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as DoubleRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as BulkStringRedisMessage)) {
if (let Some(value) <- message.getStringValue()) {
return Float64.parse(value)
} else {
return None
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class NillableIntegerResponseBuilder <: ResponseBuilder<?Int64> {
public func build(message: RedisMessage): ?Int64 {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as IntegerRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as BulkStringRedisMessage)) {
if (message.isNull()) {
return None
} else {
throw RedisException("Incompatible type, null/nil BULK_STRINGS is not the expect type")
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class BoolResponseBuilder <: ResponseBuilder<Bool> {
public func build(message: RedisMessage): Bool {
if (let Some(message) <- (message as IntegerRedisMessage)) {
let responseCode = message.getValue()
match (responseCode) {
case 0 => return false
case 1 => return true
case _ => throw RedisException("Invalid response ${responseCode} for bool response")
}
} else if (let Some(message) <- (message as BooleanRedisMessage)) {
return message.getValue()
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class ArrayResponseBuilder<T> <: ResponseBuilder<Array<T>> {
public func build(message: RedisMessage): Array<T> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<T>()
if (message.isNull()) {
return results.toArray()
}
let children = message.getValue()
if (let Some(children) <- children) {
processChildren(children, results)
}
return results.toArray()
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
protected static func processChildren(children: ArrayList<RedisMessage>, results: ArrayList<T>) {
for (child in children) {
let unwrapedValue = ResponseBuilderHelper.unwrapToSimpleType<T>(child)
results.add(unwrapedValue)
}
}
}
public class NillableArrayOfResponseBuilder<T> <: ResponseBuilder<?Array<T>> {
public func build(message: RedisMessage): ?Array<T> {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<T>()
if (message.isNull()) {
return None
}
let children = message.getValue()
if (let Some(children) <- children) {
processChildren(children, results)
}
return results.toArray()
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
protected static func processChildren(children: ArrayList<RedisMessage>, results: ArrayList<T>) {
for (child in children) {
let unwrapedValue = ResponseBuilderHelper.unwrapToSimpleType<T>(child)
results.add(unwrapedValue)
}
}
}
public class SetOfResponseBuilder<T> <: ResponseBuilder<HashSet<T>> where T <: Hashable & Equatable<T> {
public func build(message: RedisMessage): HashSet<T> {
if (let Some(message) <- (message as SetRedisMessage)) {
let results = HashSet<T>()
let children = message.getValue()
processChildren(children, results)
return results
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = HashSet<T>()
if (message.isNull()) {
return results
}
let children = message.getValue()
if (let Some(children) <- children) {
processChildren(children, results)
}
return results
} else if (let Some(message) <- (message as MapRedisMessage)) {
let results = HashSet<T>()
if (message.isEmpty()) {
return results
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
protected static func processChildren(children: ArrayList<RedisMessage>, results: HashSet<T>) {
for (child in children) {
let unwrapedValue = ResponseBuilderHelper.unwrapToSimpleType<T>(child)
results.add(unwrapedValue)
}
}
}
public class ArrayOfNillableResponseBuilder<T> <: ResponseBuilder<Array<?T>> {
public func build(message: RedisMessage): Array<?T> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<?T>()
if (message.isNull()) {
return results.toArray()
}
let children = message.getValue()
if (let Some(children) <- children) {
processChildren(children, results)
}
return results.toArray()
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
protected static func processChildren(children: ArrayList<RedisMessage>, results: ArrayList<?T>) {
for (child in children) {
let unwrapedValue = ResponseBuilderHelper.unwrapToNillableSimpleType<T>(child)
results.add(unwrapedValue)
}
}
}
public class NillableListResponseBuilder<T> <: ResponseBuilder<?ArrayList<T>> {
public func build(message: RedisMessage): ?ArrayList<T> {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as BulkStringRedisMessage)) {
if (message.isNull()) {
return None
}
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<T>()
if (message.isNull()) {
return None
}
let children = message.getValue()
if (let Some(children) <- children) {
processChildren(children, results)
}
return results
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
protected static func processChildren(children: ArrayList<RedisMessage>, results: ArrayList<T>) {
for (child in children) {
let unwrapedValue = ResponseBuilderHelper.unwrapToSimpleType<T>(child)
results.add(unwrapedValue)
}
}
}
public class ListResponseBuilder<T> <: ResponseBuilder<ArrayList<T>> {
public func build(message: RedisMessage): ArrayList<T> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<T>()
if (message.isNull() || message.getSize() == 0) {
return results
}
let children = message.getValue()
if (let Some(children) <- children) {
ArrayResponseBuilder.processChildren(children, results)
}
return results
} else if (let Some(message) <- (message as SetRedisMessage)) {
let results = ArrayList<T>()
if (message.getSize() == 0) {
return results
}
let children = message.getValue()
ArrayResponseBuilder.processChildren(children, results)
return results
} else if (let Some(message) <- (message as MapRedisMessage)) {
let results = ArrayList<T>()
if (message.isEmpty()) {
return results
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class ListOfNillableResponseBuilder<T> <: ResponseBuilder<ArrayList<?T>> {
public func build(message: RedisMessage): ArrayList<?T> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<?T>()
if (message.isNull()) {
return results
}
let children = message.getValue()
if (let Some(children) <- children) {
ArrayOfNillableResponseBuilder.processChildren(children, results)
}
return results
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class TupleOfStringAndArrayResponseBuilder<T> <: ResponseBuilder<(String, Array<T>)> {
public func build(message: RedisMessage): (String, Array<T>) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<T>()
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let arrayMessage = ResponseBuilderHelper.getRedisMessageOrThrow(children.get(1), RedisMessageType.ARRAYS
)
if (let Some(arrayMessage) <- (arrayMessage as ArraysRedisMessage)) {
let children = arrayMessage.getValue()
if (let Some(children) <- children) {
ArrayResponseBuilder.processChildren(children, results)
}
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.ARRAYS}, but ${bulkStringMessage.getType()}"
)
}
return (key, results.toArray())
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class NillableTupleOfStringAndListResponseBuilder<T> <: ResponseBuilder<?(String, ArrayList<T>)> {
public func build(message: RedisMessage): ?(String, ArrayList<T>) {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
if (message.isNull()) {
return None
}
return TupleOfStringAndListResponseBuilder<T>().build(message)
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class TupleOfStringAndTupleListResponseBuilder <: ResponseBuilder<(String, ArrayList<(String, Float64)>)> {
public func build(message: RedisMessage): (String, ArrayList<(String, Float64)>) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let arrayMessage = ResponseBuilderHelper.getRedisMessageOrThrow(children.get(1), RedisMessageType.ARRAYS
)
let results = ResponseBuilderFactory.listOfStringDoubleTupleBuilder.build(arrayMessage)
return (key, results)
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class TupleOfStringAndListResponseBuilder<T> <: ResponseBuilder<(String, ArrayList<T>)> {
public func build(message: RedisMessage): (String, ArrayList<T>) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<T>()
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let arrayMessage = ResponseBuilderHelper.getRedisMessageOrThrow(children.get(1), RedisMessageType.ARRAYS
)
if (let Some(arrayMessage) <- (arrayMessage as ArraysRedisMessage)) {
let children = arrayMessage.getValue()
if (let Some(children) <- children) {
ArrayResponseBuilder.processChildren(children, results)
}
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.ARRAYS}, but ${bulkStringMessage.getType()}"
)
}
return (key, results)
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class NillableTupleOfStringAndStringDoubleResponseBuilder <: ResponseBuilder<?(String, (String, Float64))> {
public func build(message: RedisMessage): ?(String, (String, Float64)) {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
if (message.isNull()) {
return None
}
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 3) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 3 but ${children.size}")
}
var key = ""
var bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
var value1 = ""
bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(1),
RedisMessageType.BULK_STRINGS
)
if (let Some(valueMessage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- valueMessage.getStringValue()) {
value1 = content
} else {
throw RedisException("Incompatible type, value1 is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
if (let Some(value) <- children.get(2)) {
if (let Some(value) <- (value as DoubleRedisMessage)) {
return (key, (value1, value.getValue()))
} else if (let Some(value) <- (value as BulkStringRedisMessage)) {
if (let Some(content) <- value.getStringValue()) {
return (key, (value1, Float64.parse(content)))
} else {
throw RedisException("Incompatible type, value1 is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS} or ${RedisMessageType.DOUBLES}, but ${bulkStringMessage.getType()}"
)
}
}
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class NillableTupleOfStringAndStringDoubleListResponseBuilder <: ResponseBuilder<?(String, ArrayList<(String,
Float64)>)> {
public func build(message: RedisMessage): ?(String, ArrayList<(String, Float64)>) {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
if (message.isNull()) {
return None
}
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let arrayMessage = ResponseBuilderHelper.getRedisMessageOrThrow(children.get(1), RedisMessageType.ARRAYS
)
if (let Some(arrayMessage) <- (arrayMessage as ArraysRedisMessage)) {
let results = ResponseBuilderFactory.listOfStringDoubleTupleBuilder.build(arrayMessage)
return (key, results)
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.ARRAYS}, but ${bulkStringMessage.getType()}"
)
}
}
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class TupleOfStringAndStringPairListResponseBuilder <: ResponseBuilder<(String, ArrayList<(String, String)>)> {
public func build(message: RedisMessage): (String, ArrayList<(String, String)>) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let arrayMessage = ResponseBuilderHelper.getRedisMessageOrThrow(children.get(1), RedisMessageType.ARRAYS
)
if (let Some(arrayMessage) <- (arrayMessage as ArraysRedisMessage)) {
let results = ResponseBuilderFactory.listOfStringTupleBuilder.build(arrayMessage)
return (key, results)
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.ARRAYS}, but ${bulkStringMessage.getType()}"
)
}
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class NillableIntegerDoubleTupleResponseBuilder <: ResponseBuilder<?(Int64, Float64)> {
public func build(message: RedisMessage): ?(Int64, Float64) {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
if (message.isNull()) {
return None
}
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size == 0) {
return None
}
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = 0
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.INTEGERS
)
if (let Some(keyMesage) <- (bulkStringMessage as IntegerRedisMessage)) {
key = keyMesage.getValue()
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.INTEGERS}, but ${bulkStringMessage.getType()}"
)
}
let valueDoubleMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(1),
RedisMessageType.DOUBLES
)
if (let Some(valueMessage) <- (valueDoubleMessage as DoubleRedisMessage)) {
return (key, valueMessage.getValue())
} else if (let Some(valueMessage) <- (valueDoubleMessage as BulkStringRedisMessage)) {
if (let Some(value) <- valueMessage.getStringValue()) {
return (key, Float64.parse(value))
} else {
throw RedisException("Incompatible type, nil double message")
}
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.DOUBLES}, but ${valueDoubleMessage.getType()}"
)
}
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class NillableStringDoubleTupleResponseBuilder <: ResponseBuilder<?(String, Float64)> {
public func build(message: RedisMessage): ?(String, Float64) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
if (message.isNull()) {
return None
}
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size == 0) {
return None
}
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let valueDoubleMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(1),
RedisMessageType.DOUBLES
)
if (let Some(valueMessage) <- (valueDoubleMessage as DoubleRedisMessage)) {
return (key, valueMessage.getValue())
} else if (let Some(valueMessage) <- (valueDoubleMessage as BulkStringRedisMessage)) {
if (let Some(value) <- valueMessage.getStringValue()) {
return (key, Float64.parse(value))
} else {
throw RedisException("Incompatible type, nil double message")
}
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.DOUBLES}, but ${valueDoubleMessage.getType()}"
)
}
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class StringDoubleTupleResponseBuilder <: ResponseBuilder<(String, Float64)> {
public func build(message: RedisMessage): (String, Float64) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
let valueDoubleMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(1),
RedisMessageType.DOUBLES
)
if (let Some(valueMessage) <- (valueDoubleMessage as DoubleRedisMessage)) {
return (key, valueMessage.getValue())
} else if (let Some(valueMessage) <- (valueDoubleMessage as BulkStringRedisMessage)) {
if (let Some(value) <- valueMessage.getStringValue()) {
return (key, Float64.parse(value))
} else {
throw RedisException("Incompatible type, nil double message")
}
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.DOUBLES}, but ${valueDoubleMessage.getType()}"
)
}
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class NillableStringTupleResponseBuilder <: ResponseBuilder<?(String, String)> {
public func build(message: RedisMessage): ?(String, String) {
if (let Some(message) <- (message as NullRedisMessage)) {
return None
}
if (let Some(message) <- (message as ArraysRedisMessage)) {
if (message.isNull()) {
return None
}
return ResponseBuilderFactory.stringTupleBuilder.build(message)
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class StringTupleResponseBuilder <: ResponseBuilder<(String, String)> {
public func build(message: RedisMessage): (String, String) {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size != 2) {
throw RedisException(
"Incompatible type, wrong size of ArraysRedisMessage, expect 2 but ${children.size}")
}
var key = ""
let bulkStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(0),
RedisMessageType.BULK_STRINGS
)
if (let Some(keyMesage) <- (bulkStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- keyMesage.getStringValue()) {
key = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected first message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
var value = ""
let valueStringMessage = ResponseBuilderHelper.getRedisMessageOrThrow(
children.get(1),
RedisMessageType.BULK_STRINGS
)
if (let Some(valueMessage) <- (valueStringMessage as BulkStringRedisMessage)) {
if (let Some(content) <- valueMessage.getStringValue()) {
value = content
} else {
throw RedisException("Incompatible type, key is nil")
}
} else {
throw RedisException(
"Incompatible type, expected second message's type: ${RedisMessageType.BULK_STRINGS}, but ${bulkStringMessage.getType()}"
)
}
return (key, value)
}
throw RedisException("Incompatible type, null arrays is not the expect type")
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, ${message.getType()} is not the expect type")
}
}
public class ListOfStringTupleResponseBuilder <: ResponseBuilder<ArrayList<(String, String)>> {
public func build(message: RedisMessage): ArrayList<(String, String)> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<(String, String)>()
if (message.isNull() || message.getSize() == 0) {
return results
}
let children = message.getValue()
if (let Some(children) <- children) {
if (ResponseBuilderHelper.isArraysFirstElement(children)) {
// RESP 3
for (child in children) {
let (x, y) = ResponseBuilderFactory.stringTupleBuilder.build(child)
results.add((x, y))
}
} else {
// RESP 2
var index = 0
while (index + 1 < children.size) {
let keyMessage = children[index]
let valueMessage = children[index + 1]
let key = ResponseBuilderHelper.unwrapToSimpleType<String>(keyMessage)
let value = ResponseBuilderHelper.unwrapToSimpleType<String>(valueMessage)
results.add((key, value))
index = index + 2
}
}
}
return results
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class ListOfStringDoubleTupleResponseBuilder <: ResponseBuilder<ArrayList<(String, Float64)>> {
public func build(message: RedisMessage): ArrayList<(String, Float64)> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let results = ArrayList<(String, Float64)>()
if (message.isNull() || message.getSize() == 0) {
return results
}
let children = message.getValue()
if (let Some(children) <- children) {
if (ResponseBuilderHelper.isArraysFirstElement(children)) {
// RESP 3
for (child in children) {
let (x, y) = ResponseBuilderFactory.stringDoubleTupleBuilder.build(child)
results.add((x, y))
}
} else {
// RESP 2
// Redis 6.0的返回值,Resp3缺少List,也会进入
var index = 0
while (index + 1 < children.size) {
let keyMessage = children[index]
let valueMessage = children[index + 1]
let key = ResponseBuilderHelper.unwrapToSimpleType<String>(keyMessage)
let value = ResponseBuilderHelper.unwrapToSimpleType<Float64>(valueMessage)
results.add((key, value))
index = index + 2
}
}
}
return results
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Unsupported message type: ${message.getType()}")
}
}
public class PrimitiveMapResponseBuilder<V> <: ResponseBuilder<HashMap<String, V>> {
public func build(message: RedisMessage): HashMap<String, V> {
let results = HashMap<String, V>()
let keyValues = ResponseBuilderFactory.listOfKeyValueBuilder.build(message)
processEntries(keyValues, results)
return results
}
protected static func processEntries(children: ArrayList<KeyValueMessagePair>, results: HashMap<String, V>) {
for (keyValue in children) {
let keyMessage = keyValue.getKey()
let valueMessage = keyValue.getValue()
let key = ResponseBuilderFactory.stringBuilder.build(keyMessage)
let value = unwrapValue(valueMessage)
results.add(key, value)
}
}
private static func unwrapValue(valueMessage: RedisMessage): V {
if (!valueMessage.isCollection()) {
let unwrapedValue = ResponseBuilderHelper.unwrapToSimpleType<V>(valueMessage)
return unwrapedValue
}
throw RedisException("Incompatible type, ${valueMessage.getType()} is not the expect type")
}
}
public class ListOfKeyValueResponseBuilder <: ResponseBuilder<ArrayList<KeyValueMessagePair>> {
public func build(message: RedisMessage): ArrayList<KeyValueMessagePair> {
if (let Some(message) <- (message as ArraysRedisMessage)) {
let keyValueMessages = ArrayList<KeyValueMessagePair>()
if (message.isNull() || message.getSize() == 0) {
return keyValueMessages
}
let children = message.getValue()
if (let Some(children) <- children) {
if (children.size % 2 != 0) {
throw RedisException(
"Incompatible type, could not convert to map from list which has odd number entries")
}
var index = 0
while (index + 1 < children.size) {
let keyMessage = children[index]
let valueMessage = children[index + 1]
let keyValueMessage = KeyValueMessagePair(keyMessage, valueMessage)
keyValueMessages.add(keyValueMessage)
index = index + 2
}
}
return keyValueMessages
} else if (let Some(mapMessage) <- (message as MapRedisMessage)) {
return mapMessage.getValue()
} else if (let Some(message) <- (message as ErrorRedisMessage)) {
throw RedisException(message.getValue())
}
throw RedisException("Incompatible type, could not convert ${message.getType()} to map")
}
}
public class ResponseBuilderFactory {
public static let stringBuilder = StringResponseBuilder()
public static let objectBuilder = AggressiveObjectObjectBuilder()
public static let byteArrayBuilder = ByteArrayResponseBuilder()
public static let nillableStringBuilder = NillableStringResponseBuilder()
public static let nillableByteArrayBuilder = NillableByteArrayResponseBuilder()
public static let integerBuilder = IntegerResponseBuilder()
public static let nillableIntegerBuilder = NillableIntegerResponseBuilder()
public static let nillableDoubleBuilder = NillableDoubleResponseBuilder()
public static let doubleBuilder = DoubleResponseBuilder()
public static let boolBuilder = BoolResponseBuilder()
public static let arrayOfNillableStringBuilder = ArrayOfNillableResponseBuilder<String>()
public static let setOfStringBuilder = SetOfResponseBuilder<String>()
public static let listOfStringBuilder = ListResponseBuilder<String>()
public static let listOfIntegerBuilder = ListResponseBuilder<Int64>()
public static let listOfDoubleBuilder = ListResponseBuilder<Float64>()
public static let listOfBoolBuilder = ListOfBoolBuilder()
public static let nillableListOfIntegerBuilder = NillableListResponseBuilder<Int64>()
public static let nillableListOfStringBuilder = NillableListResponseBuilder<String>()
public static let listOfNillableStringBuilder = ListOfNillableResponseBuilder<String>()
public static let listOfNillableIntegerBuilder = ListOfNillableResponseBuilder<Int64>()
public static let listOfNillableDoubleBuilder = ListOfNillableResponseBuilder<Float64>()
public static let tupleOfStringAndListResponseBuilder = TupleOfStringAndListResponseBuilder<String>()
public static let tupleOfStringAndTupleListResponseBuilder = TupleOfStringAndTupleListResponseBuilder()
public static let nillableTupleOfStringAndListResponseBuilder = NillableTupleOfStringAndListResponseBuilder<String>(
)
public static let tupleOfStringAndStringPairListBuilder = TupleOfStringAndStringPairListResponseBuilder()
public static let nillableTupleOfStringAndStringDoubleListBuilder = NillableTupleOfStringAndStringDoubleListResponseBuilder(
)
public static let nillableTupleOfStringAndStringDoubleBuilder = NillableTupleOfStringAndStringDoubleResponseBuilder(
)
public static let stringTupleBuilder = StringTupleResponseBuilder()
public static let nillableStringTupleBuilder = NillableStringTupleResponseBuilder()
public static let stringDoubleTupleBuilder = StringDoubleTupleResponseBuilder()
public static let nillableStringDoubleTupleBuilder = NillableStringDoubleTupleResponseBuilder()
public static let nillableIntegerDoubleTupleBuilder = NillableIntegerDoubleTupleResponseBuilder()
public static let listOfStringTupleBuilder = ListOfStringTupleResponseBuilder()
public static let listOfStringDoubleTupleBuilder = ListOfStringDoubleTupleResponseBuilder()
public static let stringToStringMapBuilder = PrimitiveMapResponseBuilder<String>()
public static let stringToIntegerMapBuilder = PrimitiveMapResponseBuilder<Int64>()
public static let listOfKeyValueBuilder = ListOfKeyValueResponseBuilder()
public static let listOfAnyBuilder = ListOfAnyResponseBuilder()
public static let mapOfAnyBuilder = MapOfAnyResponseBuilder()
public static let mapOfNillableAnyBuilder = MapOfNillableAnyResponseBuilder()
public static let jsonRespBuilder = JsonRespBuilder()
}