Skip to content

Commit 6d7c5ce

Browse files
RyanADThomas Darimont
authored and
Thomas Darimont
committed
DATAREDIS-293 - JedisConnection, allow bulk addition with same score.
Added version check for jedis library as the operation had been introduced in 2.4. Original Pull Request: #63
1 parent db2da6d commit 6d7c5ce

File tree

7 files changed

+270
-18
lines changed

7 files changed

+270
-18
lines changed

src/test/java/org/springframework/data/redis/Version.java renamed to src/main/java/org/springframework/data/redis/Version.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2013 the original author or authors.
2+
* Copyright 2011-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,8 +19,12 @@
1919
* A {@link Comparable} software version
2020
*
2121
* @author Jennifer Hickey
22+
* @author Christoph Strobl
2223
*/
2324
public class Version implements Comparable<Version> {
25+
26+
public static final Version UNKNOWN = new Version(0, 0, 0);
27+
2428
Integer major;
2529
Integer minor;
2630
Integer patch;
@@ -48,4 +52,51 @@ public int compareTo(Version o) {
4852
public String toString() {
4953
return "" + major + "." + minor + "." + patch;
5054
}
55+
56+
@Override
57+
public int hashCode() {
58+
final int prime = 31;
59+
int result = 1;
60+
result = prime * result + ((major == null) ? 0 : major.hashCode());
61+
result = prime * result + ((minor == null) ? 0 : minor.hashCode());
62+
result = prime * result + ((patch == null) ? 0 : patch.hashCode());
63+
return result;
64+
}
65+
66+
@Override
67+
public boolean equals(Object obj) {
68+
if (this == obj) {
69+
return true;
70+
}
71+
if (obj == null) {
72+
return false;
73+
}
74+
if (!(obj instanceof Version)) {
75+
return false;
76+
}
77+
Version other = (Version) obj;
78+
if (major == null) {
79+
if (other.major != null) {
80+
return false;
81+
}
82+
} else if (!major.equals(other.major)) {
83+
return false;
84+
}
85+
if (minor == null) {
86+
if (other.minor != null) {
87+
return false;
88+
}
89+
} else if (!minor.equals(other.minor)) {
90+
return false;
91+
}
92+
if (patch == null) {
93+
if (other.patch != null) {
94+
return false;
95+
}
96+
} else if (!patch.equals(other.patch)) {
97+
return false;
98+
}
99+
return true;
100+
}
101+
51102
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2014 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+
* http://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 org.springframework.data.redis;
17+
18+
import java.util.regex.Matcher;
19+
import java.util.regex.Pattern;
20+
21+
/**
22+
* Central class for reading version string (eg. {@literal 1.3.1}) into {@link Version}.
23+
*
24+
* @author Christoph Strobl
25+
* @since 1.3
26+
*/
27+
public class VersionParser {
28+
29+
private static final Pattern VERSION_MATCHER = Pattern.compile("([0-9]+)\\.([0-9]+)(\\.([0-9]+))?(.*)");
30+
31+
/**
32+
* Parse version string {@literal eg. 1.1.1} to {@link Version}.
33+
*
34+
* @param version
35+
* @return
36+
*/
37+
public static Version parseVersion(String version) {
38+
if (version == null) {
39+
return Version.UNKNOWN;
40+
}
41+
42+
Matcher matcher = VERSION_MATCHER.matcher(version);
43+
if (matcher.matches()) {
44+
String major = matcher.group(1);
45+
String minor = matcher.group(2);
46+
String patch = matcher.group(4);
47+
return new Version(Integer.parseInt(major), minor != null ? Integer.parseInt(minor) : 0,
48+
patch != null ? Integer.parseInt(patch) : 0);
49+
}
50+
return Version.UNKNOWN;
51+
}
52+
53+
}

src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2923,7 +2923,7 @@ private Map<byte[], Double> zAddArgs(Set<Tuple> tuples) {
29232923

29242924
Map<byte[], Double> args = new HashMap<byte[], Double>();
29252925
for (Tuple tuple : tuples) {
2926-
if (args.containsValue(tuple.getScore())) {
2926+
if (args.containsValue(tuple.getScore()) && !JedisVersionUtil.atLeastJedis24()) {
29272927
throw new UnsupportedOperationException(
29282928
"Bulk add of multiple elements with the same score is not supported. Add the elements individually.");
29292929
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2014 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+
* http://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 org.springframework.data.redis.connection.jedis;
17+
18+
import java.io.IOException;
19+
import java.util.Properties;
20+
21+
import org.springframework.core.io.support.PropertiesLoaderUtils;
22+
import org.springframework.data.redis.Version;
23+
import org.springframework.data.redis.VersionParser;
24+
import org.springframework.util.StringUtils;
25+
26+
import redis.clients.jedis.Jedis;
27+
28+
/**
29+
* @author Christoph Strobl
30+
* @since 1.3
31+
*/
32+
public class JedisVersionUtil {
33+
34+
private static Version jedisVersion = parseVersion(resolveJedisVersion());
35+
36+
/**
37+
* @return current {@link redis.clients.jedis.Jedis} version.
38+
*/
39+
public static Version jedisVersion() {
40+
return jedisVersion;
41+
}
42+
43+
/**
44+
* Parse version string {@literal eg. 1.1.1} to {@link Version}.
45+
*
46+
* @param version
47+
* @return
48+
*/
49+
static Version parseVersion(String version) {
50+
return VersionParser.parseVersion(version);
51+
}
52+
53+
/**
54+
* @return true if used jedis version is at minimum {@literal 2.4}.
55+
*/
56+
public static boolean atLeastJedis24() {
57+
return atLeast("2.4");
58+
}
59+
60+
private static String resolveJedisVersion() {
61+
62+
String version = Jedis.class.getPackage().getImplementationVersion();
63+
64+
if (!StringUtils.hasText(version)) {
65+
try {
66+
Properties props = PropertiesLoaderUtils.loadAllProperties("META-INF/maven/redis.clients/jedis/pom.properties");
67+
if (props.containsKey("version")) {
68+
version = props.getProperty("version");
69+
}
70+
} catch (IOException e) {
71+
// ignore this one
72+
}
73+
}
74+
return version;
75+
}
76+
77+
/**
78+
* Compares given version string against current jedis version.
79+
*
80+
* @param version
81+
* @return true in case given version is greater than equal to current one.
82+
*/
83+
public static boolean atLeast(String version) {
84+
return jedisVersion.compareTo(parseVersion(version)) >= 0;
85+
}
86+
87+
/**
88+
* Compares given version string against current jedis version.
89+
*
90+
* @param version
91+
* @return true in case given version is less than equal to current one.
92+
*/
93+
public static boolean atMost(String version) {
94+
return jedisVersion.compareTo(parseVersion(version)) <= 0;
95+
}
96+
97+
}
Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2013 the original author or authors.
2+
* Copyright 2011-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,20 +15,16 @@
1515
*/
1616
package org.springframework.data.redis;
1717

18-
import java.util.regex.Matcher;
19-
import java.util.regex.Pattern;
20-
2118
import org.springframework.data.redis.connection.RedisConnection;
2219

2320
/**
2421
* Utilities for examining the Redis version
2522
*
2623
* @author Jennifer Hickey
24+
* @author Christoph Strobl
2725
*/
2826
public abstract class RedisVersionUtils {
2927

30-
private static final Pattern VERSION_MATCHER = Pattern.compile("([0-9]+)\\.([0-9]+)(\\.([0-9]+))?");
31-
3228
public static Version getRedisVersion(RedisConnection connection) {
3329
return parseVersion((String) connection.info().get("redis_version"));
3430
}
@@ -42,14 +38,11 @@ public static boolean atMost(String version, RedisConnection connection) {
4238
}
4339

4440
public static Version parseVersion(String version) {
45-
Matcher matcher = VERSION_MATCHER.matcher(version);
46-
if (matcher.matches()) {
47-
String major = matcher.group(1);
48-
String minor = matcher.group(2);
49-
String patch = matcher.group(4);
50-
return new Version(Integer.parseInt(major), minor != null ? Integer.parseInt(minor) : 0,
51-
patch != null ? Integer.parseInt(patch) : 0);
41+
42+
Version resolvedVersion = VersionParser.parseVersion(version);
43+
if (Version.UNKNOWN.equals(resolvedVersion)) {
44+
throw new IllegalArgumentException("Specified version cannot be parsed");
5245
}
53-
throw new IllegalArgumentException("Specified version cannot be parsed");
46+
return resolvedVersion;
5447
}
5548
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2014 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+
* http://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 org.springframework.data.redis;
17+
18+
import static org.hamcrest.core.IsEqual.*;
19+
import static org.junit.Assert.*;
20+
21+
import org.junit.Test;
22+
23+
/**
24+
* @author Christoph Strobl
25+
*/
26+
public class VersionParserUnitTests {
27+
28+
@Test
29+
public void shouldParseNullToUnknown() {
30+
assertThat(VersionParser.parseVersion(null), equalTo(Version.UNKNOWN));
31+
}
32+
33+
@Test
34+
public void shouldParseEmptyVersionStringToUnknown() {
35+
assertThat(VersionParser.parseVersion(""), equalTo(Version.UNKNOWN));
36+
}
37+
38+
@Test
39+
public void shouldParseInvalidVersionStringToUnknown() {
40+
assertThat(VersionParser.parseVersion("ThisIsNoValidVersion"), equalTo(Version.UNKNOWN));
41+
}
42+
43+
@Test
44+
public void shouldParseMajorMinorWithoutPatchCorrectly() {
45+
assertThat(VersionParser.parseVersion("1.2"), equalTo(new Version(1, 2, 0)));
46+
}
47+
48+
@Test
49+
public void shouldParseMajorMinorPatchCorrectly() {
50+
assertThat(VersionParser.parseVersion("1.2.3"), equalTo(new Version(1, 2, 3)));
51+
}
52+
53+
@Test
54+
public void shouldParseMajorWithoutMinorPatchCorrectly() {
55+
assertThat(VersionParser.parseVersion("1.2.3.a"), equalTo(new Version(1, 2, 3)));
56+
}
57+
}

src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,13 @@ public void testClosePool() {
117117
factory2.destroy();
118118
}
119119

120-
@Test(expected = UnsupportedOperationException.class)
120+
@Test
121121
public void testZAddSameScores() {
122122
Set<StringTuple> strTuples = new HashSet<StringTuple>();
123123
strTuples.add(new DefaultStringTuple("Bob".getBytes(), "Bob", 2.0));
124124
strTuples.add(new DefaultStringTuple("James".getBytes(), "James", 2.0));
125-
connection.zAdd("myset", strTuples);
125+
Long added = connection.zAdd("myset", strTuples);
126+
assertEquals(2L, added.longValue());
126127
}
127128

128129
@Test(expected = InvalidDataAccessApiUsageException.class)

0 commit comments

Comments
 (0)