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

top.netkit.redis.client.executor.RedisCommandClient Maven / Gradle / Ivy

The newest version!
package top.netkit.redis.client.executor;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.ArrayType;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import org.redisson.api.*;
import org.redisson.api.listener.MessageListener;
import org.redisson.api.listener.PatternMessageListener;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.ScoredEntry;
import org.redisson.codec.TypedJsonJacksonCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.netkit.redis.client.codec.ObjectMapperCodec;
import top.netkit.redis.client.util.JacksonUtil;


import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Redis command client
 * @author shixinke
 */
public class RedisCommandClient implements RedisCommandExecutor {

    private static final Logger logger = LoggerFactory.getLogger(RedisCommandClient.class);


    /**
     * redisson client
     */
    private final RedissonClient redissonClient;


    public RedisCommandClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }


    private Codec codec;

    private static final Codec DEFAULT_CODEC = new ObjectMapperCodec();

    @Override
    public boolean del(String key) {
        try {
            return redissonClient.getBucket(key).delete();
        } catch (Exception ex) {
            logger.error("del exception, key={}", key, ex);
            return false;
        }

    }

    @Override
    public boolean del(Collection keys) {
        try {
            String[] members = new String[keys.size()];
            keys.toArray(members);
            long affected = redissonClient.getKeys().delete(members);
            return affected > 0;
        } catch (Exception ex) {
            logger.error("del exception, keys={}", keys, ex);
            return false;
        }
    }

    @Override
    public boolean exists(String key) {
        try {
            return redissonClient.getBucket(key).isExists();
        } catch (Exception ex) {
            logger.error("exists exception, key={}", key, ex);
            return false;
        }

    }

    @Override
    public boolean expire(String key, Long seconds) {
        try {
            return redissonClient.getBucket(key).expire(seconds, TimeUnit.SECONDS);
        } catch (Exception ex) {
            logger.error("expire exception, key={}", key, ex);
            return false;
        }

    }

    @Override
    public boolean expireAt(String key, Integer timestamp) {
        try {
            return redissonClient.getBucket(key).expire(Instant.ofEpochSecond(timestamp));
        } catch (Exception ex) {
            logger.error("expireAt exception, key={}", key, ex);
        }
        return false;

    }

    @Override
    public boolean pExpire(String key, Long mills) {
        try {
            return redissonClient.getBucket(key).expire(mills, TimeUnit.MILLISECONDS);
        } catch (Exception ex) {
            logger.error("exists exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public boolean pExpireAt(String key, Long timestampMills) {
        try {
            return redissonClient.getBucket(key).expire(Instant.ofEpochMilli(timestampMills));
        } catch (Exception ex) {
            logger.error("pExpireAt exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public Long ttl(String key) {
        try {
            long mills = redissonClient.getBucket(key, getCodec()).remainTimeToLive();
            return mills / 1000;
        } catch (Exception ex) {
            logger.error("ttl exception, key={}", key, ex);
        }
        return 0L;
    }

    @Override
    public Long pTtl(String key) {
        try {
            return redissonClient.getBucket(key).remainTimeToLive();
        } catch (Exception ex) {
            logger.error("pTtl exception, key={}", key, ex);
        }
        return 0L;
    }

    @Override
    public boolean persist(String key) {
        try {
            return redissonClient.getBucket(key).clearExpire();
        } catch (Exception ex) {
            logger.error("persist exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public boolean rename(String originalKey, String newKey) {
        try {
            redissonClient.getBucket(originalKey).rename(newKey);
        } catch (Exception ex) {
            logger.error("rename exception, originalKey={}, newKey={}", originalKey, newKey, ex);
        }

        return exists(newKey);
    }

    @Override
    public boolean renameNx(String originalKey, String newKey) {
        try {
            return redissonClient.getBucket(originalKey).renamenx(newKey);
        } catch (Exception ex) {
            logger.error("renameNx exception, originalKey={}, newKey={}", originalKey, newKey, ex);
        }
        return false;

    }

    @Override
    public String randomKey() {
        try {
            return redissonClient.getKeys().randomKey();
        } catch (Exception ex) {
            logger.error("randomKey exception", ex);
        }
        return null;
    }

    @Override
    public String type(String key) {
        try {
            RType type = redissonClient.getKeys().getType(key);
            if (type != null) {
                return type.toString();
            }
        } catch (Exception ex) {
            logger.error("type exception, key={}", key, ex);
        }

        return null;
    }

    @Override
    public Iterable keys(String pattern) {
        try {
            return redissonClient.getKeys().getKeysByPattern(pattern);
        } catch (Exception ex) {
            logger.error("keys exception:pattern={}", pattern, ex);
            return new ArrayList<>(0);
        }

    }

    @Override
    public boolean append(String key, String value) {
        try {
            redissonClient.getBinaryStream(key).getOutputStream().write(value.getBytes());
            return true;
        } catch (Exception ex) {
            logger.error("append exception:key={}", key, ex);
        }
        return false;
    }


    @Override
    public long bitCount(String key) {
        try {
            return redissonClient.getBitSet(key).cardinality();
        } catch (Exception ex) {
            logger.error("bitCount exception,key={}", key, ex);
            return 0L;
        }
    }

    @Override
    public void bitOp(String destKey, String operation, String...keys) {
        if (operation == null || operation.length() < 1) {
            return;
        }
        operation = operation.toLowerCase();
        switch (operation) {
            case "and":
                and(destKey, keys);
                break;
            case "or":
                or(destKey, keys);
                break;
            case "not":
                not(destKey);
                break;
            case "xor":
                xor(destKey, keys);
                break;
            default:
                break;
        }
    }

    @Override
    public void and(String destKey, String...keys) {
        redissonClient.getBitSet(destKey).and(keys);
    }

    @Override
    public void or(String destKey, String...keys) {
        redissonClient.getBitSet(destKey).or(keys);
    }

    @Override
    public void not(String descKey) {
        redissonClient.getBitSet(descKey).not();
    }

    @Override
    public void xor(String destKey, String... keys) {
        redissonClient.getBitSet(destKey).xor(keys);
    }


    @Override
    public  boolean set(String key, V value) {
        return set(key, value, null);
    }

    @Override
    public  boolean set(String key, V value, Long expireSeconds) {
        try {
            if (expireSeconds == null) {
                redissonClient.getBucket(key, getCodec(value.getClass())).set(value);
            } else {
                redissonClient.getBucket(key, getCodec(value.getClass())).set(value, expireSeconds, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception ex) {
            logger.error("set exception,key={}", key, ex);
            return false;
        }

    }

    @Override
    public  boolean setEx(String key, V value, Long expireSeconds) {
        try {
            redissonClient.getBucket(key, getCodec(value.getClass())).set(value, expireSeconds, TimeUnit.SECONDS);
            return true;
        } catch (Exception ex) {
            logger.error("setEx exception,key={}", key, ex);
            return false;
        }

    }

    @Override
    public  boolean pSetEx(String key, V value, Long expireMills) {
        try {
            redissonClient.getBucket(key, getCodec(value.getClass())).set(value, expireMills, TimeUnit.MILLISECONDS);
            return true;
        } catch (Exception ex) {
            logger.error("pSetEx exception, key={}",  key, ex);
            return false;
        }
    }

    @Override
    public  boolean setNx(String key, V value) {
        try {
            return redissonClient.getBucket(key, getCodec(value.getClass())).trySet(value);
        } catch (Exception ex) {
            logger.error("setNx exception, key={}",  key, ex);
            return false;
        }
    }

    @Override
    public String get(String key) {
        return get(key, String.class);
    }

    @Override
    public  V get(String key, Class clazz) {
        try {
            Object value =  redissonClient.getBucket(key, getCodec(clazz)).get();
            return JacksonUtil.toJavaObject(value, clazz);
        } catch (Exception ex) {
            logger.error("get exception, key={}",  key, ex);
            return null;
        }
    }

    @Override
    public  V get(String key, TypeReference typeReference) {
        try {
            Object value =  redissonClient.getBucket(key, getCodec(typeReference)).get();
            return JacksonUtil.toTypeReference(value, typeReference);
        } catch (Exception ex) {
            logger.error("get exception, key={}",  key, ex);
            return null;
        }

    }

    @Override
    public  V getSet(String key, V value, Class clazz) {
        try {
            Object data =  redissonClient.getBucket(key, getCodec(clazz)).getAndSet(value);
            return JacksonUtil.toJavaObject(data, clazz);
        } catch (Exception ex) {
            logger.error("getSet exception, key={}",  key, ex);
        }
        return null;
    }

    @Override
    public Long incr(String key) {
        try {
            return redissonClient.getAtomicLong(key).incrementAndGet();
        } catch (Exception ex) {
            logger.error("incr exception, key={}",  key, ex);
        }
        return 0L;
    }

    @Override
    public Long incrBy(String key, int step) {
        try {
            return redissonClient.getAtomicLong(key).addAndGet(step);
        } catch (Exception ex) {
            logger.error("incr exception, key={}",  key, ex);
        }
        return 0L;
    }

    @Override
    public double incrByFloat(String key, float step) {
        try {
            return redissonClient.getAtomicDouble(key).addAndGet(step);
        } catch (Exception ex) {
            logger.error("incrByFloat exception, key={}",  key, ex);
        }
        return 0;
    }

    @Override
    public Long decr(String key) {
        try {
            return redissonClient.getAtomicLong(key).decrementAndGet();
        } catch (Exception ex) {
            logger.error("decr exception, key={}",  key, ex);
        }
        return 0L;
    }

    @Override
    public Long decrBy(String key, int step) {
        if (step == 1) {
            return decr(key);
        }
        long originalValue = redissonClient.getAtomicLong(key).get();
        long updateValue = originalValue - step;

        try {
            redissonClient.getAtomicLong(key).compareAndSet(originalValue, updateValue);
            return updateValue;
        } catch (Exception ex) {
            logger.error("decrBy exception, key={}",  key, ex);
        }
        return 0L;
    }

    @Override
    public  Map mGet(List keys, Class clazz) {
        String[] keysArr = new String[keys.size()];
        keys.toArray(keysArr);
        try {
            return redissonClient.getBuckets(getCodec(clazz)).get(keysArr);
        } catch (Exception ex) {
            logger.error("mGet exception, keys={}",  keys, ex);
            return new HashMap<>(0);
        }

    }

    @Override
    public  Map mGet(List keys, TypeReference typeReference) {
        String[] keysArr = listToArray(keys);
        try {
            return redissonClient.getBuckets(getCodec(typeReference)).get(keysArr);
        } catch (Exception ex) {
            logger.error("mGet exception, keys={}",  keys, ex);
            return new HashMap<>(0);
        }

    }

    @Override
    public  boolean mSet(Map valueMap) {
        if (valueMap == null || valueMap.isEmpty()) {
            return false;
        }
        List values = new ArrayList<>(valueMap.values());
        V v = values.get(0);
        try {
            redissonClient.getBuckets(getCodec(v.getClass())).set(valueMap);
            return true;
        } catch (Exception ex) {
            logger.error("mSe exception",  ex);
            return false;
        }

    }

    @Override
    public  boolean mSetEx(Map valueMap, Long expire) {
        boolean result = mSet(valueMap);
        if (result) {
            for (String key : valueMap.keySet()) {
                expire(key, expire);
            }
        }
        return true;
    }

    @Override
    public  boolean mSetNx(Map valueMap) {
        try {
            if (valueMap == null || valueMap.isEmpty()) {
                return false;
            }
            List values = new ArrayList<>(valueMap.values());
            V v = values.get(0);
            redissonClient.getBuckets(getCodec(v.getClass())).trySet(valueMap);
            return true;
        } catch (Exception ex) {
            logger.error("mSetNx exception",  ex);
        }
        return false;
    }

    @Override
    public boolean setRange(String key, int offset, String value) {
        try {
            String originalValue = get(key, String.class);
            if (originalValue == null || originalValue.length() < offset) {
                return false;
            }
            String newValue = originalValue.substring(0, offset) + value;
            return redissonClient.getBucket(key, getCodec()).compareAndSet(originalValue, newValue);
        } catch (Exception ex) {
            logger.error("setRange exception:key={};", key, ex);
        }
        return false;
    }

    @Override
    public Long strLen(String key) {
        try {
            return redissonClient.getBucket(key, getCodec()).size();
        } catch (Exception ex) {
            logger.error("strLen exception:key={};", key, ex);
        }
        return 0L;
    }

    @Override
    public boolean hDel(String key, List fields) {
        try {
            long affected = redissonClient.getMap(key).fastRemove(fields.toArray());
            return affected > 0;
        } catch (Exception ex) {
            logger.error("hDel exception:key={};", key, ex);
        }
        return false;
    }

    @Override
    public boolean hDel(String key, String field) {
        try {
            long affected = redissonClient.getMap(key).fastRemove(field);
            return affected > 0;
        } catch (Exception ex) {
            logger.error("hDel exception:key={};", key, ex);
        }
        return false;
    }

    @Override
    public boolean hExists(String key, String field) {
        try {
            return redissonClient.getMap(key).containsKey(field);
        } catch (Exception ex) {
            logger.error("hExists exception:key={};", key, ex);
        }
        return false;
    }

    @Override
    public  V hGet(String key, String field, Class clazz) {
        try {
            return JacksonUtil.toJavaObject(redissonClient.getMap(key, getCodec(clazz)).get(field), clazz);
        } catch (Exception ex) {
            logger.error("hGet exception:key={};", key, ex);
        }
        return null;
    }

    @Override
    public  V hGet(String key, String field, TypeReference typeReference) {
        try {
            return JacksonUtil.toTypeReference(redissonClient.getMap(key, getCodec(typeReference)).get(field), typeReference);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public  Map hGetAll(String key, Class clazz) {
        try {
            Map dataMap = redissonClient.getMap(key, getCodec(clazz)).readAllMap();
            if (dataMap == null || dataMap.isEmpty()) {
                return new HashMap<>(0);
            }
            Map cacheMap = new HashMap<>(100);
            for (Map.Entry entry : dataMap.entrySet()) {
                cacheMap.put(String.valueOf(entry.getKey()), JacksonUtil.toJavaObject(entry.getValue(), clazz));
            }
            return cacheMap;
        } catch (Exception ex) {
            logger.error("hGetAll exception:key={};", key, ex);
        }
        return null;
    }

    @Override
    public long hIncr(String key, String field, int step) {
        try {
            return (long)redissonClient.getMap(key).addAndGet(field, step);
        } catch (Exception ex) {
            logger.error("hIncr exception:key={};", key, ex);
        }
        return 0;
    }

    @Override
    public double hIncrByFloat(String key, String field, double step) {
        try {
            return (double) redissonClient.getMap(key).addAndGet(field, step);
        } catch (Exception ex) {
            logger.error("hIncrByFloat exception:key={};", key, ex);
        }
        return 0d;
    }

    @Override
    public List hKeys(String key) {
        try {
            Set keys = redissonClient.getMap(key).readAllKeySet();
            List fields = new ArrayList<>(keys.size());
            for (Object k : keys) {
                fields.add(String.valueOf(k));
            }
            return fields;
        } catch (Exception ex) {
            logger.error("hKeys exception:key={};", key, ex);
        }
        return new ArrayList<>(0);
    }

    @Override
    public long hLen(String key) {
        try {
            return redissonClient.getMap(key).size();
        } catch (Exception ex) {
            logger.error("hLen exception:key={};", key, ex);
        }
        return 0;
    }

    @Override
    public  Map hMGet(String key, List fields, Class clazz) {
        try {
            Map dataMap = redissonClient.getMap(key, getCodec(clazz)).getAll(new HashSet<>(fields));
            if (dataMap == null || dataMap.isEmpty()) {
                return new HashMap<>(0);
            }
            Map cacheMap = new HashMap<>(fields.size());
            for (Map.Entry entry : dataMap.entrySet()) {
                cacheMap.put(String.valueOf(entry.getKey()), JacksonUtil.toJavaObject(entry.getValue(), clazz));
            }
            return cacheMap;
        } catch (Exception ex) {
            logger.error("hMGet exception, key{}", key, ex);
        }

        return null;
    }

    @Override
    public  boolean hMSet(String key, Map values) {
        if (values == null || values.isEmpty()) {
            return false;
        }
        try {
            List valueList = new ArrayList<>(values.values());
            redissonClient.getMap(key, getCodec(valueList.get(0).getClass())).putAll(values);
        } catch (Exception ex) {
            logger.error("hMSet exception:key={}", key, ex);
            return false;
        }

        return true;
    }

    @Override
    public  boolean hSet(String key, String field, V value) {
        if (value == null) {
            return false;
        }
        try {
            redissonClient.getMap(key, getCodec(value.getClass())).put(field, value);
        } catch (Exception ex) {
            logger.error("hSet exception:key={};field={}", key, field, ex);
            return false;
        }
        return true;

    }

    @Override
    public  boolean hSetNx(String key, String field, V value) {
        if (value == null) {
            return false;
        }
        try {
            return redissonClient.getMap(key, getCodec(value.getClass())).fastPutIfAbsent(field, value);
        } catch (Exception ex) {
            logger.error("hSetNx exception:key={},field={}", key, field, ex);
        }
        return false;
    }

    @Override
    public long hStrLen(String key, String field) {
        try {
            return redissonClient.getMap(key).valueSize(field);
        } catch (Exception ex) {
            logger.error("hStrLen exception:key={},field={}", key, field, ex);
        }
        return 0;
    }

    @Override
    public  List hVals(String key, Class clazz) {
        try {
            List dataList = new ArrayList<>(redissonClient.getMap(key, getCodec(clazz)).readAllValues());
            if (dataList.isEmpty()) {
                return new ArrayList<>(0);
            }
            List values = new ArrayList<>(100);
            for (Object v : dataList) {
                values.add(JacksonUtil.toJavaObject(v, clazz));
            }
            return values;
        } catch (Exception ex) {
            logger.error("hVals exception:", ex);
        }
        return new ArrayList<>(0);
    }


    @Override
    public  V blPop(String key, Long timeout, Class clazz) {
        try {
           Object value = redissonClient.getBlockingQueue(key, getCodec(clazz)).poll(timeout, TimeUnit.SECONDS);
           return JacksonUtil.toJavaObject(value, clazz);
        } catch (InterruptedException e) {
            logger.error("blPop exception:key={}", key, e);
        }
        return null;
    }

    @Override
    public  List blPop(List keys, Long timeout, Class clazz) {
        try {
            RBatch batch = redissonClient.createBatch();
            for (String key : keys) {
                batch.getBlockingDeque(key, getCodec(clazz)).pollFirstAsync(timeout, TimeUnit.MILLISECONDS);
            }
            BatchResult result = batch.execute();
            return toList(result, clazz);
        } catch (Exception ex) {
            logger.error("brPop, key={}", keys, ex);
        }
        return null;
    }

    @Override
    public  V brPop(String key, Long timeout, Class clazz) {
        try {
            return JacksonUtil.toJavaObject(redissonClient.getBlockingQueue(key, getCodec(clazz)).pollLastAndOfferFirstToAsync(key, timeout, TimeUnit.SECONDS), clazz);
        } catch (Exception ex) {
            logger.error("brPop, key={}", key, ex);
        }
        return null;
    }

    @Override
    public  List brPop(List keys, Long timeout, Class clazz) {
        try {
            RBatch batch = redissonClient.createBatch();
            for (String key : keys) {
                batch.getBlockingQueue(key,getCodec(clazz)).pollAsync(timeout, TimeUnit.MILLISECONDS);
            }
            BatchResult result = batch.execute();
            return toList(result, clazz);
        } catch (Exception ex) {
            logger.error("brPop, key={}", keys, ex);
        }
        return null;
    }

    @Override
    public  V brPopLPush(String sourceKey, String destKey, Class clazz) {
        try {
            RFuture future = redissonClient.getBlockingQueue(sourceKey, getCodec(clazz)).pollLastAndOfferFirstToAsync(destKey);
            if (future != null ) {
                return JacksonUtil.toJavaObject(future.getNow(), clazz);
            }
        } catch (Exception ex) {
            logger.error("brPopLPush exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  V lIndex(String key, int index, Class clazz) {
        try {
            return JacksonUtil.toJavaObject(redissonClient.getList(key, getCodec(clazz)).get(index), clazz);
        } catch (Exception ex) {
            logger.error("lIndex exception, key={}", key, ex);
        }
        return null;
    }


    @Override
    public  boolean lInsertBefore(String key, V pivot, List values) {
        if (values == null || values.isEmpty()) {
            return false;
        }
        V v = values.get(0);

        try {
            if (values.size() == 1) {
                int index = redissonClient.getList(key, getCodec(v.getClass())).addBefore(pivot, values.get(0));
                return index >= 0;
            } else {
                int pos = redissonClient.getList(key, getCodec(v.getClass())).indexOf(pivot);
                if (pos >= 0) {
                    return redissonClient.getList(key, getCodec(v.getClass())).addAll(pos, values);
                } else {
                    return redissonClient.getList(key, getCodec(v.getClass())).addAll(values);
                }
            }
        } catch (Exception ex) {
            logger.error("lInsertBefore exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean lInsertAfter(String key, V pivot, List values) {
        if (values == null || values.isEmpty()) {
            return false;
        }
        V v = values.get(0);
        try {
            if (values.size() == 1) {
                int index = redissonClient.getList(key, getCodec(v.getClass())).addAfter(pivot, values.get(0));
                return index >= 0;
            } else {
                int pos = redissonClient.getList(key, getCodec(v.getClass())).indexOf(pivot);
                if (pos >= 0) {
                    return redissonClient.getList(key, getCodec(v.getClass())).addAll(pos + 1, values);
                } else {
                    return redissonClient.getList(key, getCodec(v.getClass())).addAll(values);
                }
            }
        } catch (Exception ex) {
            logger.error("lInsertAfter exception, key={}", key, ex);
        }
        return false;

    }

    @Override
    public int lLen(String key) {
        try {
            return redissonClient.getList(key).size();
        } catch (Exception ex) {
            logger.error("lLen exception, key={}", key, ex);
        }
        return 0;
    }

    @Override
    public  V lPop(String key, Class clazz) {
        try {
            return JacksonUtil.toJavaObject(redissonClient.getQueue(key, getCodec(clazz)).poll(), clazz);
        } catch (Exception ex) {
            logger.error("lPop exception, key={}", key, ex);
        }
        return null;
    }

    @Override
    public  boolean lPush(String key, V value) {
        try {
            redissonClient.getDeque(key, getCodec(value.getClass())).addFirst(value);
            return true;
        } catch (Exception ex) {
            logger.error("lPush exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean lPush(String key, List values) {
        try {
            if (values == null || values.isEmpty()) {
                return false;
            }
            V v = values.get(0);
            return redissonClient.getList(key, getCodec(v.getClass())).addAll(0, values);
        } catch (Exception ex) {
            logger.error("lPush exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean lPushX(String key, V value) {
        RDeque queue = redissonClient.getDeque(key);
        if (queue.contains(value)) {
            queue.addFirst(value);
            return true;
        }
        return false;
    }

    @Override
    public  List lRange(String key, int start, int end, Class clazz) {
        try {
            List values = redissonClient.getList(key, getCodec(clazz)).range(start, end);
            return toList(values, clazz);
        } catch (Exception ex) {
            logger.error("lRange exception, key={}", key, ex);
        }
        return new ArrayList<>(0);
    }

    @Override
    public  boolean lRem(String key, V value, Integer count) {
        try {
            return redissonClient.getList(key, getCodec(value.getClass())).remove(value, count);
        } catch (Exception ex) {
            logger.error("lRem exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean lSet(String key, int index, V value) {
        try {
            Object result = redissonClient.getList(key, getCodec(value.getClass())).set(index, value);
            return result != null;
        } catch (Exception ex) {
            logger.error("lSet exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public boolean lTrim(String key, int start, int end) {
        try {
            redissonClient.getList(key).trim(start, end);
            return true;
        } catch (Exception ex) {
            logger.error("lTrim exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  V rPop(String key, Class clazz) {
        try {
            Object value = redissonClient.getDeque(key, getCodec(clazz)).pollLast();
            return JacksonUtil.toJavaObject(value, clazz);
        } catch (Exception ex) {
            logger.error("rPop exception, key={}", key, ex);
        }
        return null;
    }

    @Override
    public  V rPopLPush(String sourceKey, String destKey, Class clazz) {
        try {
            Object value = redissonClient.getDeque(sourceKey, getCodec(clazz)).pollLastAndOfferFirstTo(destKey);
            return JacksonUtil.toJavaObject(value, clazz);
        } catch (Exception ex) {
            logger.error("rPopLPush exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  boolean rPush(String key, V value) {
        try {
            return redissonClient.getList(key, getCodec(value.getClass())).add(value);
        } catch (Exception ex) {
            logger.error("sAdd exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean rPushX(String key, V value) {
        RDeque queue = redissonClient.getDeque(key);
        if (queue.contains(value)) {
            queue.addLast(value);
            return true;
        }
        return false;
    }

    @Override
    public  boolean sAdd(String key, V value) {
        try {
            return redissonClient.getSet(key, getCodec(value.getClass())).add(value);
        } catch (Exception ex) {
            logger.error("sAdd exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean sAdd(String key, List values) {
        if (values == null || values.isEmpty()) {
            return false;
        }
        V v = values.get(0);

        try {
            return redissonClient.getSet(key, getCodec(v.getClass())).addAll(values);
        } catch (Exception ex) {
            logger.error("sAdd exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public int sCard(String key) {
        try {
            return redissonClient.getSet(key).size();
        } catch (Exception ex) {
            logger.error("sCard exception, key={}", key, ex);
        }
        return 0;
    }

    @Override
    public  Set sDiff(String sourceKey, String destKey, Class clazz) {
        try {
            return toSet(redissonClient.getSet(sourceKey, getCodec(clazz)).readDiff(destKey), clazz);
        } catch (Exception ex) {
            logger.error("sDiff exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  Set sDiff(String sourceKey, List destKeys, Class clazz) {
        try {
            String[] keys = new String[destKeys.size()];
            destKeys.toArray(keys);
            return toSet(redissonClient.getSet(sourceKey, getCodec(clazz)).readDiff(keys), clazz);
        } catch (Exception ex) {
            logger.error("sDiffStore exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  boolean sDiffStore(String storeKey, String sourceKey, List destKeys, Class clazz) {
        try {
            Set values = sDiff(sourceKey, destKeys, clazz);
            return redissonClient.getSet(sourceKey, getCodec(clazz)).addAll(values);
        } catch (Exception ex) {
            logger.error("sDiffStore exception, key={}", sourceKey, ex);
        }
        return false;
    }

    @Override
    public  Set sInter(String sourceKey, String destKey, Class clazz) {
        try {
            return toSet(redissonClient.getSet(sourceKey, getCodec(clazz)).readIntersection(destKey), clazz);
        } catch (Exception ex) {
            logger.error("sInter exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  Set sInter(String sourceKey, List destKeys, Class clazz) {
        try {
            String[] keys = new String[destKeys.size()];
            destKeys.toArray(keys);
            return toSet(redissonClient.getSet(sourceKey, getCodec(clazz)).readIntersection(keys), clazz);
        } catch (Exception ex) {
            logger.error("sInter exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  boolean sInterStore(String storeKey, String sourceKey, List destKeys, Class clazz) {
        try {
            Set values = sInter(sourceKey, destKeys, clazz);
            return redissonClient.getSet(storeKey, getCodec(clazz)).addAll(values);
        } catch (Exception ex) {
            logger.error("sInterStore exception, key={}", sourceKey, ex);
        }
        return false;
    }

    @Override
    public  Set sUnion(String sourceKey, String destKey, Class clazz) {
        try {
            return toSet(redissonClient.getSet(sourceKey, getCodec(clazz)).readUnion(destKey), clazz);
        } catch (Exception ex) {
            logger.error("sUnion exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  Set sUnion(String sourceKey, List destKeys, Class clazz) {
        try {
            String[] keys = new String[destKeys.size()];
            destKeys.toArray(keys);
            return toSet(redissonClient.getSet(sourceKey, getCodec(clazz)).readUnion(keys), clazz);
        } catch (Exception ex) {
            logger.error("sUnion exception, key={}", sourceKey, ex);
        }
        return null;
    }

    @Override
    public  boolean sUnionStore(String storeKey, String sourceKey, List destKeys, Class clazz) {
        try {
            Set values = sUnion(sourceKey, destKeys, clazz);
            return redissonClient.getSet(storeKey, getCodec(clazz)).addAll(values);
        } catch (Exception ex) {
            logger.error("sUnionStore exception, key={}", sourceKey, ex);
        }
        return false;
    }

    @Override
    public  boolean sIsMember(String key, V member) {
        try {
            return redissonClient.getSet(key, getCodec(member.getClass())).contains(member);
        } catch (Exception ex) {
            logger.error("sIsMember exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  Set sMembers(String key, Class clazz) {
        try {
            return toSet(redissonClient.getSet(key, getCodec(clazz)).readAll(), clazz);
        } catch (Exception ex) {
            logger.error("sMembers exception, key={}", key, ex);
        }
        return null;
    }

    @Override
    public  boolean sMove(String sourceKey, String destKey, V value) {
        try {
            return redissonClient.getSet(sourceKey, getCodec(value.getClass())).move(destKey, value);
        } catch (Exception ex) {
            logger.error("sMove exception, sourceKey={}, destKey={}", sourceKey, destKey, ex);
        }
        return false;
    }

    @Override
    public  Set sPop(String key, Integer count, Class clazz) {
        try {
            return toSet(redissonClient.getSet(key, getCodec(clazz)).removeRandom(count), clazz);
        } catch (Exception ex) {
            logger.error("sPop exception, key={}", key, ex);
        }
        return null;
    }

    @Override
    public  boolean sRem(String key, V value) {
        try {
            return redissonClient.getSet(key, getCodec(value.getClass())).remove(value);
        } catch (Exception ex) {
            logger.error("sRem exception, key={}", key, ex);
        }
        return false;
    }

    @Override
    public  boolean sRem(String key, List values) {
        if (values == null || values.isEmpty()) {
            return false;
        }
        V v = values.get(0);
        try {
            return redissonClient.getSet(key, getCodec(v.getClass())).removeAll(values);
        } catch (Exception ex) {
            logger.error("sRem exception", ex);
        }
        return false;
    }

    @Override
    public  Set sRandomMember(String key, Integer count, Class clazz) {
        try {
            return toSet(redissonClient.getSet(key, getCodec(clazz)).random(count), clazz);
        } catch (Exception ex) {
            logger.error("sRandomMember exception", ex);
        }
        return null;
    }

    @Override
    public  boolean zAdd(String key, V member, Double score) {
        try {
            return redissonClient.getScoredSortedSet(key, getCodec(member.getClass())).add(score, member);
        } catch (Exception ex) {
            logger.error("zAdd exception", ex);
        }
        return false;
    }

    @Override
    public  boolean zAdd(String key, Map members) {
        if (members == null || members.isEmpty()) {
            return false;
        }
        List values = new ArrayList<>(members.keySet());
        V v = values.get(0);
        Map fields = new HashMap<>(members.size());
        for (Map.Entry entry : members.entrySet()) {
            fields.put(entry.getKey(), entry.getValue());
        }
        try {
            int affected = redissonClient.getScoredSortedSet(key, getCodec(v.getClass())).addAll(fields);
            return affected > 0;
        } catch (Exception ex) {
            logger.error("zAdd exception", ex);
        }
        return false;
    }

    @Override
    public int zCard(String key) {
        try {
            return redissonClient.getScoredSortedSet(key).size();
        } catch (Exception ex) {
            logger.error("zCard exception", ex);
        }
        return 0;
    }

    @Override
    public int zCount(String key, double min, double max) {
        try {
            return redissonClient.getScoredSortedSet(key).count(min, true, max, true);
        } catch (Exception ex) {
            logger.error("zCount exception", ex);
        }
        return 0;
    }

    @Override
    public  double zIncrBy(String key, V member, double step) {
        try {
            return redissonClient.getScoredSortedSet(key, getCodec(member.getClass())).addScore(member, step);
        } catch (Exception ex) {
            logger.error("zIncrBy exception", ex);
        }
        return 0d;
    }

    @Override
    public boolean zInterStore(String storeKey, String sourceKey, List destKeys) {
        destKeys.add(sourceKey);
        String[] keys = new String[destKeys.size()];
        destKeys.toArray(keys);
        int affected = redissonClient.getScoredSortedSet(storeKey).intersection(keys);
        return affected > 0;
    }

    @Override
    public long zLexCount(String key, String minMember, String maxMember) {
        return redissonClient.getLexSortedSet(key).count(maxMember, true, maxMember, true);
    }

    @Override
    public  List zRangeWithoutScore(String key, int start, int end, Class clazz) {
        try {
            Collection> values = redissonClient.getScoredSortedSet(key, getCodec(clazz)).entryRange(start, end);
            return parseMemberList(values, start, end, clazz);
        } catch (Exception ex) {
            logger.error("zRangeWithoutScore exception", ex);
        }
        return new ArrayList<>(0);
    }

    @Override
    public  List> zRange(String key, int start, int end, Class clazz) {
        try {
            Collection> values = redissonClient.getScoredSortedSet(key, getCodec(clazz)).entryRange(start, end);
            return parseScoredEntryList(values, start, end, clazz);
        } catch (Exception ex) {
            logger.error("zRange exception", ex);
        }
        return new ArrayList<>(0);
    }

    @Override
    public  Map zRangeByScore(String key, int start, int end, boolean withScores, Long offset, Long count, Class clazz) {
        List dataList = redissonClient.getScoredSortedSet(key).valueRange(start, end).stream().skip(offset).limit(count).collect(Collectors.toList());
        return buildEntryMap(dataList, start, end, clazz);
    }

    @Override
    public  List> zRevRange(String key, int start, int end, Class clazz) {
        try {
            Collection> values = redissonClient.getScoredSortedSet(key, getCodec(clazz)).entryRangeReversed(start, end);
            return parseScoredEntryList(values, start, end, clazz);
        } catch (Exception ex) {
            logger.error("zRevRange exception", ex);
        }
        return new ArrayList<>(0);
    }

    @Override
    public  List zRevRangeWithoutScore(String key, int start, int end, Class clazz) {
        try {
            Collection> values = redissonClient.getScoredSortedSet(key, getCodec(clazz)).entryRangeReversed(start, end);
            return parseMemberList(values, start, end, clazz);
        } catch (Exception ex) {
            logger.error("zRevRangeWithoutScore exception", ex);
        }
        return new ArrayList<>(0);
    }

    @Override
    public  Map zRevRangeByScore(String key, int start, int end, boolean withScores, Long offset, Long count, Class clazz) {
        List> dataList = redissonClient.getScoredSortedSet(key, getCodec(clazz)).entryRangeReversed(start, end).stream().skip(offset).limit(count).collect(Collectors.toList());
        return buildScoredEntryMap(dataList, start, end, clazz);
    }

    @Override
    public  Integer zRank(String key, V member) {
        try {
            return redissonClient.getScoredSortedSet(key, getCodec(member.getClass())).rank(member);
        } catch (Exception ex) {
            logger.error("zRank exception", ex);
        }
        return 0;
    }

    @Override
    public  Integer zRevRank(String key, V member) {
        try {
            return redissonClient.getScoredSortedSet(key, getCodec(member.getClass())).revRank(member);
        } catch (Exception ex) {
            logger.error("zRevRank exception", ex);
        }
        return 0;
    }

    @Override
    public  boolean zRem(String key, V member) {
        try {
            return redissonClient.getScoredSortedSet(key, getCodec(member.getClass())).remove(member);
        } catch (Exception ex) {
            logger.error("zRem exception", ex);
        }
        return false;
    }

    @Override
    public  boolean zRem(String key, List members) {
        try {
            if (members == null || members.isEmpty()) {
                return false;
            }
            V v = members.get(0);
            return redissonClient.getScoredSortedSet(key, getCodec(v.getClass())).removeAll(members);
        } catch (Exception ex) {
            logger.error("zRem exception", ex);
        }
        return false;
    }

    @Override
    public boolean zRemRangeByRank(String key, int start, int end) {
        try {
            int affected = redissonClient.getScoredSortedSet(key).removeRangeByRank(start, end);
            return affected > 0;
        } catch (Exception ex) {
            logger.error("zRemRangeByRank exception", ex);
        }
        return false;
    }

    @Override
    public boolean zRemRangeByScope(String key, double min, double max) {
        try {
            int affected = redissonClient.getScoredSortedSet(key).removeRangeByScore(min, true, max, true);
            return affected > 0;
        } catch (Exception ex) {
            logger.error("zRemRangeByScope exception", ex);
        }
        return false;
    }

    @Override
    public  Double zScore(String key, V member) {
        try {
            return redissonClient.getScoredSortedSet(key, getCodec(member.getClass())).getScore(member);
        } catch (Exception ex) {
            logger.error("zScore exception", ex);
        }
        return 0d;
    }

    @Override
    public boolean zUnionStore(String storeKey, String sourceKey, List destKeys) {
        List keys = new ArrayList<>(10);
        keys.add(sourceKey);
        if (destKeys != null) {
            keys.addAll(destKeys);
        }
        String[] keysArr = new String[keys.size()];
        keys.toArray(keysArr);
        int affected =  redissonClient.getScoredSortedSet(storeKey).union(keysArr);
        return affected > 0;
    }

    private  List> parseScoredEntryList(Collection> entryList, int start, int end, Class clazz) {
        int size = 10;
        if (end > 0) {
            size = end - start;
        }
        List> valueList = new ArrayList<>(size);
        for (ScoredEntry entry : entryList) {
            Map valueMap = new HashMap<>(1);
            valueMap.put(JacksonUtil.toJavaObject(entry.getValue(), clazz), entry.getScore());
            valueList.add(valueMap);
        }
        return valueList;
    }

    private  Map buildEntryMap(Collection entryList, int start, int end, Class clazz) {
        int size = 10;
        if (end > 0) {
            size = end - start;
        }
        Map valueMap = new HashMap<>(size);
        for (Object item : entryList) {
            if (!(item instanceof ScoredEntry)) {
                continue;
            }
            ScoredEntry entry = (ScoredEntry) item;
            valueMap.put(JacksonUtil.toJavaObject(entry.getValue(), clazz), entry.getScore());
        }
        return valueMap;
    }

    private  Map buildScoredEntryMap(Collection> entryList, int start, int end, Class clazz) {
        int size = 10;
        if (end > 0) {
            size = end - start;
        }
        Map valueMap = new HashMap<>(size);
        for (ScoredEntry entry : entryList) {
            valueMap.put(JacksonUtil.toJavaObject(entry.getValue(), clazz), entry.getScore());
        }
        return valueMap;
    }

    private  List parseMemberList(Collection> entryList, int start, int end, Class clazz) {
        int size = 10;
        if (end > 0) {
            size = end - start;
        }
        List memberList = new ArrayList<>(size);
        for (ScoredEntry entry : entryList) {
            memberList.add(JacksonUtil.toJavaObject(entry.getValue(), clazz));
        }
        return memberList;
    }

    @Override
    public boolean discard(RTransaction transaction) {
        try {
            if (transaction == null) {
                transaction = redissonClient.createTransaction(TransactionOptions.defaults());
            }
            transaction.rollback();
            return true;
        } catch (Exception ex) {
            logger.error("discard exception", ex);
        }
        return false;
    }


    @Override
    public boolean multi(ReturnableExecutor executor) {
        try {
            RBatch batch = redissonClient.createBatch();
            Boolean result = executor.execute(batch);
            if (result) {
                batch.execute();
            } else {
                batch.discardAsync();
            }
            return result;
        } catch (Exception ex) {
            logger.error("multi exception", ex);
        }
        return false;
    }

    @Override
    public boolean pipeline(ReturnableExecutor executor) {
        return multi(executor);
    }


    @Override
    public  void pSubscribe(String pattern, Class type, PatternMessageListener listener) {
        try {
            redissonClient.getPatternTopic(pattern, getCodec()).addListener(type, listener);
        } catch (Exception ex) {
            logger.error("pSubscribe exception", ex);
        }

    }

    @Override
    public  void pSubscribe(List patterns, List> types, List> listeners) {
        for (int i = 0; i < patterns.size(); i++) {
            try {
                redissonClient.getPatternTopic(patterns.get(i), getCodec()).addListener(types.get(i), listeners.get(i));
            } catch (Exception ex) {
                logger.error("pSubscribe exception", ex);
            }

        }
    }

    @Override
    public void pUnSubscribe(String pattern) {
        try {
            redissonClient.getPatternTopic(pattern, getCodec()).removeAllListeners();
        } catch (Exception ex) {
            logger.error("pUnSubscribe exception", ex);
        }

    }

    @Override
    public void pUnSubscribe(List patterns) {
        for (String pattern : patterns) {
            try {
                redissonClient.getPatternTopic(pattern, getCodec()).removeAllListeners();
            } catch (Exception ex) {
                logger.error("pUnSubscribe exception", ex);
            }
        }
    }

    @Override
    public  Long publish(String channel, V message) {
        try {
            return redissonClient.getTopic(channel, getCodec(message.getClass())).publish(message);
        } catch (Exception ex) {
            logger.error("publish exception", ex);
        }
        return null;
    }

    @Override
    public  void subscribe(String topic, Class clazz, MessageListener listener) {
        try {
            redissonClient.getTopic(topic, getCodec()).addListener(clazz, listener);
        } catch (Exception ex) {
            logger.error("subscribe exception", ex);
        }

    }

    @Override
    public  void subscribe(List topics, List> clazz, List> listeners) {
        for (int i = 0; i < topics.size(); i ++) {
            try {
                redissonClient.getTopic(topics.get(i), getCodec()).addListener(clazz.get(i), listeners.get(i));
            } catch (Exception ex) {
                logger.error("subscribe exception", ex);
            }

        }
    }

    @Override
    public void unsubscribe(String topic) {
        try {
            redissonClient.getTopic(topic, getCodec()).removeAllListeners();
        } catch (Exception ex) {
            logger.error("unsubscribe exception", ex);
        }

    }

    @Override
    public void unsubscribe(List topics) {
        for (String topic : topics) {
            try {
                redissonClient.getTopic(topic, getCodec()).removeAllListeners();
            } catch (Exception ex) {
                logger.error("unsubscribe exception", ex);
            }

        }
    }


    @Override
    public  V eval(String key, String script, boolean readonly, List keys, List args, Class clazz) {
        RScript.Mode mode = RScript.Mode.READ_WRITE;
        if (readonly) {
            mode = RScript.Mode.READ_ONLY;
        }
        return redissonClient.getScript(getCodec(clazz)).eval(key, mode, script, getReturnType(clazz), keys, args);
    }

    @Override
    public  V eval(String script, boolean readonly, List keys, List args, Class clazz) {
        RScript.Mode mode = RScript.Mode.READ_WRITE;
        if (readonly) {
            mode = RScript.Mode.READ_ONLY;
        }
        return redissonClient.getScript(getCodec(clazz)).eval(mode, script, getReturnType(clazz), keys, args);
    }

    @Override
    public  V eval(String script, boolean readonly, Class clazz) {
        RScript.Mode mode = RScript.Mode.READ_WRITE;
        if (readonly) {
            mode = RScript.Mode.READ_ONLY;
        }
        return redissonClient.getScript(getCodec(clazz)).eval(mode, script, getReturnType(clazz));
    }


    @Override
    public  V evalSha(String key, String script, boolean readonly, List keys, List args, Class clazz) {
        RScript.Mode mode = RScript.Mode.READ_WRITE;
        if (readonly) {
            mode = RScript.Mode.READ_ONLY;
        }
        return redissonClient.getScript(getCodec(clazz)).evalSha(key, mode, script, getReturnType(clazz), keys, args);
    }

    @Override
    public  V evalSha(String script, boolean readonly, List keys, List args, Class clazz) {
        RScript.Mode mode = RScript.Mode.READ_WRITE;
        if (readonly) {
            mode = RScript.Mode.READ_ONLY;
        }
        return redissonClient.getScript(getCodec(clazz)).evalSha(mode, script, getReturnType(clazz), keys, args);
    }

    @Override
    public  V evalSha(String script, boolean readonly, Class clazz) {
        RScript.Mode mode = RScript.Mode.READ_WRITE;
        if (readonly) {
            mode = RScript.Mode.READ_ONLY;
        }
        return redissonClient.getScript(getCodec(clazz)).evalSha(mode, script, getReturnType(clazz));
    }


    @Override
    public boolean scriptExists(String script) {
        try {
            List resultList = redissonClient.getScript().scriptExists(script);
            if (resultList == null || resultList.isEmpty()) {
                return false;
            }
            return resultList.get(0);
        } catch (Exception ex) {
            logger.error("script exists exception", ex);
        }
        return false;

    }

    @Override
    public List scriptExists(List scripts) {
        try {
            String[] scriptArr = new String[scripts.size()];
            scripts.toArray(scriptArr);
            return redissonClient.getScript().scriptExists(scriptArr);
        } catch (Exception ex) {
            logger.error("script exists exception", ex);
        }
        return null;

    }

    @Override
    public boolean flushScript() {
        try {
            redissonClient.getScript().scriptFlush();
            return true;
        } catch (Exception ex) {
            logger.error("flushScript exception", ex);
        }
        return false;

    }

    @Override
    public boolean killScript() {
        try {
            redissonClient.getScript().scriptKill();
            return true;
        } catch (Exception ex) {
            logger.error("killScript exception", ex);
        }
        return false;
    }

    @Override
    public  V loadScript(String script) {
        try {
            redissonClient.getScript().scriptLoad(script);
        } catch (Exception ex) {
            logger.error("loadScript exception", ex);
        }

        return null;
    }


    @Override
    public void setCodec(Codec codec) {
        this.codec = codec;
    }

    @Override
    public Codec getCodec() {
        if (this.codec == null) {
            return DEFAULT_CODEC;
        }
        return codec;
    }

    /**
     * get codec by clazz
     * @param clazz class type
     * @return Codec
     */
    public  Codec getCodec(Class clazz) {
        if (String.class == clazz) {
            return new StringCodec();
        }
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        return new TypedJsonJacksonCodec(clazz, objectMapper);
    }

    /**
     * get codec by typeReference
     * @param typeReference typeReference
     * @return Codec
     */
    public  Codec getCodec(TypeReference typeReference) {
        return new TypedJsonJacksonCodec(typeReference);
    }

    private  RScript.ReturnType getReturnType(Class clazz) {
        if (Integer.class == clazz || Long.class == clazz) {
            return RScript.ReturnType.INTEGER;
        }
        if (String.class == clazz) {
            return RScript.ReturnType.STATUS;
        }
        if (Map.class == clazz) {
            return RScript.ReturnType.MAPVALUE;
        }
        if (List.class == clazz) {
            return RScript.ReturnType.MULTI;
        }
        if (Boolean.class == clazz) {
            return RScript.ReturnType.BOOLEAN;
        }
        return RScript.ReturnType.VALUE;
    }

    /**
     * get return type
     * @param typeReference typeReference
     * @return RScript.ReturnType
     */
    private  RScript.ReturnType getReturnType(TypeReference typeReference) {
        if (typeReference.getType() instanceof ArrayType || typeReference.getType() instanceof CollectionType) {
            return RScript.ReturnType.MAPVALUELIST;
        }
        if (typeReference.getType() instanceof MapType) {
            return RScript.ReturnType.MAPVALUE;
        }
        return RScript.ReturnType.VALUE;
    }

    /**
     * list to array
     * @param keys keys
     * @return String[]
     */
    private String[] listToArray(List keys) {
        String[] keysArr = new String[keys.size()];
        keys.toArray(keysArr);
        return keysArr;
    }

    /**
     * to list
     * @param values list values
     * @param clazz class type
     * @return List
     */
    private  List toList(List values, Class clazz) {
        if (values == null || values.isEmpty()) {
            return new ArrayList<>(0);
        }
        List dataList = new ArrayList<>(values.size());
        for (Object v : values) {
            dataList.add(JacksonUtil.toJavaObject(v, clazz));
        }
        return dataList;
    }

    /**
     * to list
     * @param values list values
     * @param clazz class type
     * @return List
     */
    private  Set toSet(Set values, Class clazz) {
        if (values == null || values.isEmpty()) {
            return new HashSet<>(0);
        }
        Set dataSet = new HashSet<>(values.size());
        for (Object v : values) {
            dataSet.add(JacksonUtil.toJavaObject(v, clazz));
        }
        return dataSet;
    }

    private  List toList(BatchResult result, Class clazz) {
        if (result == null || result.getResponses() == null) {
            return new ArrayList<>(0);
        }
        List dataList = new ArrayList<>(result.getResponses().size());
        for (Object v : result.getResponses()) {
            dataList.add(JacksonUtil.toJavaObject(v, clazz));
        }
        return dataList;
    }
}