Skip to content

Commit 335899c

Browse files
authored
Merge pull request #120 from opencb/TASK-7881
TASK-7881 - Can't filter by "not equals" with an "AND" operator
2 parents 12e81e5 + 6a637e3 commit 335899c

4 files changed

Lines changed: 118 additions & 35 deletions

File tree

commons-datastore/commons-datastore-core/src/main/java/org/opencb/commons/datastore/core/ObjectMap.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public class ObjectMap implements Map<String, Object>, Serializable {
3838

3939
private static final Pattern KEY_SPLIT_PATTERN = Pattern.compile("(^[^\\[\\].]+(?:\\[[^\\]]+\\])?)(?:\\.(.*))*");
4040
private static final Pattern LIST_FILTER_PATTERN = Pattern.compile("([^\\[\\]]+)\\[([^=]*?)(?:[=]?)([^=]+)\\]$");
41-
public static final Pattern COMMA_SEPARATED_LIST_SPLIT_PATTERN = Pattern.compile("((?:(?!,\\S).)+)+");
4241

4342
public ObjectMap() {
4443
objectMap = new LinkedHashMap<>();

commons-datastore/commons-datastore-core/src/test/java/org/opencb/commons/datastore/core/ObjectMapTest.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -263,35 +263,4 @@ public void testGetWithFilterFromList() {
263263
assertEquals("CGHI", objectMap.get("nestedList[nested.value=G].nested.list[id=Cghi].name"));
264264
}
265265

266-
@Test
267-
public void testPatternListSplit() {
268-
List<String> originalValues = Arrays.asList("disorder1", "disorder2, blabla", "disorder3");
269-
objectMap.put("key", StringUtils.join(originalValues, ","));
270-
objectMap.put("key1", "");
271-
objectMap.put("key2", "my value");
272-
objectMap.put("key3", Arrays.asList("1", "2"));
273-
objectMap.put("key4", Arrays.asList(1, 2));
274-
275-
List<String> values = objectMap.getAsStringList("key", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
276-
assertEquals(originalValues.size(), values.size());
277-
assertTrue(originalValues.containsAll(values));
278-
279-
values = objectMap.getAsStringList("key1", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
280-
assertEquals(1, values.size());
281-
assertEquals("", values.get(0));
282-
283-
values = objectMap.getAsStringList("key2", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
284-
assertEquals(1, values.size());
285-
assertEquals("my value", values.get(0));
286-
287-
values = objectMap.getAsStringList("key3", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
288-
assertEquals(2, values.size());
289-
assertEquals("1", values.get(0));
290-
assertEquals("2", values.get(1));
291-
292-
values = objectMap.getAsStringList("key4", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
293-
assertEquals(2, values.size());
294-
assertEquals("1", values.get(0));
295-
assertEquals("2", values.get(1));
296-
}
297266
}

commons-datastore/commons-datastore-mongodb/src/main/java/org/opencb/commons/datastore/mongodb/MongoDBQueryUtils.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636

3737
import static com.mongodb.client.model.Aggregates.*;
3838
import static com.mongodb.client.model.Projections.*;
39+
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.*;
3940
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.bucket;
4041
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.count;
41-
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.*;
4242

4343
/**
4444
* Created by imedina on 17/01/16.
@@ -178,6 +178,53 @@ public static Bson createFilter(String mongoDbField, String queryParam, Query qu
178178
return filter;
179179
}
180180

181+
/**
182+
* Splits a string by the given separator, handling quoted values properly.
183+
* Quoted values can contain the separator character without being split.
184+
* Removes surrounding quotes and trims whitespace from each value.
185+
*
186+
* @param input the input string to split
187+
* @param separator the separator to split by ("," or ";")
188+
* @return list of trimmed, unquoted values
189+
*/
190+
public static List<String> smartSplit(String input, String separator) {
191+
List<String> result = new ArrayList<>();
192+
if (input == null || input.isEmpty()) {
193+
return result;
194+
}
195+
196+
boolean inQuotes = false;
197+
StringBuilder currentValue = new StringBuilder();
198+
199+
for (int i = 0; i < input.length(); i++) {
200+
char c = input.charAt(i);
201+
202+
if (c == '"') {
203+
inQuotes = !inQuotes;
204+
} else if (!inQuotes && input.substring(i).startsWith(separator)) {
205+
// Found separator outside quotes
206+
String value = currentValue.toString().trim();
207+
if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
208+
value = value.substring(1, value.length() - 1);
209+
}
210+
result.add(value.trim());
211+
currentValue = new StringBuilder();
212+
i += separator.length() - 1; // Skip the separator
213+
} else {
214+
currentValue.append(c);
215+
}
216+
}
217+
218+
// Add the last value
219+
String value = currentValue.toString().trim();
220+
if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
221+
value = value.substring(1, value.length() - 1);
222+
}
223+
result.add(value.trim());
224+
225+
return result;
226+
}
227+
181228
private static String getLogicalSeparator(LogicalOperator operator) {
182229
return (operator != null && operator.equals(LogicalOperator.AND)) ? AND : OR;
183230
}
@@ -258,8 +305,13 @@ protected static String getOp2(String op, String value) {
258305

259306
public static Bson createAutoFilter(String mongoDbField, String queryParam, Query query, QueryParam.Type type, LogicalOperator operator)
260307
throws NumberFormatException {
261-
262-
List<String> queryParamList = query.getAsStringList(queryParam, getLogicalSeparator(operator));
308+
List<String> queryParamList;
309+
String value = query.getString(queryParam);
310+
if (StringUtils.isNotEmpty(value) && value.contains("\"")) {
311+
queryParamList = smartSplit(value, getLogicalSeparator(operator));
312+
} else {
313+
queryParamList = query.getAsStringList(queryParam, getLogicalSeparator(operator));
314+
}
263315
return createAutoFilter(mongoDbField, queryParam, type, operator, queryParamList);
264316
}
265317

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.opencb.commons.datastore.mongodb;
2+
3+
import org.junit.Test;
4+
import java.util.List;
5+
import static org.junit.Assert.assertEquals;
6+
7+
public class SmartSplitTest {
8+
9+
@Test
10+
public void testSmartSplitWithQuotedCommaValues() {
11+
String input = "\"a \",\" b\",\" c \"";
12+
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");
13+
14+
assertEquals(3, result.size());
15+
assertEquals("a", result.get(0));
16+
assertEquals("b", result.get(1));
17+
assertEquals("c", result.get(2));
18+
}
19+
20+
@Test
21+
public void testSmartSplitWithQuotedSemicolonValues() {
22+
String input = "\"a \";\" b\";\" c \"";
23+
List<String> result = MongoDBQueryUtils.smartSplit(input, ";");
24+
25+
assertEquals(3, result.size());
26+
assertEquals("a", result.get(0));
27+
assertEquals("b", result.get(1));
28+
assertEquals("c", result.get(2));
29+
}
30+
31+
@Test
32+
public void testSmartSplitWithNonQuotedValues() {
33+
String input = "a,b,c";
34+
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");
35+
36+
assertEquals(3, result.size());
37+
assertEquals("a", result.get(0));
38+
assertEquals("b", result.get(1));
39+
assertEquals("c", result.get(2));
40+
}
41+
42+
@Test
43+
public void testSmartSplitWithNonQuotedValuesAndSpaces() {
44+
String input = "a, b,c ";
45+
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");
46+
47+
assertEquals(3, result.size());
48+
assertEquals("a", result.get(0));
49+
assertEquals("b", result.get(1));
50+
assertEquals("c", result.get(2));
51+
}
52+
53+
@Test
54+
public void testSmartSplitWithMixedValues() {
55+
String input = "\"a, with comma\",b,\"c\"";
56+
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");
57+
58+
assertEquals(3, result.size());
59+
assertEquals("a, with comma", result.get(0));
60+
assertEquals("b", result.get(1));
61+
assertEquals("c", result.get(2));
62+
}
63+
}

0 commit comments

Comments
 (0)