Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public class ObjectMap implements Map<String, Object>, Serializable {

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

public ObjectMap() {
objectMap = new LinkedHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,35 +263,4 @@ public void testGetWithFilterFromList() {
assertEquals("CGHI", objectMap.get("nestedList[nested.value=G].nested.list[id=Cghi].name"));
}

@Test
public void testPatternListSplit() {
List<String> originalValues = Arrays.asList("disorder1", "disorder2, blabla", "disorder3");
objectMap.put("key", StringUtils.join(originalValues, ","));
objectMap.put("key1", "");
objectMap.put("key2", "my value");
objectMap.put("key3", Arrays.asList("1", "2"));
objectMap.put("key4", Arrays.asList(1, 2));

List<String> values = objectMap.getAsStringList("key", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
assertEquals(originalValues.size(), values.size());
assertTrue(originalValues.containsAll(values));

values = objectMap.getAsStringList("key1", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
assertEquals(1, values.size());
assertEquals("", values.get(0));

values = objectMap.getAsStringList("key2", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
assertEquals(1, values.size());
assertEquals("my value", values.get(0));

values = objectMap.getAsStringList("key3", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
assertEquals(2, values.size());
assertEquals("1", values.get(0));
assertEquals("2", values.get(1));

values = objectMap.getAsStringList("key4", ObjectMap.COMMA_SEPARATED_LIST_SPLIT_PATTERN);
assertEquals(2, values.size());
assertEquals("1", values.get(0));
assertEquals("2", values.get(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@

import static com.mongodb.client.model.Aggregates.*;
import static com.mongodb.client.model.Projections.*;
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.*;
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.bucket;
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.count;
import static org.opencb.commons.datastore.mongodb.MongoDBQueryUtils.Accumulator.*;

/**
* Created by imedina on 17/01/16.
Expand Down Expand Up @@ -178,6 +178,53 @@ public static Bson createFilter(String mongoDbField, String queryParam, Query qu
return filter;
}

/**
* Splits a string by the given separator, handling quoted values properly.
* Quoted values can contain the separator character without being split.
* Removes surrounding quotes and trims whitespace from each value.
*
* @param input the input string to split
* @param separator the separator to split by ("," or ";")
* @return list of trimmed, unquoted values
*/
public static List<String> smartSplit(String input, String separator) {
List<String> result = new ArrayList<>();
if (input == null || input.isEmpty()) {
return result;
}

boolean inQuotes = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there are unbalanced quotes?

"value1","value 2","value3

StringBuilder currentValue = new StringBuilder();

for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);

if (c == '"') {
inQuotes = !inQuotes;
} else if (!inQuotes && input.substring(i).startsWith(separator)) {
// Found separator outside quotes
String value = currentValue.toString().trim();
if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
value = value.substring(1, value.length() - 1);
}
result.add(value.trim());
currentValue = new StringBuilder();
i += separator.length() - 1; // Skip the separator
} else {
currentValue.append(c);
}
}

// Add the last value
String value = currentValue.toString().trim();
if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
value = value.substring(1, value.length() - 1);
}
result.add(value.trim());

return result;
}

private static String getLogicalSeparator(LogicalOperator operator) {
return (operator != null && operator.equals(LogicalOperator.AND)) ? AND : OR;
}
Expand Down Expand Up @@ -258,8 +305,13 @@ protected static String getOp2(String op, String value) {

public static Bson createAutoFilter(String mongoDbField, String queryParam, Query query, QueryParam.Type type, LogicalOperator operator)
throws NumberFormatException {

List<String> queryParamList = query.getAsStringList(queryParam, getLogicalSeparator(operator));
List<String> queryParamList;
String value = query.getString(queryParam);
if (StringUtils.isNotEmpty(value) && value.contains("\"")) {
queryParamList = smartSplit(value, getLogicalSeparator(operator));
} else {
queryParamList = query.getAsStringList(queryParam, getLogicalSeparator(operator));
}
return createAutoFilter(mongoDbField, queryParam, type, operator, queryParamList);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.opencb.commons.datastore.mongodb;

import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertEquals;

public class SmartSplitTest {

@Test
public void testSmartSplitWithQuotedCommaValues() {
String input = "\"a \",\" b\",\" c \"";
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");

assertEquals(3, result.size());
assertEquals("a", result.get(0));
assertEquals("b", result.get(1));
assertEquals("c", result.get(2));
}

@Test
public void testSmartSplitWithQuotedSemicolonValues() {
String input = "\"a \";\" b\";\" c \"";
List<String> result = MongoDBQueryUtils.smartSplit(input, ";");

assertEquals(3, result.size());
assertEquals("a", result.get(0));
assertEquals("b", result.get(1));
assertEquals("c", result.get(2));
}

@Test
public void testSmartSplitWithNonQuotedValues() {
String input = "a,b,c";
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");

assertEquals(3, result.size());
assertEquals("a", result.get(0));
assertEquals("b", result.get(1));
assertEquals("c", result.get(2));
}

@Test
public void testSmartSplitWithNonQuotedValuesAndSpaces() {
String input = "a, b,c ";
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");

assertEquals(3, result.size());
assertEquals("a", result.get(0));
assertEquals("b", result.get(1));
assertEquals("c", result.get(2));
}

@Test
public void testSmartSplitWithMixedValues() {
String input = "\"a, with comma\",b,\"c\"";
List<String> result = MongoDBQueryUtils.smartSplit(input, ",");

assertEquals(3, result.size());
assertEquals("a, with comma", result.get(0));
assertEquals("b", result.get(1));
assertEquals("c", result.get(2));
}
}
Loading