Skip to content

Commit fa29ceb

Browse files
denglimingmp911de
authored andcommitted
Add support for STRALGO LCS #1280
Original pull request: #1282.
1 parent 3fbcb0f commit fa29ceb

14 files changed

+506
-2
lines changed

src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,11 @@ public RedisFuture<Long> strlen(K key) {
14271427
return dispatch(commandBuilder.strlen(key));
14281428
}
14291429

1430+
@Override
1431+
public RedisFuture<StringMatchResult> stralgoLcs(StrAlgoArgs args) {
1432+
return dispatch(commandBuilder.stralgoLcs(args));
1433+
}
1434+
14301435
@Override
14311436
public RedisFuture<Set<V>> sunion(K... keys) {
14321437
return dispatch(commandBuilder.sunion(keys));

src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,11 @@ public Mono<Long> strlen(K key) {
15031503
return createMono(() -> commandBuilder.strlen(key));
15041504
}
15051505

1506+
@Override
1507+
public Mono<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs) {
1508+
return createMono(() -> commandBuilder.stralgoLcs(strAlgoArgs));
1509+
}
1510+
15061511
@Override
15071512
public Flux<V> sunion(K... keys) {
15081513
return createDissolvingFlux(() -> commandBuilder.sunion(keys));

src/main/java/io/lettuce/core/RedisCommandBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,14 @@ Command<K, V, Long> strlen(K key) {
19721972
return createCommand(STRLEN, new IntegerOutput<>(codec), key);
19731973
}
19741974

1975+
Command<K, V, StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs) {
1976+
LettuceAssert.notNull(strAlgoArgs, "StrAlgoArgs " + MUST_NOT_BE_NULL);
1977+
1978+
CommandArgs<K, V> args = new CommandArgs<>(codec);
1979+
strAlgoArgs.build(args);
1980+
return createCommand(STRALGO, new StringMatchResultOutput<>(codec, strAlgoArgs.isWithIdx()), args);
1981+
}
1982+
19751983
Command<K, V, Set<V>> sunion(K... keys) {
19761984
notEmpty(keys);
19771985

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright 2011-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.lettuce.core;
17+
18+
import io.lettuce.core.internal.LettuceAssert;
19+
import io.lettuce.core.protocol.CommandArgs;
20+
21+
import java.nio.charset.Charset;
22+
import java.nio.charset.StandardCharsets;
23+
24+
/**
25+
* Argument list builder for the Redis <a href="http://redis.io/commands/stralgo">STRALGO</a> command.
26+
* Static import the methods from {@link StrAlgoArgs.Builder} and call the methods: {@code block(…)} .
27+
* <p>
28+
* {@link StrAlgoArgs} is a mutable object and instances should be used only once to avoid shared mutable state.
29+
*
30+
* @author dengliming
31+
* @since 6.0
32+
*/
33+
public class StrAlgoArgs implements CompositeArgument {
34+
35+
private boolean justLen;
36+
private int minMatchLen;
37+
private boolean withMatchLen;
38+
private boolean withIdx;
39+
private By by = By.STRINGS;
40+
private String[] keys;
41+
private Charset charset = StandardCharsets.UTF_8;
42+
43+
/**
44+
* Builder entry points for {@link StrAlgoArgs}.
45+
*/
46+
public static class Builder {
47+
48+
/**
49+
* Utility constructor.
50+
*/
51+
private Builder() {
52+
}
53+
54+
/**
55+
* Creates new {@link StrAlgoArgs} by keys.
56+
*
57+
* @return new {@link StrAlgoArgs} with {@literal By KEYS} set.
58+
*/
59+
public static StrAlgoArgs keys(String... keys) {
60+
return new StrAlgoArgs().by(By.KEYS, keys);
61+
}
62+
63+
/**
64+
* Creates new {@link StrAlgoArgs} by strings.
65+
*
66+
* @return new {@link StrAlgoArgs} with {@literal By STRINGS} set.
67+
*/
68+
public static StrAlgoArgs strings(String... strings) {
69+
return new StrAlgoArgs().by(By.STRINGS, strings);
70+
}
71+
72+
/**
73+
* Creates new {@link StrAlgoArgs} by strings and charset.
74+
*
75+
* @return new {@link StrAlgoArgs} with {@literal By STRINGS} set.
76+
*/
77+
public static StrAlgoArgs strings(Charset charset, String... strings) {
78+
return new StrAlgoArgs().by(By.STRINGS, strings).charset(charset);
79+
}
80+
}
81+
/**
82+
* restrict the list of matches to the ones of a given minimal length.
83+
*
84+
* @return {@code this} {@link StrAlgoArgs}.
85+
*/
86+
public StrAlgoArgs minMatchLen(int minMatchLen) {
87+
this.minMatchLen = minMatchLen;
88+
return this;
89+
}
90+
91+
/**
92+
* Request just the length of the match for results.
93+
*
94+
* @return {@code this} {@link StrAlgoArgs}.
95+
*/
96+
public StrAlgoArgs justLen() {
97+
justLen = true;
98+
return this;
99+
}
100+
101+
/**
102+
* Request match len for results.
103+
*
104+
* @return {@code this} {@link StrAlgoArgs}.
105+
*/
106+
public StrAlgoArgs withMatchLen() {
107+
withMatchLen = true;
108+
return this;
109+
}
110+
111+
/**
112+
* Request match position in each strings for results.
113+
*
114+
* @return {@code this} {@link StrAlgoArgs}.
115+
*/
116+
public StrAlgoArgs withIdx() {
117+
withIdx = true;
118+
return this;
119+
}
120+
121+
public StrAlgoArgs by(By by, String... keys) {
122+
this.by = by;
123+
this.keys = keys;
124+
return this;
125+
}
126+
127+
public boolean isWithIdx() {
128+
return withIdx;
129+
}
130+
131+
public StrAlgoArgs charset(Charset charset) {
132+
this.charset = charset;
133+
return this;
134+
}
135+
136+
public enum By {
137+
STRINGS, KEYS
138+
}
139+
140+
public <K, V> void build(CommandArgs<K, V> args) {
141+
LettuceAssert.notEmpty(keys, "strings or keys must be not empty");
142+
143+
args.add("LCS");
144+
args.add(by.name());
145+
for (String key : keys) {
146+
if (by == By.STRINGS) {
147+
args.add(key.getBytes(charset));
148+
} else {
149+
args.add(key);
150+
}
151+
}
152+
if (justLen) {
153+
args.add("LEN");
154+
}
155+
if (withIdx) {
156+
args.add("IDX");
157+
}
158+
159+
if (minMatchLen > 0) {
160+
args.add("MINMATCHLEN");
161+
args.add(minMatchLen);
162+
}
163+
164+
if (withMatchLen) {
165+
args.add("WITHMATCHLEN");
166+
}
167+
}
168+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2011-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.lettuce.core;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
/**
22+
* Result for STRALGO command
23+
*
24+
* @author dengliming
25+
*/
26+
public class StringMatchResult {
27+
28+
private String matchString;
29+
private List<MatchedPosition> matches = new ArrayList<>();
30+
private long len;
31+
32+
public StringMatchResult matchString(String matchString) {
33+
this.matchString = matchString;
34+
return this;
35+
}
36+
37+
public StringMatchResult addMatch(MatchedPosition match) {
38+
this.matches.add(match);
39+
return this;
40+
}
41+
42+
public StringMatchResult len(long len) {
43+
this.len = len;
44+
return this;
45+
}
46+
47+
public String getMatchString() {
48+
return matchString;
49+
}
50+
51+
public List<MatchedPosition> getMatches() {
52+
return matches;
53+
}
54+
55+
public long getLen() {
56+
return len;
57+
}
58+
59+
/**
60+
* match position in each strings
61+
*/
62+
public static class MatchedPosition {
63+
private Position a;
64+
private Position b;
65+
private long matchLen;
66+
67+
public MatchedPosition(Position a, Position b, long matchLen) {
68+
this.a = a;
69+
this.b = b;
70+
this.matchLen = matchLen;
71+
}
72+
73+
public Position getA() {
74+
return a;
75+
}
76+
77+
public void setA(Position a) {
78+
this.a = a;
79+
}
80+
81+
public Position getB() {
82+
return b;
83+
}
84+
85+
public void setB(Position b) {
86+
this.b = b;
87+
}
88+
89+
public long getMatchLen() {
90+
return matchLen;
91+
}
92+
93+
public void setMatchLen(long matchLen) {
94+
this.matchLen = matchLen;
95+
}
96+
}
97+
98+
/**
99+
* position range
100+
*/
101+
public static class Position {
102+
private final long start;
103+
private final long end;
104+
105+
public Position(long start, long end) {
106+
this.start = start;
107+
this.end = end;
108+
}
109+
110+
public long getStart() {
111+
return start;
112+
}
113+
114+
public long getEnd() {
115+
return end;
116+
}
117+
}
118+
}

src/main/java/io/lettuce/core/api/async/RedisStringAsyncCommands.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import io.lettuce.core.RedisFuture;
2424
import io.lettuce.core.SetArgs;
2525
import io.lettuce.core.output.KeyValueStreamingChannel;
26+
import io.lettuce.core.StrAlgoArgs;
27+
import io.lettuce.core.StringMatchResult;
2628

2729
/**
2830
* Asynchronous executed commands for Strings.
@@ -374,4 +376,13 @@ public interface RedisStringAsyncCommands<K, V> {
374376
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
375377
*/
376378
RedisFuture<Long> strlen(K key);
379+
380+
/**
381+
* The STRALGO implements complex algorithms that operate on strings.
382+
*
383+
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
384+
* @param strAlgoArgs
385+
* @return StringMatchResult
386+
*/
387+
RedisFuture<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs);
377388
}

