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

com.github.lontime.shaded.org.redisson.RedissonGeo Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2013-2021 Nikita Koksharov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.lontime.shaded.org.redisson;

import java.math.BigDecimal;
import java.util.*;

import com.github.lontime.shaded.org.redisson.api.GeoEntry;
import com.github.lontime.shaded.org.redisson.api.GeoOrder;
import com.github.lontime.shaded.org.redisson.api.GeoPosition;
import com.github.lontime.shaded.org.redisson.api.GeoUnit;
import com.github.lontime.shaded.org.redisson.api.RFuture;
import com.github.lontime.shaded.org.redisson.api.RGeo;
import com.github.lontime.shaded.org.redisson.api.RedissonClient;
import com.github.lontime.shaded.org.redisson.api.geo.GeoSearchArgs;
import com.github.lontime.shaded.org.redisson.api.geo.GeoSearchNode;
import com.github.lontime.shaded.org.redisson.client.codec.Codec;
import com.github.lontime.shaded.org.redisson.client.codec.LongCodec;
import com.github.lontime.shaded.org.redisson.client.codec.StringCodec;
import com.github.lontime.shaded.org.redisson.client.protocol.RedisCommand;
import com.github.lontime.shaded.org.redisson.client.protocol.RedisCommands;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.CodecDecoder;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.GeoDistanceDecoder;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.GeoPositionDecoder;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.GeoPositionMapDecoder;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.ListMultiDecoder2;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.MultiDecoder;
import com.github.lontime.shaded.org.redisson.client.protocol.decoder.ObjectMapReplayDecoder2;
import com.github.lontime.shaded.org.redisson.command.CommandAsyncExecutor;
import com.github.lontime.shaded.org.redisson.connection.decoder.MapGetAllDecoder;

/**
 * Geospatial items holder
 * 
 * @author Nikita Koksharov
 *
 * @param  value
 */
public class RedissonGeo extends RedissonScoredSortedSet implements RGeo {

    private static final MultiDecoder> POSTITION_DECODER = new ListMultiDecoder2(
            new ObjectMapReplayDecoder2(),
            new CodecDecoder(),
            new GeoPositionDecoder());
    
    private static final MultiDecoder> DISTANCE_DECODER = new ListMultiDecoder2(
            new ObjectMapReplayDecoder2(),
            new GeoDistanceDecoder());
    
    private static final RedisCommand> GEORADIUS_RO_DISTANCE = new RedisCommand>(
            "GEORADIUS_RO", DISTANCE_DECODER);
    private static final RedisCommand> GEOSEARCH_DISTANCE = new RedisCommand>(
            "GEOSEARCH", DISTANCE_DECODER);
    private static final RedisCommand> GEOSEARCH_POS = new RedisCommand>(
            "GEOSEARCH", POSTITION_DECODER);
    private static final RedisCommand> GEORADIUS_RO_POS = new RedisCommand>(
            "GEORADIUS_RO", POSTITION_DECODER);
    private static final RedisCommand> GEORADIUSBYMEMBER_RO_DISTANCE = new RedisCommand>(
            "GEORADIUSBYMEMBER_RO", DISTANCE_DECODER);
    private static final RedisCommand> GEORADIUSBYMEMBER_RO_POS = new RedisCommand>(
            "GEORADIUSBYMEMBER_RO", POSTITION_DECODER);

    public RedissonGeo(CommandAsyncExecutor connectionManager, String name, RedissonClient redisson) {
        super(connectionManager, name, redisson);
    }

    public RedissonGeo(Codec codec, CommandAsyncExecutor connectionManager, String name, RedissonClient redisson) {
        super(codec, connectionManager, name, redisson);
    }

