Skip to content

Commit

Permalink
Add support for STRALGO LCS #1280
Browse files Browse the repository at this point in the history
Original pull request: #1282.
  • Loading branch information
dengliming authored and mp911de committed Jun 24, 2020
1 parent 2f7b13c commit f61e323
Show file tree
Hide file tree
Showing 14 changed files with 506 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,11 @@ public RedisFuture<Long> strlen(K key) {
return dispatch(commandBuilder.strlen(key));
}

@Override
public RedisFuture<StringMatchResult> stralgoLcs(StrAlgoArgs args) {
return dispatch(commandBuilder.stralgoLcs(args));
}

@Override
public RedisFuture<Set<V>> sunion(K... keys) {
return dispatch(commandBuilder.sunion(keys));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,11 @@ public Mono<Long> strlen(K key) {
return createMono(() -> commandBuilder.strlen(key));
}

@Override
public Mono<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs) {
return createMono(() -> commandBuilder.stralgoLcs(strAlgoArgs));
}

@Override
public Flux<V> sunion(K... keys) {
return createDissolvingFlux(() -> commandBuilder.sunion(keys));
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/io/lettuce/core/RedisCommandBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2031,6 +2031,14 @@ Command<K, V, Long> strlen(K key) {
return createCommand(STRLEN, new IntegerOutput<>(codec), key);
}

Command<K, V, StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs) {
LettuceAssert.notNull(strAlgoArgs, "StrAlgoArgs " + MUST_NOT_BE_NULL);

CommandArgs<K, V> args = new CommandArgs<>(codec);
strAlgoArgs.build(args);
return createCommand(STRALGO, new StringMatchResultOutput<>(codec, strAlgoArgs.isWithIdx()), args);
}