src/main/java/io/lettuce/core/api/reactive/RedisStringReactiveCommands.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io.lettuce.core.SetArgs;
2525
import io.lettuce.core.Value;
2626
import io.lettuce.core.output.KeyValueStreamingChannel;
27+
import io.lettuce.core.StrAlgoArgs;
28+
import io.lettuce.core.StringMatchResult;
2729

2830
/**
2931
* Reactive executed commands for Strings.
@@ -375,4 +377,13 @@ public interface RedisStringReactiveCommands<K, V> {
375377
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
376378
*/
377379
Mono<Long> strlen(K key);
380+
381+
/**
382+
* The STRALGO implements complex algorithms that operate on strings.
383+
*
384+
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
385+
* @param strAlgoArgs
386+
* @return StringMatchResult
387+
*/
388+
Mono<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs);
378389
}

src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import io.lettuce.core.KeyValue;
2323
import io.lettuce.core.SetArgs;
2424
import io.lettuce.core.output.KeyValueStreamingChannel;
25+
import io.lettuce.core.StrAlgoArgs;
26+
import io.lettuce.core.StringMatchResult;
2527

2628
/**
2729
* Synchronous executed commands for Strings.
@@ -373,4 +375,13 @@ public interface RedisStringCommands<K, V> {
373375
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
374376
*/
375377
Long strlen(K key);
378+
379+
/**
380+
* The STRALGO implements complex algorithms that operate on strings.
381+
*
382+
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
383+
* @param strAlgoArgs
384+
* @return StringMatchResult
385+
*/
386+
StringMatchResult stralgoLcs(StrAlgoArgs strAlgoArgs);
376387
}

0 commit comments

Comments
 (0)