    @Override
    public RFuture addAsync(double longitude, double latitude, V member) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEOADD, getRawName(), convert(longitude),
                convert(latitude), encode(member));
    }

    private String convert(double longitude) {
        return BigDecimal.valueOf(longitude).toPlainString();
    }

    @Override
    public long add(double longitude, double latitude, V member) {
        return get(addAsync(longitude, latitude, member));
    }

    @Override
    public long add(GeoEntry... entries) {
        return get(addAsync(entries));
    }

    @Override
    public RFuture addAsync(GeoEntry... entries) {
        return addAsync("", entries);
    }

    private RFuture addAsync(String subCommand, GeoEntry... entries) {
        List params = new ArrayList(entries.length + 2);
        params.add(getRawName());
        if (!subCommand.isEmpty()) {
            params.add(subCommand);
        }
        for (GeoEntry entry : entries) {
            params.add(entry.getLongitude());
            params.add(entry.getLatitude());
            params.add(encode(entry.getMember()));
        }
        return commandExecutor.writeAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.GEOADD, params.toArray());
    }

    @Override
    public Boolean addIfExists(double longitude, double latitude, V member) {
        return get(addIfExistsAsync(longitude, latitude, member));
    }

    @Override
    public long addIfExists(GeoEntry... entries) {
        return get(addIfExistsAsync(entries));
    }

    @Override
    public RFuture addIfExistsAsync(double longitude, double latitude, V member) {
        return commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_BOOLEAN,
            "local value = redis.call('geopos', KEYS[1], ARGV[3]); "
                + "if value[1] ~= false then "
                    + "redis.call('geoadd', KEYS[1], ARGV[1], ARGV[2], ARGV[3]); "
                    + "return 1; "
                + "end; "
                + "return 0; ",
                Collections.singletonList(getRawName()),
                convert(longitude), convert(latitude), encode(member));
    }

    @Override
    public RFuture addIfExistsAsync(GeoEntry... entries) {
        return addAsync("XX", entries);
    }

    @Override
    public boolean tryAdd(double longitude, double latitude, V member) {
        return get(tryAddAsync(longitude, latitude, member));
    }

    @Override
    public long tryAdd(GeoEntry... entries) {
        return get(tryAddAsync(entries));
    }

    @Override
    public RFuture tryAddAsync(double longitude, double latitude, V member) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEOADD_BOOLEAN, getRawName(), "NX", convert(longitude),
                convert(latitude), encode(member));
    }

    @Override
    public RFuture tryAddAsync(GeoEntry... entries) {
        return addAsync("NX", entries);
    }

    @Override
    public Double dist(V firstMember, V secondMember, GeoUnit geoUnit) {
        return get(distAsync(firstMember, secondMember, geoUnit));
    }

    @Override
    public RFuture distAsync(V firstMember, V secondMember, GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.GEODIST, getRawName(),
                encode(firstMember), encode(secondMember), geoUnit);
    }

    @Override
    public Map hash(V... members) {
        return get(hashAsync(members));
    }

    @Override
    public RFuture> hashAsync(V... members) {
        List params = new ArrayList(members.length + 1);
        params.add(getRawName());
        for (Object member : members) {
            params.add(encode(member));
        }
        RedisCommand> command = new RedisCommand>("GEOHASH",
                new MapGetAllDecoder((List) Arrays.asList(members), 0));
        return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, command, params.toArray());
    }

    @Override
    public Map pos(V... members) {
        return get(posAsync(members));
    }

    @Override
    public RFuture> posAsync(V... members) {
        List params = new ArrayList(members.length + 1);
        params.add(getRawName());
        for (Object member : members) {
            params.add(encode(member));
        }

        MultiDecoder> decoder = new ListMultiDecoder2(
                new GeoPositionMapDecoder((List) Arrays.asList(members)),
                new GeoPositionDecoder());
        RedisCommand> command = new RedisCommand>("GEOPOS", decoder);
        return commandExecutor.readAsync(getRawName(), StringCodec.INSTANCE, command, params.toArray());
    }

    @Override
    public List search(GeoSearchArgs args) {
        return get(searchAsync(args));
    }

    @Override
    public RFuture> searchAsync(GeoSearchArgs args) {
        GeoSearchNode node = (GeoSearchNode) args;
        Map params = node.getParams();

        List commandParams = new ArrayList<>();
        commandParams.add(getRawName());
        RedisCommand command = null;
        if (params.get(GeoSearchNode.Params.LATITUDE) != null
                && params.get(GeoSearchNode.Params.LONGITUDE) != null) {
            command = RedisCommands.GEORADIUS_RO;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = RedisCommands.GEOSEARCH;
                commandParams.add("FROMLONLAT");
            }
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LONGITUDE)));
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LATITUDE)));
        }
        if (params.get(GeoSearchNode.Params.MEMBER) != null) {
            command = RedisCommands.GEORADIUSBYMEMBER_RO;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = RedisCommands.GEOSEARCH;
                commandParams.add("FROMMEMBER");
            }
            commandParams.add(encode(params.get(GeoSearchNode.Params.MEMBER)));
        }
        if (params.get(GeoSearchNode.Params.RADIUS) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.RADIUS));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add("BYBOX");
            commandParams.add(params.get(GeoSearchNode.Params.WIDTH));
            commandParams.add(params.get(GeoSearchNode.Params.HEIGHT));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));

            if (params.get(GeoSearchNode.Params.ORDER) != null) {
                commandParams.add(params.get(GeoSearchNode.Params.ORDER));
            }
        }
        if (params.get(GeoSearchNode.Params.COUNT) != null) {
            commandParams.add("COUNT");
            commandParams.add(params.get(GeoSearchNode.Params.COUNT));
            if (params.get(GeoSearchNode.Params.COUNT_ANY) != null) {
                commandParams.add("ANY");
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null
                && params.get(GeoSearchNode.Params.ORDER) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.ORDER));
        }

        return commandExecutor.readAsync(getRawName(), codec, command, commandParams.toArray());
    }

    @Override
    public Map searchWithDistance(GeoSearchArgs args) {
        return get(searchWithDistanceAsync(args));
    }

    @Override
    public RFuture> searchWithDistanceAsync(GeoSearchArgs args) {
        GeoSearchNode node = (GeoSearchNode) args;
        Map params = node.getParams();

        List commandParams = new ArrayList<>();
        commandParams.add(getRawName());
        RedisCommand command = null;
        if (params.get(GeoSearchNode.Params.LATITUDE) != null
                && params.get(GeoSearchNode.Params.LONGITUDE) != null) {
            command = GEORADIUS_RO_DISTANCE;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = GEOSEARCH_DISTANCE;
                commandParams.add("FROMLONLAT");
            }
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LONGITUDE)));
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LATITUDE)));
        }
        if (params.get(GeoSearchNode.Params.MEMBER) != null) {
            command = GEORADIUSBYMEMBER_RO_DISTANCE;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = GEOSEARCH_DISTANCE;
                commandParams.add("FROMMEMBER");
            }
            commandParams.add(encode(params.get(GeoSearchNode.Params.MEMBER)));
        }
        if (params.get(GeoSearchNode.Params.RADIUS) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.RADIUS));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add("BYBOX");
            commandParams.add(params.get(GeoSearchNode.Params.WIDTH));
            commandParams.add(params.get(GeoSearchNode.Params.HEIGHT));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));

            if (params.get(GeoSearchNode.Params.ORDER) != null) {
                commandParams.add(params.get(GeoSearchNode.Params.ORDER));
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null) {
            commandParams.add("WITHDIST");
        }
        if (params.get(GeoSearchNode.Params.COUNT) != null) {
            commandParams.add("COUNT");
            commandParams.add(params.get(GeoSearchNode.Params.COUNT));
            if (params.get(GeoSearchNode.Params.COUNT_ANY) != null) {
                commandParams.add("ANY");
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null
                && params.get(GeoSearchNode.Params.ORDER) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.ORDER));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
            commandParams.add("WITHDIST");
        }

        return commandExecutor.readAsync(getRawName(), codec, command, commandParams.toArray());
    }

    @Override
    public Map searchWithPosition(GeoSearchArgs args) {
        return get(searchWithPositionAsync(args));
    }

    @Override
    public RFuture> searchWithPositionAsync(GeoSearchArgs args) {
        GeoSearchNode node = (GeoSearchNode) args;
        Map params = node.getParams();

        List commandParams = new ArrayList<>();
        commandParams.add(getRawName());
        RedisCommand command = null;
        if (params.get(GeoSearchNode.Params.LATITUDE) != null
                && params.get(GeoSearchNode.Params.LONGITUDE) != null) {
            command = GEORADIUS_RO_POS;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = GEOSEARCH_POS;
                commandParams.add("FROMLONLAT");
            }
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LONGITUDE)));
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LATITUDE)));
        }
        if (params.get(GeoSearchNode.Params.MEMBER) != null) {
            command = GEORADIUSBYMEMBER_RO_POS;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = GEOSEARCH_POS;
                commandParams.add("FROMMEMBER");
            }
            commandParams.add(encode(params.get(GeoSearchNode.Params.MEMBER)));
        }
        if (params.get(GeoSearchNode.Params.RADIUS) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.RADIUS));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add("BYBOX");
            commandParams.add(params.get(GeoSearchNode.Params.WIDTH));
            commandParams.add(params.get(GeoSearchNode.Params.HEIGHT));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));

            if (params.get(GeoSearchNode.Params.ORDER) != null) {
                commandParams.add(params.get(GeoSearchNode.Params.ORDER));
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null) {
            commandParams.add("WITHCOORD");
        }
        if (params.get(GeoSearchNode.Params.COUNT) != null) {
            commandParams.add("COUNT");
            commandParams.add(params.get(GeoSearchNode.Params.COUNT));
            if (params.get(GeoSearchNode.Params.COUNT_ANY) != null) {
                commandParams.add("ANY");
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null
                && params.get(GeoSearchNode.Params.ORDER) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.ORDER));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
            commandParams.add("WITHCOORD");
        }

        return commandExecutor.readAsync(getRawName(), codec, command, commandParams.toArray());
    }

    @Override
    public List radius(double longitude, double latitude, double radius, GeoUnit geoUnit) {
        return get(radiusAsync(longitude, latitude, radius, geoUnit));
    }

    @Override
    public RFuture> radiusAsync(double longitude, double latitude, double radius, GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUS_RO, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit);
    }

    @Override
    public List radius(double longitude, double latitude, double radius, GeoUnit geoUnit, int count) {
        return get(radiusAsync(longitude, latitude, radius, geoUnit, count));
    }

    @Override
    public RFuture> radiusAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, int count) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUS_RO, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "COUNT", count);
    }

    @Override
    public List radius(double longitude, double latitude, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
        return get(radiusAsync(longitude, latitude, radius, geoUnit, geoOrder));
    }

    @Override
    public RFuture> radiusAsync(double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUS_RO, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, geoOrder);
    }

    @Override
    public List radius(double longitude, double latitude, double radius, GeoUnit geoUnit, GeoOrder geoOrder,
            int count) {
        return get(radiusAsync(longitude, latitude, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture> radiusAsync(double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUS_RO, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "COUNT", count, geoOrder);
    }

    @Override
    public Map radiusWithDistance(double longitude, double latitude, double radius, GeoUnit geoUnit) {
        return get(radiusWithDistanceAsync(longitude, latitude, radius, geoUnit));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_DISTANCE, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHDIST");
    }

    @Override
    public Map radiusWithDistance(double longitude, double latitude, double radius, GeoUnit geoUnit,
            int count) {
        return get(radiusWithDistanceAsync(longitude, latitude, radius, geoUnit, count));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_DISTANCE, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHDIST", "COUNT", count);
    }

    @Override
    public Map radiusWithDistance(double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder) {
        return get(radiusWithDistanceAsync(longitude, latitude, radius, geoUnit, geoOrder));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_DISTANCE, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHDIST", geoOrder);
    }

    @Override
    public Map radiusWithDistance(double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return get(radiusWithDistanceAsync(longitude, latitude, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_DISTANCE, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHDIST", "COUNT", count, geoOrder);
    }

    @Override
    public Map radiusWithPosition(double longitude, double latitude, double radius, GeoUnit geoUnit) {
        return get(radiusWithPositionAsync(longitude, latitude, radius, geoUnit));
    }

    @Override
    public RFuture> radiusWithPositionAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_POS, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHCOORD");
    }

    @Override
    public Map radiusWithPosition(double longitude, double latitude, double radius, GeoUnit geoUnit,
            int count) {
        return get(radiusWithPositionAsync(longitude, latitude, radius, geoUnit, count));
    }

    @Override
    public RFuture> radiusWithPositionAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_POS, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHCOORD", "COUNT", count);
    }

    @Override
    public Map radiusWithPosition(double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder) {
        return get(radiusWithPositionAsync(longitude, latitude, radius, geoUnit, geoOrder));
    }

    @Override
    public RFuture> radiusWithPositionAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_POS, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHCOORD", geoOrder);
    }

    @Override
    public Map radiusWithPosition(double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return get(radiusWithPositionAsync(longitude, latitude, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture> radiusWithPositionAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUS_RO_POS, getRawName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHCOORD", "COUNT", count, geoOrder);
    }

    @Override
    public List radius(V member, double radius, GeoUnit geoUnit) {
        return get(radiusAsync(member, radius, geoUnit));
    }

    @Override
    public RFuture> radiusAsync(V member, double radius, GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_RO, getRawName(),
                encode(member), radius, geoUnit);
    }

    @Override
    public List radius(V member, double radius, GeoUnit geoUnit, int count) {
        return get(radiusAsync(member, radius, geoUnit, count));
    }

    @Override
    public RFuture> radiusAsync(V member, double radius, GeoUnit geoUnit, int count) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_RO, getRawName(),
                encode(member), radius, geoUnit, "COUNT", count);
    }

    @Override
    public List radius(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
        return get(radiusAsync(member, radius, geoUnit, geoOrder));
    }

    @Override
    public RFuture> radiusAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_RO, getRawName(),
                encode(member), radius, geoUnit, geoOrder);
    }

    @Override
    public List radius(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return get(radiusAsync(member, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture> radiusAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return commandExecutor.readAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_RO, getRawName(),
                encode(member), radius, geoUnit, "COUNT", count, geoOrder);
    }

    @Override
    public Map radiusWithDistance(V member, double radius, GeoUnit geoUnit) {
        return get(radiusWithDistanceAsync(member, radius, geoUnit));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getRawName(), encode(member),
                radius, geoUnit, "WITHDIST");
    }

    @Override
    public Map radiusWithDistance(V member, double radius, GeoUnit geoUnit, int count) {
        return get(radiusWithDistanceAsync(member, radius, geoUnit, count));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getRawName(), encode(member),
                radius, geoUnit, "WITHDIST", "COUNT", count);
    }

    @Override
    public Map radiusWithDistance(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
        return get(radiusWithDistanceAsync(member, radius, geoUnit, geoOrder));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getRawName(), encode(member),
                radius, geoUnit, "WITHDIST", geoOrder);
    }

    @Override
    public Map radiusWithDistance(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return get(radiusWithDistanceAsync(member, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder,
            int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getRawName(), encode(member),
                radius, geoUnit, "WITHDIST", "COUNT", count, geoOrder);
    }

    @Override
    public Map radiusWithPosition(V member, double radius, GeoUnit geoUnit) {
        return get(radiusWithPositionAsync(member, radius, geoUnit));
    }

    @Override
    public RFuture> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_POS, getRawName(), encode(member), radius,
                geoUnit, "WITHCOORD");
    }

    @Override
    public Map radiusWithPosition(V member, double radius, GeoUnit geoUnit, int count) {
        return get(radiusWithPositionAsync(member, radius, geoUnit, count));
    }

    @Override
    public RFuture> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_POS, getRawName(), encode(member), radius,
                geoUnit, "WITHCOORD", "COUNT", count);
    }

    @Override
    public Map radiusWithPosition(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
        return get(radiusWithPositionAsync(member, radius, geoUnit, geoOrder));
    }

    @Override
    public RFuture> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_POS, getRawName(), encode(member), radius,
                geoUnit, "WITHCOORD", geoOrder);
    }

    @Override
    public Map radiusWithPosition(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder,
            int count) {
        return get(radiusWithPositionAsync(member, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return commandExecutor.readAsync(getRawName(), codec, GEORADIUSBYMEMBER_RO_POS, getRawName(), encode(member), radius,
                geoUnit, "WITHCOORD", "COUNT", count, geoOrder);
    }

    @Override
    public long radiusStoreTo(String destName, double longitude, double latitude, double radius, GeoUnit geoUnit) {
        return get(radiusStoreToAsync(destName, longitude, latitude, radius, geoUnit));
    }

    @Override
    public RFuture radiusStoreToAsync(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit) {
        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.GEORADIUS_STORE, getRawName(),
                convert(longitude), convert(latitude), radius, geoUnit, "STORE", destName);
    }

    @Override
    public long storeSearchTo(String destName, GeoSearchArgs args) {
        return get(storeSearchToAsync(destName, args));
    }

    @Override
    public RFuture storeSearchToAsync(String destName, GeoSearchArgs args) {
        GeoSearchNode node = (GeoSearchNode) args;
        Map params = node.getParams();

        List commandParams = new ArrayList<>();
        if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
            commandParams.add(destName);
        }
        commandParams.add(getRawName());
        RedisCommand command = null;
        if (params.get(GeoSearchNode.Params.LATITUDE) != null
                && params.get(GeoSearchNode.Params.LONGITUDE) != null) {
            command = RedisCommands.GEORADIUS_STORE;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = RedisCommands.GEOSEARCHSTORE_STORE;
                commandParams.add("FROMLONLAT");
            }
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LONGITUDE)));
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LATITUDE)));
        }
        if (params.get(GeoSearchNode.Params.MEMBER) != null) {
            command = RedisCommands.GEORADIUSBYMEMBER_STORE;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = RedisCommands.GEOSEARCHSTORE_STORE;
                commandParams.add("FROMMEMBER");
            }
            commandParams.add(encode(params.get(GeoSearchNode.Params.MEMBER)));
        }
        if (params.get(GeoSearchNode.Params.RADIUS) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.RADIUS));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add("BYBOX");
            commandParams.add(params.get(GeoSearchNode.Params.WIDTH));
            commandParams.add(params.get(GeoSearchNode.Params.HEIGHT));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));

            if (params.get(GeoSearchNode.Params.ORDER) != null) {
                commandParams.add(params.get(GeoSearchNode.Params.ORDER));
            }
        }
        if (params.get(GeoSearchNode.Params.COUNT) != null) {
            commandParams.add("COUNT");
            commandParams.add(params.get(GeoSearchNode.Params.COUNT));
            if (params.get(GeoSearchNode.Params.COUNT_ANY) != null) {
                commandParams.add("ANY");
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null
                && params.get(GeoSearchNode.Params.ORDER) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.ORDER));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null) {
            commandParams.add("STORE");
            commandParams.add(destName);
        }

        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, command, commandParams.toArray());
    }

    @Override
    public long radiusStoreTo(String destName, double longitude, double latitude, double radius, GeoUnit geoUnit,
            int count) {
        return get(radiusStoreToAsync(destName, longitude, latitude, radius, geoUnit, count));
    }

    @Override
    public RFuture radiusStoreToAsync(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit, int count) {
        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.GEORADIUS_STORE, getRawName(),
                convert(longitude), convert(latitude), radius, geoUnit, "COUNT", count, "STORE", destName);
    }

    @Override
    public long radiusStoreTo(String destName, double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return get(radiusStoreToAsync(destName, longitude, latitude, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture radiusStoreToAsync(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.GEORADIUS_STORE, getRawName(),
                convert(longitude), convert(latitude), radius, geoUnit, geoOrder, "COUNT", count, "STORE", destName);
    }

    @Override
    public long radiusStoreTo(String destName, V member, double radius, GeoUnit geoUnit) {
        return get(radiusStoreToAsync(destName, member, radius, geoUnit));
    }

    @Override
    public RFuture radiusStoreToAsync(String destName, V member, double radius, GeoUnit geoUnit) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_STORE, getRawName(),
                encode(member), radius, geoUnit, "STORE", destName);
    }

    @Override
    public long radiusStoreTo(String destName, V member, double radius, GeoUnit geoUnit, int count) {
        return get(radiusStoreToAsync(destName, member, radius, geoUnit, count));
    }

    @Override
    public RFuture radiusStoreToAsync(String destName, V member, double radius, GeoUnit geoUnit, int count) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_STORE, getRawName(),
                encode(member), radius, geoUnit, "COUNT", count, "STORE", destName);
    }

    @Override
    public long radiusStoreTo(String destName, V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return get(radiusStoreToAsync(destName, member, radius, geoUnit, geoOrder, count));
    }

    @Override
    public RFuture radiusStoreToAsync(String destName, V member, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_STORE, getRawName(),
                encode(member), radius, geoUnit, geoOrder, "COUNT", count, "STORE", destName);
    }

    @Override
    public long storeSortedSearchTo(String destName, GeoSearchArgs args) {
        return get(storeSortedSearchToAsync(destName, args));
    }

    @Override
    public RFuture storeSortedSearchToAsync(String destName, GeoSearchArgs args) {
        GeoSearchNode node = (GeoSearchNode) args;
        Map params = node.getParams();

        List commandParams = new ArrayList<>();
        if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
            commandParams.add(destName);
        }
        commandParams.add(getRawName());
        RedisCommand command = null;
        if (params.get(GeoSearchNode.Params.LATITUDE) != null
                && params.get(GeoSearchNode.Params.LONGITUDE) != null) {
            command = RedisCommands.GEORADIUS_STORE;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = RedisCommands.GEOSEARCHSTORE_STORE;
                commandParams.add("FROMLONLAT");
            }
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LONGITUDE)));
            commandParams.add(convert((double) params.get(GeoSearchNode.Params.LATITUDE)));
        }
        if (params.get(GeoSearchNode.Params.MEMBER) != null) {
            command = RedisCommands.GEORADIUSBYMEMBER_STORE;
            if (params.get(GeoSearchNode.Params.HEIGHT) != null) {
                command = RedisCommands.GEOSEARCHSTORE_STORE;
                commandParams.add("FROMMEMBER");
            }
            commandParams.add(encode(params.get(GeoSearchNode.Params.MEMBER)));
        }
        if (params.get(GeoSearchNode.Params.RADIUS) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.RADIUS));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) != null
            && params.get(GeoSearchNode.Params.UNIT) != null) {
            commandParams.add("BYBOX");
            commandParams.add(params.get(GeoSearchNode.Params.WIDTH));
            commandParams.add(params.get(GeoSearchNode.Params.HEIGHT));
            commandParams.add(params.get(GeoSearchNode.Params.UNIT));

            if (params.get(GeoSearchNode.Params.ORDER) != null) {
                commandParams.add(params.get(GeoSearchNode.Params.ORDER));
            }
        }
        if (params.get(GeoSearchNode.Params.COUNT) != null) {
            commandParams.add("COUNT");
            commandParams.add(params.get(GeoSearchNode.Params.COUNT));
            if (params.get(GeoSearchNode.Params.COUNT_ANY) != null) {
                commandParams.add("ANY");
            }
        }
        if (params.get(GeoSearchNode.Params.HEIGHT) == null
                && params.get(GeoSearchNode.Params.ORDER) != null) {
            commandParams.add(params.get(GeoSearchNode.Params.ORDER));
        }
        commandParams.add("STOREDIST");
        if (params.get(GeoSearchNode.Params.HEIGHT) == null) {
            commandParams.add(destName);
        }

        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, command, commandParams.toArray());
    }

    @Override
    public RFuture radiusStoreSortedToAsync(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit) {
        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.GEORADIUS_STORE, getRawName(),
                convert(longitude), convert(latitude), radius, geoUnit, "STOREDIST", destName);
    }

    @Override
    public RFuture radiusStoreSortedToAsync(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit, int count) {
        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.GEORADIUS_STORE, getRawName(),
                convert(longitude), convert(latitude), radius, geoUnit, "COUNT", count, "STOREDIST", destName);
    }

    @Override
    public RFuture radiusStoreSortedToAsync(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return commandExecutor.writeAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.GEORADIUS_STORE, getRawName(),
                convert(longitude), convert(latitude), radius, geoUnit, geoOrder, "COUNT", count, "STOREDIST", destName);
    }

    @Override
    public RFuture radiusStoreSortedToAsync(String destName, V member, double radius, GeoUnit geoUnit) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_STORE, getRawName(),
                encode(member), radius, geoUnit, "STOREDIST", destName);
    }

    @Override
    public RFuture radiusStoreSortedToAsync(String destName, V member, double radius, GeoUnit geoUnit,
            int count) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_STORE, getRawName(),
                encode(member), radius, geoUnit, "COUNT", count, "STOREDIST", destName);
    }

    @Override
    public RFuture radiusStoreSortedToAsync(String destName, V member, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return commandExecutor.writeAsync(getRawName(), codec, RedisCommands.GEORADIUSBYMEMBER_STORE, getRawName(),
                encode(member), radius, geoUnit, geoOrder, "COUNT", count, "STOREDIST", destName);
    }

    @Override
    public long radiusStoreSortedTo(String destName, double longitude, double latitude, double radius,
            GeoUnit geoUnit) {
        return get(radiusStoreSortedToAsync(destName, longitude, latitude, radius, geoUnit));
    }

    @Override
    public long radiusStoreSortedTo(String destName, double longitude, double latitude, double radius, GeoUnit geoUnit,
            int count) {
        return get(radiusStoreSortedToAsync(destName, longitude, latitude, radius, geoUnit, count));
    }

    @Override
    public long radiusStoreSortedTo(String destName, double longitude, double latitude, double radius, GeoUnit geoUnit,
            GeoOrder geoOrder, int count) {
        return get(radiusStoreSortedToAsync(destName, longitude, latitude, radius, geoUnit, geoOrder, count));
    }

    @Override
    public long radiusStoreSortedTo(String destName, V member, double radius, GeoUnit geoUnit) {
        return get(radiusStoreSortedToAsync(destName, member, radius, geoUnit));
    }

    @Override
    public long radiusStoreSortedTo(String destName, V member, double radius, GeoUnit geoUnit, int count) {
        return get(radiusStoreSortedToAsync(destName, member, radius, geoUnit));
    }

    @Override
    public long radiusStoreSortedTo(String destName, V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder,
            int count) {
        return get(radiusStoreSortedToAsync(destName, member, radius, geoUnit));
    }

}