Command<K, V, Set<V>> sunion(K... keys) {
notEmpty(keys);

Expand Down
168 changes: 168 additions & 0 deletions src/main/java/io/lettuce/core/StrAlgoArgs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright 2011-2020 the original author or authors.
*
* 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
*
* https://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 io.lettuce.core;

import io.lettuce.core.internal.LettuceAssert;
import io.lettuce.core.protocol.CommandArgs;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
* Argument list builder for the Redis <a href="http://redis.io/commands/stralgo">STRALGO</a> command.
* Static import the methods from {@link StrAlgoArgs.Builder} and call the methods: {@code block(…)} .
* <p>
* {@link StrAlgoArgs} is a mutable object and instances should be used only once to avoid shared mutable state.
*
* @author dengliming
* @since 6.0
*/
public class StrAlgoArgs implements CompositeArgument {

private boolean justLen;
private int minMatchLen;
private boolean withMatchLen;
private boolean withIdx;
private By by = By.STRINGS;
private String[] keys;
private Charset charset = StandardCharsets.UTF_8;

/**
* Builder entry points for {@link StrAlgoArgs}.
*/
public static class Builder {

/**
* Utility constructor.
*/
private Builder() {
}

/**
* Creates new {@link StrAlgoArgs} by keys.
*
* @return new {@link StrAlgoArgs} with {@literal By KEYS} set.
*/
public static StrAlgoArgs keys(String... keys) {
return new StrAlgoArgs().by(By.KEYS, keys);
}

/**
* Creates new {@link StrAlgoArgs} by strings.
*
* @return new {@link StrAlgoArgs} with {@literal By STRINGS} set.
*/
public static StrAlgoArgs strings(String... strings) {
return new StrAlgoArgs().by(By.STRINGS, strings);
}

/**
* Creates new {@link StrAlgoArgs} by strings and charset.
*
* @return new {@link StrAlgoArgs} with {@literal By STRINGS} set.
*/
public static StrAlgoArgs strings(Charset charset, String... strings) {
return new StrAlgoArgs().by(By.STRINGS, strings).charset(charset);
}
}
/**
* restrict the list of matches to the ones of a given minimal length.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs minMatchLen(int minMatchLen) {
this.minMatchLen = minMatchLen;
return this;
}

/**
* Request just the length of the match for results.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs justLen() {
justLen = true;
return this;
}

/**
* Request match len for results.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs withMatchLen() {
withMatchLen = true;
return this;
}

/**
* Request match position in each strings for results.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs withIdx() {
withIdx = true;
return this;
}

public StrAlgoArgs by(By by, String... keys) {
this.by = by;
this.keys = keys;
return this;
}

public boolean isWithIdx() {
return withIdx;
}

public StrAlgoArgs charset(Charset charset) {
this.charset = charset;
return this;
}

public enum By {
STRINGS, KEYS
}

public <K, V> void build(CommandArgs<K, V> args) {
LettuceAssert.notEmpty(keys, "strings or keys must be not empty");

args.add("LCS");
args.add(by.name());
for (String key : keys) {
if (by == By.STRINGS) {
args.add(key.getBytes(charset));
} else {
args.add(key);
}
}
if (justLen) {
args.add("LEN");
}
if (withIdx) {
args.add("IDX");
}

if (minMatchLen > 0) {
args.add("MINMATCHLEN");
args.add(minMatchLen);
}

if (withMatchLen) {
args.add("WITHMATCHLEN");
}
}
}
118 changes: 118 additions & 0 deletions src/main/java/io/lettuce/core/StringMatchResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2011-2020 the original author or authors.
*
* 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
*
* https://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 io.lettuce.core;

import java.util.ArrayList;
import java.util.List;

/**
* Result for STRALGO command
*
* @author dengliming
*/
public class StringMatchResult {

private String matchString;
private List<MatchedPosition> matches = new ArrayList<>();
private long len;

public StringMatchResult matchString(String matchString) {
this.matchString = matchString;
return this;
}

public StringMatchResult addMatch(MatchedPosition match) {
this.matches.add(match);
return this;
}

public StringMatchResult len(long len) {
this.len = len;
return this;
}

public String getMatchString() {
return matchString;
}

public List<MatchedPosition> getMatches() {
return matches;
}

public long getLen() {
return len;
}

/**
* match position in each strings
*/
public static class MatchedPosition {
private Position a;
private Position b;
private long matchLen;

public MatchedPosition(Position a, Position b, long matchLen) {
this.a = a;
this.b = b;
this.matchLen = matchLen;
}

public Position getA() {
return a;
}

public void setA(Position a) {
this.a = a;
}

public Position getB() {
return b;
}

public void setB(Position b) {
this.b = b;
}

public long getMatchLen() {
return matchLen;
}

public void setMatchLen(long matchLen) {
this.matchLen = matchLen;
}
}

/**
* position range
*/
public static class Position {
private final long start;
private final long end;

public Position(long start, long end) {
this.start = start;
this.end = end;
}

public long getStart() {
return start;
}

public long getEnd() {
return end;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import io.lettuce.core.RedisFuture;
import io.lettuce.core.SetArgs;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.StrAlgoArgs;
import io.lettuce.core.StringMatchResult;

/**
* Asynchronous executed commands for Strings.
Expand Down Expand Up @@ -374,4 +376,13 @@ public interface RedisStringAsyncCommands<K, V> {
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
*/
RedisFuture<Long> strlen(K key);

/**
* The STRALGO implements complex algorithms that operate on strings.
*
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
* @param strAlgoArgs
* @return StringMatchResult
*/
RedisFuture<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import io.lettuce.core.SetArgs;
import io.lettuce.core.Value;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.StrAlgoArgs;
import io.lettuce.core.StringMatchResult;

/**
* Reactive executed commands for Strings.
Expand Down Expand Up @@ -375,4 +377,13 @@ public interface RedisStringReactiveCommands<K, V> {
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
*/
Mono<Long> strlen(K key);

/**
* The STRALGO implements complex algorithms that operate on strings.
*
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
* @param strAlgoArgs
* @return StringMatchResult
*/
Mono<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs);
}
11 changes: 11 additions & 0 deletions src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import io.lettuce.core.KeyValue;
import io.lettuce.core.SetArgs;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.StrAlgoArgs;
import io.lettuce.core.StringMatchResult;

/**
* Synchronous executed commands for Strings.
Expand Down Expand Up @@ -373,4 +375,13 @@ public interface RedisStringCommands<K, V> {
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
*/
Long strlen(K key);

/**
* The STRALGO implements complex algorithms that operate on strings.
*
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
* @param strAlgoArgs
* @return StringMatchResult
*/
StringMatchResult stralgoLcs(StrAlgoArgs strAlgoArgs);
}
Loading

0 comments on commit f61e323

Please sign in to comment.