diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java index 7f7b03a42d0e3be71f65d3a7494db5abfb80f1bb..fedc1ec2a70d637e726d32ada21234e06791831a 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java @@ -72,6 +72,12 @@ class SearchService implements ISearchService public List<IDataSetImmutable> searchForDataSets(String property, String value, String typeOrNull) + { + return searchForDataSets(property, value, typeOrNull, false); + } + + public List<IDataSetImmutable> searchForDataSets(String property, String value, + String typeOrNull, boolean escape) { SearchCriteria sc = new SearchCriteria(); if (null != typeOrNull) @@ -79,11 +85,18 @@ class SearchService implements ISearchService sc.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE, typeOrNull)); } - sc.addMatchClause(MatchClause.createPropertyMatch(property, value)); + sc.addMatchClause(MatchClause.createPropertyMatch(property, + escape ? MatchClause.escape(value) : value)); return searchForDataSets(sc); } public List<ISampleImmutable> searchForSamples(String property, String value, String typeOrNull) + { + return searchForSamples(property, value, typeOrNull, false); + } + + public List<ISampleImmutable> searchForSamples(String property, String value, + String typeOrNull, boolean escape) { SearchCriteria sc = new SearchCriteria(); if (null != typeOrNull) @@ -91,7 +104,8 @@ class SearchService implements ISearchService sc.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE, typeOrNull)); } - sc.addMatchClause(MatchClause.createPropertyMatch(property, value)); + sc.addMatchClause(MatchClause.createPropertyMatch(property, + escape ? MatchClause.escape(value) : value)); return searchForSamples(sc); } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java index dfd0fd2585169e39ffe37dfb5550919487943bea..4689d760a220c148aed15f0f9ba8f90df45bbf5f 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java @@ -41,7 +41,21 @@ public interface ISearchService * @param value The value the property should have. This may contain wildcards. * @return A list of matching data sets. */ - public List<IDataSetImmutable> searchForDataSets(String property, String value, String typeOrNul); + public List<IDataSetImmutable> searchForDataSets(String property, String value, + String typeOrNull); + + /** + * List all data sets with a given value for a particular property, optionally restricted to a + * specific type. + * + * @param property The property of interest. + * @param value The value the property should have. This may contain wildcards if + * <var>escape</var> is set to <code>false</code>. + * @param escape If <code>true</code>, escape the <var>value</var> to search for it verbatimly. + * @return A list of matching data sets. + */ + public List<IDataSetImmutable> searchForDataSets(String property, String value, + String typeOrNull, boolean escape); /** * List all samples with a given value for a particular property, optionally restricted to a @@ -53,6 +67,19 @@ public interface ISearchService */ public List<ISampleImmutable> searchForSamples(String property, String value, String typeOrNull); + /** + * List all samples with a given value for a particular property, optionally restricted to a + * specific type. + * + * @param property The property of interest. + * @param value The value the property should have. This may contain wildcards if + * <var>escape</var> is set to <code>false</code>. + * @param escape If <code>true</code>, escape the <var>value</var> to search for it verbatimly. + * @return A list of matching samples. + */ + public List<ISampleImmutable> searchForSamples(String property, String value, + String typeOrNull, boolean escape); + /** * List all data sets that match the given searchCriteria. * diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchCriteria.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchCriteria.java index 39a74e8c03728a88f0899b70b79a0d754ca6f1cd..2eb9b97e4de0fb614fe87c19d843b1b54709371a 100644 --- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchCriteria.java +++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SearchCriteria.java @@ -170,6 +170,29 @@ public class SearchCriteria implements Serializable return new AttributeMatchClause(attribute, mode, date); } + /** + * Returns a String where those characters that Lucene expects to be escaped are + * escaped by a preceding <code>\</code>. + * <p> + * Copy of Lucene's <code>QueryParser.escape()</code> method. + */ + public static String escape(String s) + { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) + { + final char c = s.charAt(i); + // These characters are part of the query syntax and must be escaped + if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' + || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' + || c == '~' || c == '*' || c == '?' || c == '|' || c == '&') + { + sb.append('\\'); + } + sb.append(c); + } + return sb.toString(); + } /** * The field type this MatchClause matches against. Could be either a property or attribute.