diff --git a/MetFragLib/src/main/java/de/ipbhalle/metfraglib/parameter/ParameterDataTypes.java b/MetFragLib/src/main/java/de/ipbhalle/metfraglib/parameter/ParameterDataTypes.java index 8a2f0208..321f9532 100644 --- a/MetFragLib/src/main/java/de/ipbhalle/metfraglib/parameter/ParameterDataTypes.java +++ b/MetFragLib/src/main/java/de/ipbhalle/metfraglib/parameter/ParameterDataTypes.java @@ -1,6 +1,8 @@ package de.ipbhalle.metfraglib.parameter; import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; import org.apache.log4j.Level; @@ -264,15 +266,71 @@ public static Object getParameter(String parameter, String parameterName) throws values[i] = Double.parseDouble(tmp[i]); return values; } - if(type.equals("String[]")) { - String[] tmp = parameter.split(","); - for(int i = 0; i < tmp.length; i++) - tmp[i] = tmp[i].trim(); - return tmp; + if (type.equals("String[]")) { + // Special handling for SMARTS inclusion and exclusion lists + if (parameterName.equals(VariableNames.PRE_CANDIDATE_FILTER_SMARTS_INCLUSION_LIST_NAME) + || parameterName.equals(VariableNames.PRE_CANDIDATE_FILTER_SMARTS_EXCLUSION_LIST_NAME)) { + return splitSmartsString(parameter); + } else { + String[] tmp = parameter.split(","); + for (int i = 0; i < tmp.length; i++) + tmp[i] = tmp[i].trim(); + return tmp; + } } return parameter; } - + + /** + * Splits a string containing multiple SMARTS patterns separated by commas into an array of individual SMARTS patterns. + * This method is designed to handle the complexity of SMARTS syntax, which may include commas as part of the pattern + * rather than separators. + * + * Specifically, it ignores commas that are: + * - Inside square brackets, which are used for atom specifications in SMARTS. + * - Surrounded by bond primitives (e.g., '-', '/', '\\', '?', '=', '#', ':', '~', '@') or the not operator '!', + * as these commas are part of the SMARTS pattern. + * + * @param input A string containing multiple SMARTS patterns separated by commas. + * @return An array of individual SMARTS patterns. + */ + public static String[] splitSmartsString(String input) { + + List substrings = new ArrayList<>(); + int start = 0; + int squareBracketCount = 0; + String bondPrimitives = "-/\\?=#:~@!"; + + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + if (c == '[') { + squareBracketCount++; + } else if (c == ']') { + squareBracketCount--; + } else if (c == ',' && squareBracketCount == 0) { + + // Check if the comma is surrounded by bond primitives or the not operator "!". + // If so, skip this comma as it's part of the SMARTS pattern, not a separator. + if (i > 0 && i + 1 < input.length() // Check if the comma is not at the beginning or the end of the string + && bondPrimitives.indexOf(input.charAt(i - 1)) != -1 + && bondPrimitives.indexOf(input.charAt(i + 1)) != -1) { + continue; + } + + String substring = input.substring(start, i).trim(); + if (!substring.isEmpty()) { + substrings.add(substring); + } + start = i + 1; + } + } + String lastSubstring = input.substring(start).trim(); + if (!lastSubstring.isEmpty()) { + substrings.add(lastSubstring); + } + return substrings.toArray(new String[substrings.size()]); + } + public static String getType(String parameterName) { if(!parameterDatatypes.containsKey(parameterName)) return ""; return parameterDatatypes.get(parameterName); diff --git a/MetFragLib/src/test/java/de/ipbhalle/metfraglib/parameter/CheckParameterDataType_Test.java b/MetFragLib/src/test/java/de/ipbhalle/metfraglib/parameter/CheckParameterDataType_Test.java index b0dd0f04..8ad5cfad 100644 --- a/MetFragLib/src/test/java/de/ipbhalle/metfraglib/parameter/CheckParameterDataType_Test.java +++ b/MetFragLib/src/test/java/de/ipbhalle/metfraglib/parameter/CheckParameterDataType_Test.java @@ -29,6 +29,29 @@ public void test() { } } + @Test + public void testSplitSmartsList() { + /* + * check SMARTS list string splitting + */ + try { + String[] smartsListExpected = { + "C(=O)-O", // no comma in SMARTS + "[C,O]-c1ccccc1", // comma in a pair of square brackets + "C-,=C@,!-N", // comma between bond primitives and not operator "!" + "[$(c1(-[O,N])ccccc1),$(c1c(-[O,N])cccc1)]-C(=O)-O", // comma in nested square brackets + }; + String smartsListString = String.join(",", smartsListExpected); + String[] smartsListActual = (String[]) ParameterDataTypes.getParameter(smartsListString, + VariableNames.PRE_CANDIDATE_FILTER_SMARTS_INCLUSION_LIST_NAME); + assertArrayEquals("\"" + smartsListString + "\" " + VariableNames.PRE_CANDIDATE_FILTER_SMARTS_INCLUSION_LIST_NAME + " was wrongly split", + smartsListExpected, + smartsListActual); + } catch (ParameterNotKnownException e) { + fail(e.getMessage()); + } + } + /** * check exception *