From b3a2d990cc1f839e8aa1d3741bb986e1116bd418 Mon Sep 17 00:00:00 2001
From: brinn <brinn>
Date: Tue, 27 Mar 2012 14:45:38 +0000
Subject: [PATCH] Add: MatchClause.escape() for escaping query values and
 SearchService.searchForDataSets() and searchForSamples() which offer
 escaping.

SVN: 24788
---
 .../api/v1/impl/SearchService.java            | 18 ++++++++++--
 .../api/internal/v1/ISearchService.java       | 29 ++++++++++++++++++-
 .../shared/api/v1/dto/SearchCriteria.java     | 23 +++++++++++++++
 3 files changed, 67 insertions(+), 3 deletions(-)

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 7f7b03a42d0..fedc1ec2a70 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 dfd0fd25851..4689d760a22 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 39a74e8c037..2eb9b97e4de 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.
-- 
GitLab