diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
index 861f277a405c269549399ab5e8915e34c7c813b8..248a9ef81e26288318de333616b8a6f0e0ff1951 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
@@ -60,10 +60,12 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IShareIdManager;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ProcessingStatus;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISequenceDatabase;
 import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImportFile;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescription;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IDatasetLocation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
@@ -502,6 +504,49 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
             QueueingPathRemoverService.removeRecursively(sessionWorkspace);
         }
     }
+    
+    @Override
+    public List<SequenceSearchResult> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull)
+    {
+        PluginTaskProvider<ISequenceDatabase> provider = pluginTaskInfoProvider.getSequenceDatabasesProvider();
+        ISequenceDatabase sequenceDatabase = findSequenceDatabase(provider, preferredSequenceDatabaseOrNull);
+        if (sequenceDatabase != null)
+        {
+            List<SequenceSearchResult> result = sequenceDatabase.search(sequenceSnippet, optionalParametersOrNull);
+            for (SequenceSearchResult sequenceSearchResult : result)
+            {
+                sequenceSearchResult.setSequenceDatabaseName(sequenceDatabase.getName());
+            }
+            return result;
+        }
+        operationLog.warn("No available sequence database found.");
+        return new ArrayList<SequenceSearchResult>();
+    }
+    
+    private ISequenceDatabase findSequenceDatabase(PluginTaskProvider<ISequenceDatabase> provider, 
+            String preferredSequenceDatabaseOrNull)
+    {
+        List<DatastoreServiceDescription> pluginDescriptions = provider.getPluginDescriptions();
+        ISequenceDatabase availableDatabase = null;
+        for (DatastoreServiceDescription description : pluginDescriptions)
+        {
+            ISequenceDatabase database = provider.getPluginInstance(description.getKey());
+            if (database.isAvailable())
+            {
+                if (description.getKey().equals(preferredSequenceDatabaseOrNull))
+                {
+                    return database;
+                }
+                if (availableDatabase == null)
+                {
+                    availableDatabase = database;
+                }
+            }
+        }
+        return availableDatabase;
+    }
 
     private PutDataSetService getPutDataSetService()
     {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
index 86859ebe1a448e06e73404bf7198119eeabbb113..1466957fab368b7466c8d53ce83835e631241990 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
@@ -26,8 +26,9 @@ import ch.systemsx.cisd.common.resource.IInitializable;
 import ch.systemsx.cisd.common.serviceconversation.ServiceMessage;
 import ch.systemsx.cisd.openbis.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImportFile;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImportFile;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IDatasetLocation;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
@@ -194,4 +195,14 @@ class DataStoreServiceLogger implements IDataStoreService, IInitializable
     {
         log("cleanupSession", "USER_SESSION(%s)", userSessionToken);
     }
+
+    @Override
+    public List<SequenceSearchResult> searchForDataSetsWithSequences(String sessionToken, 
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet, 
+            Map<String, String> optionalParametersOrNull)
+    {
+        log("searchForDataSetsWithSequences", "SEQUENCE_DATABASE(%s) SEQUENCE_SNIPPET(%s)", 
+                preferredSequenceDatabaseOrNull, sequenceSnippet);
+        return null;
+    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v2/sequencedatabases/AbstractSequenceDatabase.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v2/sequencedatabases/AbstractSequenceDatabase.java
new file mode 100644
index 0000000000000000000000000000000000000000..41f119859f94c0cd64a0d13ad3e6604bad22b1c1
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v2/sequencedatabases/AbstractSequenceDatabase.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014 ETH Zuerich, SIS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.server.api.v2.sequencedatabases;
+
+import java.io.File;
+import java.util.Properties;
+
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.PluginTaskFactory;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISequenceDatabase;
+
+/**
+ * Abstract super class of all {@link ISequenceDatabase} implementations which get the name from 
+ * the property {@link PluginTaskFactory#LABEL_PROPERTY_NAME}.
+ *
+ * @author Franz-Josef Elmer
+ */
+public abstract class AbstractSequenceDatabase implements ISequenceDatabase
+{
+    private final String name;
+
+    protected AbstractSequenceDatabase(Properties properties, File storeRoot)
+    {
+        name = properties.getProperty(PluginTaskFactory.LABEL_PROPERTY_NAME);
+    }
+    
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v2/sequencedatabases/BlastDatabase.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v2/sequencedatabases/BlastDatabase.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e8105cb7f43a9d87c54ddb1fc05cd0405c8e5c1
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v2/sequencedatabases/BlastDatabase.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014 ETH Zuerich, SIS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.server.api.v2.sequencedatabases;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
+import ch.systemsx.cisd.common.fasta.FastaUtilities;
+import ch.systemsx.cisd.common.fasta.SequenceType;
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.process.ProcessExecutionHelper;
+import ch.systemsx.cisd.common.process.ProcessResult;
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.BlastUtils;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class BlastDatabase extends AbstractSequenceDatabase
+{
+    public static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, BlastDatabase.class);
+    private static final Logger machineLog =
+            LogFactory.getLogger(LogCategory.MACHINE, BlastDatabase.class);
+    private static final String QUERY_FILE_NAME_TEMPLATE = "query-{0,date,yyyyMMDDHHmmssSSS}-{1}.fasta";
+    private static final Pattern STITLE_PATTERN = Pattern.compile("(.*) \\[Data set: (.*), File: (.*)\\]$"); 
+
+    private final File databaseFolder;
+    private final String blastn;
+    private final String blastp;
+    private final boolean available;
+    private final File queriesFolder;
+    
+    private AtomicInteger counter = new AtomicInteger();
+
+    public BlastDatabase(Properties properties, File storeRoot)
+    {
+        super(properties, storeRoot);
+        String blastToolDirectory = BlastUtils.getBLASTToolDirectory(properties);
+        blastn = blastToolDirectory + "blastn";
+        blastp = blastToolDirectory + "blastp";
+        available = process(blastn, "-version");
+        if (available == false)
+        {
+            BlastUtils.logMissingTools(operationLog);
+        }
+        databaseFolder = BlastUtils.getBlastDatabaseFolder(properties, storeRoot);
+        queriesFolder = new File(databaseFolder, "queries-folder");
+        queriesFolder.mkdirs();
+    }
+
+    @Override
+    public boolean isAvailable()
+    {
+        return available;
+    }
+    
+    @Override
+    public List<SequenceSearchResult> search(String sequenceSnippet, Map<String, String> optionalParameters)
+    {
+        List<SequenceSearchResult> result = new ArrayList<SequenceSearchResult>();
+        SequenceType sequenceType = FastaUtilities.determineSequenceType(sequenceSnippet);
+        String queryFileName = new MessageFormat(QUERY_FILE_NAME_TEMPLATE).format(
+                new Object[] {new Date(), counter.getAndIncrement()});
+        File queryFile = new File(queriesFolder, queryFileName);
+        try
+        {
+            FileUtilities.writeToFile(queryFile, ">query\n" + sequenceSnippet + "\n");
+            List<String> command = createCommand(sequenceType, queryFile);
+            List<String> output = processAndDeliverOutput(command);
+            for (String line : output)
+            {
+                String[] row = line.split("\t");
+                Matcher matcher = STITLE_PATTERN.matcher(row[0]);
+                if (matcher.matches())
+                {
+                    SequenceSearchResult sequenceSearchResult = new SequenceSearchResult();
+                    sequenceSearchResult.setSequenceIdentifier(matcher.group(1));
+                    sequenceSearchResult.setDataSetCode(matcher.group(2));
+                    sequenceSearchResult.setPathInDataSet(matcher.group(3));
+                    sequenceSearchResult.setPositionInSequence(parse(row[1]));
+                    result.add(sequenceSearchResult);
+                }
+            }
+        } finally
+        {
+            FileUtilities.delete(queryFile);
+        }
+        return result;
+    }
+    
+    private int parse(String number)
+    {
+        try
+        {
+            return Integer.parseInt(number);
+        } catch (NumberFormatException ex)
+        {
+            return -1;
+        }
+    }
+
+    private List<String> createCommand(SequenceType sequenceType, File queryFile)
+    {
+        List<String> command = new ArrayList<String>();
+        if (sequenceType == SequenceType.NUCL)
+        {
+            command.add(blastn);
+            command.add("-task");
+            command.add("blastn");
+        } else
+        {
+            command.add(blastp);
+            command.add("-task");
+            command.add("blastp");
+        }
+        command.add("-db");
+        command.add(databaseFolder.getAbsolutePath() + "/all-" + sequenceType.toString().toLowerCase());
+        command.add("-query");
+        command.add(queryFile.getAbsolutePath());
+        command.add("-outfmt");
+        command.add("6 stitle sstart");
+        return command;
+    }
+    
+    private boolean process(String... command)
+    {
+        ProcessResult processResult = ProcessExecutionHelper.run(Arrays.asList(command), operationLog, machineLog);
+        if (processResult.isOK())
+        {
+            processResult.logAsInfo();
+        } else
+        {
+            processResult.log();
+        }
+        return processResult.isOK();
+    }
+
+    private List<String> processAndDeliverOutput(List<String> command)
+    {
+        ProcessResult processResult = ProcessExecutionHelper.run(command, operationLog, machineLog);
+        List<String> output = processResult.getOutput();
+        if (processResult.isOK())
+        {
+            return output;
+        }
+        StringBuilder builder = new StringBuilder("Execution failed: ").append(command);
+        List<String> lines = processResult.isBinaryOutput() ? processResult.getErrorOutput() : output;
+        for (String line : lines)
+        {
+            builder.append("\n").append(line);
+        }
+        processResult.log();
+        throw new EnvironmentFailureException(builder.toString()); 
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DecoratingTableModelReportingPlugin.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DecoratingTableModelReportingPlugin.java
index a5c2f1dd094f068172d2565ebb7922e948e16f46..6b01307630b2902a4d601f56410b4c9d5f1f1e97 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DecoratingTableModelReportingPlugin.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DecoratingTableModelReportingPlugin.java
@@ -25,7 +25,7 @@ import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.properties.ExtendedProperties;
 import ch.systemsx.cisd.common.properties.PropertyUtils;
 import ch.systemsx.cisd.common.reflection.ClassUtils;
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.AbstractPluginTaskFactory;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.PluginTaskFactory;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IReportingPluginTask;
 import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext;
 import ch.systemsx.cisd.openbis.generic.shared.basic.ITableModelTransformation;
@@ -71,7 +71,7 @@ public class DecoratingTableModelReportingPlugin extends AbstractTableModelRepor
     {
         String className =
                 PropertyUtils.getMandatoryProperty(pluginProperties,
-                        AbstractPluginTaskFactory.CLASS_PROPERTY_NAME);
+                        PluginTaskFactory.CLASS_PROPERTY_NAME);
         try
         {
             return ClassUtils.create(IReportingPluginTask.class, className, pluginProperties,
@@ -87,7 +87,7 @@ public class DecoratingTableModelReportingPlugin extends AbstractTableModelRepor
     {
         String className =
                 PropertyUtils.getMandatoryProperty(transformationProperties,
-                        AbstractPluginTaskFactory.CLASS_PROPERTY_NAME);
+                        PluginTaskFactory.CLASS_PROPERTY_NAME);
         try
         {
             return ClassUtils.create(ITableModelTransformation.class, className,
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IPluginTaskInfoProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IPluginTaskInfoProvider.java
index de73f4669403a1d45537ca661bf5bc3caf2708a1..be60e2671affa58cba50ecdc4082d3271d28558e 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IPluginTaskInfoProvider.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/IPluginTaskInfoProvider.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks;
 
 import java.io.File;
 
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISequenceDatabase;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions;
 
 /**
@@ -41,6 +42,8 @@ public interface IPluginTaskInfoProvider
     public PluginTaskProvider<IReportingPluginTask> getReportingPluginsProvider();
 
     public PluginTaskProvider<IProcessingPluginTask> getProcessingPluginsProvider();
+    
+    public PluginTaskProvider<ISequenceDatabase> getSequenceDatabasesProvider();
 
     public ArchiverPluginFactory getArchiverPluginFactory();
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/AbstractPluginTaskFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskFactory.java
similarity index 91%
rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/AbstractPluginTaskFactory.java
rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskFactory.java
index 10af3443b24c310b7383f7cc0cd42bb4b186a1a2..42d4f74e9aca3e4ece1c16cc1ca7c1ae79dac7c9 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/AbstractPluginTaskFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskFactory.java
@@ -40,22 +40,18 @@ import ch.systemsx.cisd.common.properties.PropertyUtils;
 import ch.systemsx.cisd.common.properties.PropertyParametersUtil.SectionProperties;
 import ch.systemsx.cisd.common.reflection.ClassUtils;
 import ch.systemsx.cisd.openbis.dss.generic.server.IServletPropertiesManager;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISequenceDatabase;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DssPropertyParametersUtil;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescription;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ReportingPluginType;
 
 /**
- * Abstract class for a factory of plugin tasks.
+ * Factory of plugin tasks.
  * 
  * @author Tomasz Pylak
  */
-public abstract class AbstractPluginTaskFactory<T>
+public class PluginTaskFactory<T>
 {
-    /**
-     * Logs the current parameters to the {@link LogCategory#OPERATION} log.
-     */
-    abstract public void logConfiguration();
-
     /** Property name which stores a plugin label. */
     @Private
     public final static String LABEL_PROPERTY_NAME = "label";
@@ -81,7 +77,7 @@ public abstract class AbstractPluginTaskFactory<T>
     public final static String PARAMS_FILE_PATH_PROPERTY_NAME = "properties-file";
 
     private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
-            AbstractPluginTaskFactory.class);
+            PluginTaskFactory.class);
 
     private final DatastoreServiceDescription description;
 
@@ -91,10 +87,13 @@ public abstract class AbstractPluginTaskFactory<T>
 
     private final T pluginInstance;
 
-    protected AbstractPluginTaskFactory(IServletPropertiesManager servletPropertiesManager,
-            SectionProperties sectionProperties, String datastoreCode, Class<T> clazz,
+    private final String pluginTaskName;
+
+    public PluginTaskFactory(IServletPropertiesManager servletPropertiesManager,
+            SectionProperties sectionProperties, String datastoreCode, Class<T> clazz, String pluginTaskName,
             File storeRoot)
     {
+        this.pluginTaskName = pluginTaskName;
         Properties pluginProperties = sectionProperties.getProperties();
         String label = PropertyUtils.getMandatoryProperty(pluginProperties, LABEL_PROPERTY_NAME);
         Properties props =
@@ -129,6 +128,11 @@ public abstract class AbstractPluginTaskFactory<T>
             this.description =
                     DatastoreServiceDescription.reporting(pluginKey, label, datasetCodes,
                             datastoreCode, type);
+        } else if (pluginInstance instanceof ISequenceDatabase)
+        {
+            this.description =
+                    DatastoreServiceDescription.processing(pluginKey, label, new String[0],
+                            datastoreCode);
         } else
         {
             String[] datasetCodes = extractDatasetCodes(pluginProperties);
@@ -137,6 +141,17 @@ public abstract class AbstractPluginTaskFactory<T>
                             datastoreCode);
         }
     }
+    
+    /**
+     * Logs the current parameters to the {@link LogCategory#OPERATION} log.
+     */
+    public void logConfiguration()
+    {
+        String key = getPluginDescription().getKey();
+        operationLog.info(String.format(pluginTaskName + " '%s' configuration:", key));
+        logPropertiesConfiguration();
+    }
+
 
     /**
      * Returns an instance of a plugin task
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java
index 7597a248b9814440a819fb50ec21ff2d34fc4ca9..0a926633da7a43b96739275f28901be7eb749188 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java
@@ -17,6 +17,8 @@
 package ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 
 import ch.rinn.restrictions.Private;
@@ -25,6 +27,7 @@ import ch.systemsx.cisd.common.properties.PropertyParametersUtil.SectionProperti
 import ch.systemsx.cisd.openbis.dss.generic.server.DataStoreServer;
 import ch.systemsx.cisd.openbis.dss.generic.server.IServletPropertiesManager;
 import ch.systemsx.cisd.openbis.dss.generic.shared.Constants;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISequenceDatabase;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DssPropertyParametersUtil;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.SessionWorkspaceUtil;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions;
@@ -46,12 +49,15 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
 
     private final PluginTaskProvider<IProcessingPluginTask> processingPlugins;
 
+    private final PluginTaskProvider<ISequenceDatabase> sequenceDatabasePlugins;
+    
     private final ArchiverPluginFactory archiverTaskFactory;
 
     private final File storeRoot;
 
     private final File sessionWorkspaceRootDir;
 
+
     /** for external injections */
     public static IPluginTaskInfoProvider create()
     {
@@ -83,6 +89,9 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
         this.processingPlugins =
                 createProcessingPluginsFactories(serviceProperties, servletPropertiesManager,
                         datastoreCode, storeRoot);
+        sequenceDatabasePlugins = createPluginsFactories(serviceProperties, servletPropertiesManager, 
+                datastoreCode, storeRoot, ISequenceDatabase.class, "Sequence database", 
+                Constants.SEQUENCE_DATABASES_NAMES);
         this.archiverTaskFactory = createArchiverTaskFactory(serviceProperties, datastoreCode);
     }
 
@@ -116,6 +125,12 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
         return processingPlugins;
     }
 
+    @Override
+    public PluginTaskProvider<ISequenceDatabase> getSequenceDatabasesProvider()
+    {
+        return sequenceDatabasePlugins;
+    }
+
     @Override
     public ArchiverPluginFactory getArchiverPluginFactory()
     {
@@ -126,6 +141,7 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
     {
         processingPlugins.check(true);
         reportingPlugins.check(false);
+        sequenceDatabasePlugins.check(false);
         archiverTaskFactory.check(storeRoot);
     }
 
@@ -134,6 +150,7 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
     {
         processingPlugins.logConfigurations();
         reportingPlugins.logConfigurations();
+        sequenceDatabasePlugins.logConfigurations();
         archiverTaskFactory.logConfiguration();
     }
 
@@ -142,17 +159,8 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
             Properties serviceProperties, IServletPropertiesManager configParameters,
             String datastoreCode, File storeRoot)
     {
-        SectionProperties[] sectionsProperties =
-                extractSectionProperties(serviceProperties, Constants.REPORTING_PLUGIN_NAMES);
-        ReportingPluginTaskFactory[] factories =
-                new ReportingPluginTaskFactory[sectionsProperties.length];
-        for (int i = 0; i < factories.length; i++)
-        {
-            factories[i] =
-                    new ReportingPluginTaskFactory(configParameters, sectionsProperties[i],
-                            datastoreCode, storeRoot);
-        }
-        return new PluginTaskProvider<IReportingPluginTask>(factories);
+        return createPluginsFactories(serviceProperties, configParameters, datastoreCode, storeRoot, 
+                IReportingPluginTask.class, "Reporting plugin", Constants.REPORTING_PLUGIN_NAMES);
     }
 
     @Private
@@ -160,17 +168,22 @@ public class PluginTaskInfoProvider implements IPluginTaskInfoProvider
             Properties serviceProperties, IServletPropertiesManager configParameters,
             String datastoreCode, File storeRoot)
     {
-        SectionProperties[] sectionsProperties =
-                extractSectionProperties(serviceProperties, Constants.PROCESSING_PLUGIN_NAMES);
-        ProcessingPluginTaskFactory[] factories =
-                new ProcessingPluginTaskFactory[sectionsProperties.length];
-        for (int i = 0; i < factories.length; i++)
+        return createPluginsFactories(serviceProperties, configParameters, datastoreCode, storeRoot,
+                IProcessingPluginTask.class, "Processing plugin", Constants.PROCESSING_PLUGIN_NAMES);
+    }
+    
+    private static <T> PluginTaskProvider<T> createPluginsFactories(Properties serviceProperties,
+            IServletPropertiesManager configParameters, String datastoreCode, File storeRoot, Class<T> clazz,
+            String pluginTaskName, String propertySectionName)
+    {
+        SectionProperties[] sectionsProperties = extractSectionProperties(serviceProperties, propertySectionName);
+        List<PluginTaskFactory<T>> factories = new ArrayList<PluginTaskFactory<T>>();
+        for (SectionProperties sectionProps : sectionsProperties)
         {
-            factories[i] =
-                    new ProcessingPluginTaskFactory(configParameters, sectionsProperties[i],
-                            datastoreCode, storeRoot);
+            factories.add(new PluginTaskFactory<T>(configParameters, sectionProps,
+                    datastoreCode, clazz, pluginTaskName, storeRoot));
         }
-        return new PluginTaskProvider<IProcessingPluginTask>(factories);
+        return new PluginTaskProvider<T>(factories);
     }
 
     private ArchiverPluginFactory createArchiverTaskFactory(Properties serviceProperties,
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProvider.java
index a43c6ecb32bf4d3ea9f489504b9d636f1e9b31dc..0b79490ca38290ebf39ebb2febec8b3e5d3a5e36 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProvider.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskProvider.java
@@ -17,7 +17,6 @@
 package ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import ch.systemsx.cisd.common.collection.IKeyExtractor;
@@ -31,16 +30,16 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescrip
  */
 public class PluginTaskProvider<P>
 {
-    private final TableMap<String, AbstractPluginTaskFactory<P>> factories;
+    private final TableMap<String, PluginTaskFactory<P>> factories;
 
-    public PluginTaskProvider(AbstractPluginTaskFactory<P>[] factories)
+    public PluginTaskProvider(List<PluginTaskFactory<P>> factories)
     {
         this.factories =
-                new TableMap<String, AbstractPluginTaskFactory<P>>(Arrays.asList(factories),
-                        new IKeyExtractor<String, AbstractPluginTaskFactory<P>>()
+                new TableMap<String, PluginTaskFactory<P>>(factories,
+                        new IKeyExtractor<String, PluginTaskFactory<P>>()
                             {
                                 @Override
-                                public String getKey(AbstractPluginTaskFactory<P> factory)
+                                public String getKey(PluginTaskFactory<P> factory)
                                 {
                                     return factory.getPluginDescription().getKey();
                                 }
@@ -64,7 +63,7 @@ public class PluginTaskProvider<P>
     {
         List<DatastoreServiceDescription> descriptions =
                 new ArrayList<DatastoreServiceDescription>();
-        for (AbstractPluginTaskFactory<?> factory : factories.values())
+        for (PluginTaskFactory<?> factory : factories.values())
         {
             descriptions.add(factory.getPluginDescription());
         }
@@ -74,7 +73,7 @@ public class PluginTaskProvider<P>
     /** checks that all factories can produce plugins */
     public void check(boolean checkIfSerializable)
     {
-        for (AbstractPluginTaskFactory<P> factory : factories.values())
+        for (PluginTaskFactory<P> factory : factories.values())
         {
             factory.check(checkIfSerializable);
         }
@@ -83,15 +82,15 @@ public class PluginTaskProvider<P>
     /** Writes information about all plugin factory configurations to the log */
     public void logConfigurations()
     {
-        for (AbstractPluginTaskFactory<P> factory : factories.values())
+        for (PluginTaskFactory<P> factory : factories.values())
         {
             factory.logConfiguration();
         }
     }
 
-    private AbstractPluginTaskFactory<P> getFactory(String pluginKey)
+    private PluginTaskFactory<P> getFactory(String pluginKey)
     {
-        AbstractPluginTaskFactory<P> factory = factories.tryGet(pluginKey);
+        PluginTaskFactory<P> factory = factories.tryGet(pluginKey);
         if (factory == null)
         {
             throw new IllegalArgumentException("No plugin registered for key '" + pluginKey + "'.");
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ProcessingPluginTaskFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ProcessingPluginTaskFactory.java
deleted file mode 100644
index bbd618e75dcbbeb77cb3fbfe141af4a26ca668c4..0000000000000000000000000000000000000000
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ProcessingPluginTaskFactory.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2009 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks;
-
-import java.io.File;
-
-import org.apache.log4j.Logger;
-
-import ch.systemsx.cisd.common.logging.LogCategory;
-import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.common.properties.PropertyParametersUtil.SectionProperties;
-import ch.systemsx.cisd.openbis.dss.generic.server.IServletPropertiesManager;
-
-/**
- * Factory of Processing Plugin Tasks.
- * 
- * @author Tomasz Pylak
- */
-public class ProcessingPluginTaskFactory extends AbstractPluginTaskFactory<IProcessingPluginTask>
-{
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, ProcessingPluginTaskFactory.class);
-
-    public ProcessingPluginTaskFactory(IServletPropertiesManager servletPropertiesManager,
-            SectionProperties sectionProperties, String datastoreCode, File storeRoot)
-    {
-        super(servletPropertiesManager, sectionProperties, datastoreCode, IProcessingPluginTask.class,
-                storeRoot);
-    }
-
-    @Override
-    public void logConfiguration()
-    {
-        operationLog.info(String.format("Processing plugin '%s' configuration:",
-                getPluginDescription().getKey()));
-        logPropertiesConfiguration();
-    }
-}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ReportingPluginTaskFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ReportingPluginTaskFactory.java
deleted file mode 100644
index f79bce3d428d1aa4f22de147ce28022ad292c895..0000000000000000000000000000000000000000
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/ReportingPluginTaskFactory.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2009 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks;
-
-import java.io.File;
-
-import org.apache.log4j.Logger;
-
-import ch.systemsx.cisd.common.logging.LogCategory;
-import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.common.properties.PropertyParametersUtil.SectionProperties;
-import ch.systemsx.cisd.openbis.dss.generic.server.IServletPropertiesManager;
-
-/**
- * Factory of Reporting Plugin Tasks.
- * 
- * @author Tomasz Pylak
- */
-public class ReportingPluginTaskFactory extends AbstractPluginTaskFactory<IReportingPluginTask>
-{
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, ProcessingPluginTaskFactory.class);
-
-    public ReportingPluginTaskFactory(IServletPropertiesManager servletPropertiesManager,
-            SectionProperties sectionProperties, String datastoreCode, File storeRoot)
-    {
-        super(servletPropertiesManager, sectionProperties, datastoreCode, IReportingPluginTask.class,
-                storeRoot);
-    }
-
-    @Override
-    public void logConfiguration()
-    {
-        operationLog.info(String.format("Reporting plugin '%s' configuration:",
-                getPluginDescription().getKey()));
-        logPropertiesConfiguration();
-    }
-}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/Constants.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/Constants.java
index 1b5fe90e9edac7ddd6a0ea7426980ec095d0044a..99f9e73d12d7c0149aef80a1a7b41e8740ece19d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/Constants.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/Constants.java
@@ -36,6 +36,9 @@ public class Constants
     /** property with processing plugins names separated by delimiter */
     public static final String PROCESSING_PLUGIN_NAMES = "processing-plugins";
 
+    /** property with sequnence databases names separated by delimiter */
+    public static final String SEQUENCE_DATABASES_NAMES = "sequence-databases";
+    
     /** Key of service property which is a list of data source IDs. */ 
     public static final String DATA_SOURCES_KEY = "data-sources";
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v2/ISequenceDatabase.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v2/ISequenceDatabase.java
new file mode 100644
index 0000000000000000000000000000000000000000..95eae980da558faafcda8c147fbb6f30e0843b36
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v2/ISequenceDatabase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 ETH Zuerich, SIS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
+
+/**
+ * Interface for a database for nucleotid or protein sequences.
+ * Implenting classes should have a public constructor with two arguments: First is an instance of
+ * {@link Properties} and second is an instance of {@link File} which points to the root of the data set store.
+ *
+ * @author Franz-Josef Elmer
+ */
+public interface ISequenceDatabase
+{
+    public String getName();
+    
+    public boolean isAvailable();
+    
+    public List<SequenceSearchResult> search(String sequenceSnippet, Map<String, String> optionalParameters);
+}
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java
index e1e23a2158a328fb517310a92ba7411ae8a6bb03..f88246a57f3c43a126b86082e98d0b82f0c517d2 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceTest.java
@@ -20,7 +20,10 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Properties;
 
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -34,11 +37,17 @@ import ch.systemsx.cisd.common.exceptions.InvalidAuthenticationException;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
 import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.mail.MailClientParameters;
+import ch.systemsx.cisd.common.properties.PropertyParametersUtil.SectionProperties;
+import ch.systemsx.cisd.openbis.dss.generic.server.api.v2.sequencedatabases.AbstractSequenceDatabase;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IPluginTaskInfoProvider;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.PluginTaskFactory;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.PluginTaskProvider;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IShareIdManager;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISequenceDatabase;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PluginUtilTest;
 import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService;
 import ch.systemsx.cisd.openbis.generic.shared.IServiceForDataStoreServer;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext;
 import ch.systemsx.cisd.openbis.generic.shared.dto.builders.DatasetDescriptionBuilder;
@@ -48,6 +57,10 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.builders.DatasetDescriptionBu
  */
 public class DataStoreServiceTest extends AssertJUnit
 {
+    private static final Map<String, String> OPTIONAL_PARAMETERS = Collections.singletonMap("greeting", "hi");
+
+    private static final String SEQUENCE_SNIPPET = "GATTACA";
+
     private static final String INVALID_SESSION_TOKEN_MSG = "Invalid session token.";
 
     private static final String CIFEX_URL = "cifexURL";
@@ -55,7 +68,7 @@ public class DataStoreServiceTest extends AssertJUnit
     private static final File TEST_FOLDER = new File("targets/data-store-service-test");
 
     private static final File TEST_STORE = new File(TEST_FOLDER, "store");
-
+    
     private static final class MockDataStoreService extends DataStoreService
     {
         private final ICIFEXRPCServiceFactory cifexServiceFactory;
@@ -81,6 +94,39 @@ public class DataStoreServiceTest extends AssertJUnit
             return cifexServiceFactory;
         }
     }
+    
+    public static final class MockSequenceDatabase extends AbstractSequenceDatabase
+    {
+        private static final String DATA_SET_KEY = "data-set";
+        private static final String AVAILABLE_KEY = "available";
+        
+        private boolean available;
+        private String dataSetCode;
+
+        public MockSequenceDatabase(Properties properties, File storeRoot)
+        {
+            super(properties, storeRoot);
+            available = "true".equals(properties.getProperty(AVAILABLE_KEY));
+            dataSetCode = properties.getProperty(DATA_SET_KEY);
+        }
+
+        @Override
+        public boolean isAvailable()
+        {
+            return available;
+        }
+
+        @Override
+        public List<SequenceSearchResult> search(String sequenceSnippet, Map<String, String> optionalParameters)
+        {
+            assertSame(SEQUENCE_SNIPPET, sequenceSnippet);
+            assertSame(OPTIONAL_PARAMETERS, optionalParameters);
+            SequenceSearchResult sequenceSearchResult = new SequenceSearchResult();
+            sequenceSearchResult.setDataSetCode(dataSetCode);
+            return Arrays.asList(sequenceSearchResult);
+        }
+        
+    }
 
     private SessionTokenManager sessionTokenManager;
 
@@ -132,6 +178,74 @@ public class DataStoreServiceTest extends AssertJUnit
         context.assertIsSatisfied();
     }
 
+    @Test
+    public void testSearchForDataSetsWithSequencesUndefinedDatabases()
+    {
+        pluginTaskParameters = context.mock(IPluginTaskInfoProvider.class);
+        preparePluginTaskInfoProvider();
+
+        List<SequenceSearchResult> result = createService().searchForDataSetsWithSequences(sessionToken, 
+                null, SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+
+        assertEquals(0, result.size());
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testSearchForDataSetsWithSequencesUnAvailableDatabases()
+    {
+        pluginTaskParameters = context.mock(IPluginTaskInfoProvider.class);
+        preparePluginTaskInfoProvider("-1", "-2");
+        
+        List<SequenceSearchResult> result = createService().searchForDataSetsWithSequences(sessionToken, 
+                null, SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+        
+        assertEquals(0, result.size());
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testSearchForDataSetsWithSequencesWithUnspecifiedDatabase()
+    {
+        pluginTaskParameters = context.mock(IPluginTaskInfoProvider.class);
+        preparePluginTaskInfoProvider("1", "2");
+        
+        List<SequenceSearchResult> result = createService().searchForDataSetsWithSequences(sessionToken, 
+                null, SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+        
+        assertEquals("DS-1", result.get(0).getDataSetCode());
+        assertEquals(1, result.size());
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testSearchForDataSetsWithSequencesWithSpecifiedAndAvailableDatabase()
+    {
+        pluginTaskParameters = context.mock(IPluginTaskInfoProvider.class);
+        preparePluginTaskInfoProvider("1", "2");
+        
+        List<SequenceSearchResult> result = createService().searchForDataSetsWithSequences(sessionToken, 
+                "db-2", SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+        
+        assertEquals("DS-2", result.get(0).getDataSetCode());
+        assertEquals(1, result.size());
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testSearchForDataSetsWithSequencesWithSpecifiedButUnailableDatabase()
+    {
+        pluginTaskParameters = context.mock(IPluginTaskInfoProvider.class);
+        preparePluginTaskInfoProvider("-1", "2", "-3", "4");
+        
+        List<SequenceSearchResult> result = createService().searchForDataSetsWithSequences(sessionToken, 
+                "db-3", SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+        
+        assertEquals("DS-2", result.get(0).getDataSetCode());
+        assertEquals(1, result.size());
+        context.assertIsSatisfied();
+    }
+    
     @Test
     public void testGetVersionForInvalidSessionToken()
     {
@@ -284,6 +398,38 @@ public class DataStoreServiceTest extends AssertJUnit
         context.assertIsSatisfied();
     }
 
+    private void preparePluginTaskInfoProvider(final String... databases)
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    allowing(pluginTaskParameters).getStoreRoot();
+                    will(returnValue(TEST_STORE));
+                    
+                    List<PluginTaskFactory<ISequenceDatabase>> factories 
+                            = new ArrayList<PluginTaskFactory<ISequenceDatabase>>();
+                    for (String database : databases)
+                    {
+                        boolean available = database.startsWith("-") == false;
+                        if (available == false)
+                        {
+                            database = database.substring(1);
+                        }
+                        Properties sectionProperties = new Properties();
+                        sectionProperties.setProperty(PluginTaskFactory.LABEL_PROPERTY_NAME, database);
+                        sectionProperties.setProperty(PluginTaskFactory.CLASS_PROPERTY_NAME, MockSequenceDatabase.class.getName());
+                        sectionProperties.setProperty(MockSequenceDatabase.AVAILABLE_KEY, Boolean.toString(available));
+                        sectionProperties.setProperty(MockSequenceDatabase.DATA_SET_KEY, "DS-" + database.toUpperCase());
+                        factories.add(new PluginTaskFactory<ISequenceDatabase>(null, 
+                                new SectionProperties("db-" + database, sectionProperties), "DSS", 
+                                ISequenceDatabase.class,  "Test-db-" + database, TEST_STORE));
+                    }
+                    allowing(pluginTaskParameters).getSequenceDatabasesProvider();
+                    will(returnValue(new PluginTaskProvider<ISequenceDatabase>(factories)));
+                }
+            });
+    }
+
     private IDataStoreService createService()
     {
         context.checking(new Expectations()
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskParametersTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskParametersTest.java
index 64a1423097e1aecf20bd80a78b95b9d0b65d72d1..03b461a65494034cc2cee173064914da92fad414 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskParametersTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskParametersTest.java
@@ -61,7 +61,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
  * @author Tomasz Pylak
  */
 @Friend(toClasses =
-    { PluginTaskInfoProvider.class, AbstractPluginTaskFactory.class })
+    { PluginTaskInfoProvider.class, PluginTaskFactory.class })
 public class PluginTaskParametersTest extends AbstractFileSystemTestCase
 {
     private static final File STORE_ROOT = new File("../datastore_server/resource/test-data/"
@@ -155,7 +155,7 @@ public class PluginTaskParametersTest extends AbstractFileSystemTestCase
         final String pluginLabel2 = "Demo Reporting 2";
         String datasetCodes2 = "EICML";
         setPluginProperties(props, plugin2, pluginLabel2, datasetCodes2, DemoReportingPlugin.class);
-        setPluginProperty(props, plugin2, AbstractPluginTaskFactory.SERVLETS_PROPERTY_NAME,
+        setPluginProperty(props, plugin2, PluginTaskFactory.SERVLETS_PROPERTY_NAME,
                 "s1, s2");
         setPluginProperty(props, plugin2, "s1.a", "alpha");
         setPluginProperty(props, plugin2, "s2.b", "beta");
@@ -254,7 +254,7 @@ public class PluginTaskParametersTest extends AbstractFileSystemTestCase
         props.setProperty(Constants.PROCESSING_PLUGIN_NAMES, plugin1);
         setPluginProperties(props, plugin1, "pluginLabel1", "datasetCodes1",
                 DemoProcessingPlugin.class);
-        setPluginProperty(props, plugin1, AbstractPluginTaskFactory.SERVLET_PROPERTY_NAME + ".a",
+        setPluginProperty(props, plugin1, PluginTaskFactory.SERVLET_PROPERTY_NAME + ".a",
                 "alpha");
         context.checking(new Expectations()
             {
@@ -292,17 +292,17 @@ public class PluginTaskParametersTest extends AbstractFileSystemTestCase
     private void setPluginProperties(Properties props, String pluginId, String pluginLabel,
             String datasetCodes, Class<?> pluginClass) throws IOException, FileNotFoundException
     {
-        setPluginProperty(props, pluginId, AbstractPluginTaskFactory.LABEL_PROPERTY_NAME,
+        setPluginProperty(props, pluginId, PluginTaskFactory.LABEL_PROPERTY_NAME,
                 pluginLabel);
-        setPluginProperty(props, pluginId, AbstractPluginTaskFactory.DATASET_CODES_PROPERTY_NAME,
+        setPluginProperty(props, pluginId, PluginTaskFactory.DATASET_CODES_PROPERTY_NAME,
                 datasetCodes);
-        setPluginProperty(props, pluginId, AbstractPluginTaskFactory.CLASS_PROPERTY_NAME,
+        setPluginProperty(props, pluginId, PluginTaskFactory.CLASS_PROPERTY_NAME,
                 pluginClass.getName());
         String[] pluginParams = new String[]
             { "param1 = X", "param2 = Y" };
         File paramsFile = createPluginPropertiesFile(pluginParams);
         setPluginProperty(props, pluginId,
-                AbstractPluginTaskFactory.PARAMS_FILE_PATH_PROPERTY_NAME, paramsFile.getPath());
+                PluginTaskFactory.PARAMS_FILE_PATH_PROPERTY_NAME, paramsFile.getPath());
     }
 
     private File createPluginPropertiesFile(String... lines) throws IOException,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index f11abe1f38999d9100f89c7f0547505aaef1a565..06945f32ed13bf2c6c4298e129e20b061e3adb0b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -83,6 +83,7 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.validator.ExternalD
 import ch.systemsx.cisd.openbis.generic.server.authorization.validator.MatchingEntityValidator;
 import ch.systemsx.cisd.openbis.generic.server.authorization.validator.ProjectValidator;
 import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SampleValidator;
+import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SequenceSearchResultValidator;
 import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SpaceValidator;
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.DataAccessExceptionTranslator;
@@ -155,104 +156,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWit
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IdentifierExtractor;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Attachment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AuthorizationGroupUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BasicEntityDescription;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchOperationKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CorePlugin;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImport;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImportFile;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelatedEntities;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetRelationshipRole;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetTypePropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetUpdateResult;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStore;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescription;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DynamicPropertyEvaluationInfo;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityHistory;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityValidationEvaluationInfo;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentTypePropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentUpdateResult;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalDataManagementSystem;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IMetaprojectRegistration;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IMetaprojectUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Identifier;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LastModificationState;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedUiActionDescription;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectCriteria;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewBasicExperiment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewDataSet;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETNewPTAssigments;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewPTNewAssigment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PhysicalDataSet;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PluginType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyUpdates;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.*;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleTypePropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleUpdateResult;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptUpdateResult;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UpdatedBasicExperiment;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UpdatedDataSet;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UpdatedSample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermReplacement;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedUiAction;
@@ -1701,6 +1606,20 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         return translateExperiments(sessionToken, experiments);
     }
 
+    @Override
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @ReturnValueFilter(validatorClass = SequenceSearchResultValidator.class)
+    public List<SequenceSearchResultWithFullDataSet> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull)
+    {
+        Session session = getSession(sessionToken);
+
+        IDataSetTable dataSetTable = businessObjectFactory.createDataSetTable(session);
+        return dataSetTable.searchForDataSetsWithSequences(preferredSequenceDatabaseOrNull, sequenceSnippet,
+                optionalParametersOrNull);
+    }
+
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     @ReturnValueFilter(validatorClass = ExternalDataValidator.class)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index ae7a9a20f7c8f28a1b7305644ccb09efc70b4eb1..37ad732eafa3f64504d5b7f6bf21c8188f514574 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -110,6 +110,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleUpdateResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptUpdateResult;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -695,6 +696,16 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         return null;
     }
 
+    @Override
+    public List<SequenceSearchResultWithFullDataSet> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull)
+    {
+        logAccess(sessionToken, "search_for_datasets_with_sequences", "preferred_database(%s) sequence_snippet(%s)",
+                preferredSequenceDatabaseOrNull, sequenceSnippet);
+        return null;
+    }
+
     @Override
     public List<AbstractExternalData> searchForDataSets(String sessionToken,
             DetailedSearchCriteria criteria)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
index e167efeb073559becf7a95d52d08fd47bc5448dd..81955f7a9e2837f5182b0ff6aa7e0aa9b0073dc9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
@@ -94,6 +94,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchableEntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.IObjectId;
@@ -113,6 +114,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentHolderPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AuthorizationGroupPE;
@@ -141,7 +143,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 public class GeneralInformationService extends AbstractServer<IGeneralInformationService> implements
         IGeneralInformationService
 {
-    public static final int MINOR_VERSION = 28;
+    public static final int MINOR_VERSION = 29;
 
     @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER)
     private ICommonServer commonServer;
@@ -945,6 +947,26 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
         }
     }
 
+    @Override
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    // There is no @ReturnValueFilter because commonServer.searchForDataSetsWithSequences() does already the filtering.
+    public List<SequenceSearchResult> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull)
+    {
+        checkSession(sessionToken);
+
+        List<SequenceSearchResult> result = new ArrayList<SequenceSearchResult>();
+        List<SequenceSearchResultWithFullDataSet> list = commonServer.searchForDataSetsWithSequences(sessionToken,
+                preferredSequenceDatabaseOrNull, sequenceSnippet, optionalParametersOrNull);
+        for (SequenceSearchResultWithFullDataSet sequenceSearchResult : list)
+        {
+            result.add(sequenceSearchResult.getSearchResult());
+        }
+        return result;
+    }
+
     @Override
     @Transactional(readOnly = true)
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
index b0ef6402de9e01f16f6a2c0af915c3eeb94b0de2..8c810eeab6fe2ec71d004146ad95e763d0f8db29 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
@@ -46,6 +46,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.IExperimentId;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.IMetaprojectId;
@@ -294,6 +295,16 @@ class GeneralInformationServiceLogger extends AbstractServerLogger implements
         return null;
     }
 
+    @Override
+    public List<SequenceSearchResult> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull)
+    {
+        logAccess(sessionToken, "search-for-data-sets-with-sequences", "PREFERRED_DATABASE(%s) SEQUENCE_SNIPPET(%s)",
+                preferredSequenceDatabaseOrNull, sequenceSnippet);
+        return null;
+    }
+
     @Override
     public List<DataSet> searchForDataSets(String sessionToken, SearchCriteria searchCriteria)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/validator/SequenceSearchResultValidator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/validator/SequenceSearchResultValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..694c157557f014f2dcfc7fa08ab832d7a13c3a50
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/validator/SequenceSearchResultValidator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 ETH Zuerich, SIS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.authorization.validator;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+
+/**
+ * Validator of @SequenceSearchResult.
+ * 
+ * @author Franz-Josef Elmer
+ */
+public class SequenceSearchResultValidator extends AbstractValidator<SequenceSearchResultWithFullDataSet>
+{
+    private final ExternalDataValidator validator = new ExternalDataValidator();
+
+    @Override
+    public boolean doValidation(PersonPE person, SequenceSearchResultWithFullDataSet value)
+    {
+        return validator.isValid(person, value.getDataSet());
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java
index 2e0c4a7d65eec1df69567cb6413f6cebd7db0f7a..bbec982eb4c4e4e0e1392408a93e9728ee01de3c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java
@@ -36,6 +36,8 @@ import org.springframework.dao.DataIntegrityViolationException;
 
 import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.common.collection.CollectionUtils;
+import ch.systemsx.cisd.common.collection.IKeyExtractor;
+import ch.systemsx.cisd.common.collection.TableMap;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
@@ -55,8 +57,10 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.exception.DataSetDele
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.event.DeleteDataSetEventBuilder;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.util.KeyExtractorFactory;
 import ch.systemsx.cisd.openbis.generic.shared.Constants;
 import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TableModelAppender;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TableModelAppender.TableModelWithDifferentColumnCountException;
@@ -70,6 +74,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetBatchUpdateDetai
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStoreServiceKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetBatchUpdatesDTO;
@@ -269,6 +274,70 @@ public final class DataSetTable extends AbstractDataSetBusinessObject implements
         this.dataSets = dataSets;
     }
 
+    @Override
+    public List<SequenceSearchResultWithFullDataSet> searchForDataSetsWithSequences(String preferredSequenceDatabaseOrNull,
+            String sequenceSnippet, Map<String, String> optionalParametersOrNull)
+    {
+        List<SequenceSearchResult> result = askAllDataStoreServers(preferredSequenceDatabaseOrNull,
+                sequenceSnippet, optionalParametersOrNull);
+        TableMap<String, AbstractExternalData> fullDataSetsByCode = listFullDataSets(result);
+        return filterSearchResultAndInjectFullDataSets(result, fullDataSetsByCode);
+    }
+
+    private List<SequenceSearchResultWithFullDataSet> filterSearchResultAndInjectFullDataSets(List<SequenceSearchResult> result,
+            TableMap<String, AbstractExternalData> fullDataSetsByCode)
+    {
+        List<SequenceSearchResultWithFullDataSet> filteredResult = new ArrayList<SequenceSearchResultWithFullDataSet>();
+        for (SequenceSearchResult sequenceSearchResult : result)
+        {
+            String dataSetCode = sequenceSearchResult.getDataSetCode();
+            AbstractExternalData fullDataSet = fullDataSetsByCode.tryGet(dataSetCode);
+            if (fullDataSet != null)
+            {
+                SequenceSearchResultWithFullDataSet resultWithFullDataSet = new SequenceSearchResultWithFullDataSet();
+                resultWithFullDataSet.setDataSet(fullDataSet);
+                resultWithFullDataSet.setSearchResult(sequenceSearchResult);
+                filteredResult.add(resultWithFullDataSet);
+            }
+        }
+        return filteredResult;
+    }
+
+    private TableMap<String, AbstractExternalData> listFullDataSets(List<SequenceSearchResult> result)
+    {
+        IKeyExtractor<String, AbstractExternalData> codeKeyExtractor = KeyExtractorFactory.<AbstractExternalData> createCodeKeyExtractor();
+        if (result.isEmpty())
+        {
+            return new TableMap<String, AbstractExternalData>(codeKeyExtractor);
+        }
+        List<String> codes = new ArrayList<String>();
+        for (SequenceSearchResult sequenceSearchResult : result)
+        {
+            codes.add(sequenceSearchResult.getDataSetCode());
+        }
+        List<DataPE> fullDataSetPEs = getDataDAO().tryToFindFullDataSetsByCodes(codes, false, false);
+        List<AbstractExternalData> fullDataSets = DataSetTranslator.translate(fullDataSetPEs, "?", "?",
+                new HashMap<Long, Set<Metaproject>>(), managedPropertyEvaluatorFactory);
+        return new TableMap<String, AbstractExternalData>(fullDataSets, codeKeyExtractor);
+    }
+
+    private List<SequenceSearchResult> askAllDataStoreServers(String preferredSequenceDatabaseOrNull,
+            String sequenceSnippet, Map<String, String> optionalParametersOrNull)
+    {
+        List<SequenceSearchResult> result = new ArrayList<SequenceSearchResult>();
+        List<DataStorePE> stores = getDataStoreDAO().listDataStores();
+        for (DataStorePE dataStore : stores)
+        {
+            IDataStoreService service = tryGetDataStoreService(dataStore);
+            if (service != null)
+            {
+                result.addAll(service.searchForDataSetsWithSequences(dataStore.getSessionToken(),
+                        preferredSequenceDatabaseOrNull, sequenceSnippet, optionalParametersOrNull));
+            }
+        }
+        return result;
+    }
+
     @Override
     public void loadByDataSetCodes(List<String> dataSetCodes, boolean withProperties,
             boolean lockForUpdate)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java
index afaeb18469ad2030974a55894e8979a5e72f4aa8..714ba7e419d025600d0b29abdf3003dfecb40451 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java
@@ -21,6 +21,7 @@ import java.util.Map;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetBatchUpdatesDTO;
@@ -35,6 +36,12 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
  */
 public interface IDataSetTable
 {
+    /**
+     * Searchs for data sets with sequences.
+     */
+    List<SequenceSearchResultWithFullDataSet> searchForDataSetsWithSequences(String preferredSequenceDatabaseOrNull,
+            String sequenceSnippet, Map<String, String> optionalParametersOrNull);
+
     /**
      * Loads data sets specified by their codes. Data set codes will be ignored if no {@link DataPE} could be found. Properties will be loaded too
      * depending on <var>withProperties</var> value. Optionally if <var>lockForUpdate</var> is <var>true</var> all updates to loaded data sets from
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 8b097adacdf8d81383684b70e23f2e47b31e2f75..c4dc36c00031ef1d4195b902d1b5774ba91458a2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -105,6 +105,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleUpdateResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptUpdateResult;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -657,6 +658,14 @@ public interface ICommonServer extends IServer
     public List<Experiment> searchForExperiments(String sessionToken,
             DetailedSearchCriteria criteria);
 
+    /**
+     * Searches for data sets which have nucleotid or aminoacid sequences in there files.
+     */
+    @Transactional(readOnly = true)
+    public List<SequenceSearchResultWithFullDataSet> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull);
+
     /**
      * Searches for data sets that fulfill the specified search criteria.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
index 54b6cbd6cd192f500862f230fad1a4e960867ab2..566fa5ae5ce92c7f76ee3ac923aecb4dfd4d5f14 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import ch.systemsx.cisd.common.exceptions.InvalidAuthenticationException;
 import ch.systemsx.cisd.openbis.common.conversation.annotation.Conversational;
 import ch.systemsx.cisd.openbis.common.conversation.annotation.Progress;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.CustomImportFile;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IDatasetLocation;
@@ -41,7 +42,7 @@ public interface IDataStoreService
     /**
      * Every time this interface and related DTO's are changed, we should increment this number.
      */
-    public static final int VERSION = 9; // for release 142
+    public static final int VERSION = 10; // for S185
 
     /**
      * Returns the version of this service.
@@ -81,8 +82,8 @@ public interface IDataStoreService
     /**
      * Runs the reporting task with the specified id for provided datasets.
      * <p>
-     * <i> Ensure that you call {@link #cleanupSession(String)} on closing of the user sesssion
-     * <var>userSessionToken</var> so that DSS gets the chance to cleanup session files. </i>
+     * <i> Ensure that you call {@link #cleanupSession(String)} on closing of the user sesssion <var>userSessionToken</var> so that DSS gets the
+     * chance to cleanup session files. </i>
      */
     @Conversational(progress = Progress.AUTOMATIC)
     public TableModel createReportFromDatasets(String sessionToken, String userSessionToken,
@@ -90,16 +91,13 @@ public interface IDataStoreService
             String userEmailOrNull);
 
     /**
-     * Schedules the processing task with the specified id for provided datasets and specified
-     * parameter bindings.
+     * Schedules the processing task with the specified id for provided datasets and specified parameter bindings.
      * 
      * @param userSessionToken The session token of the user that initiated the processing.
-     * @param parameterBindings Contains at least the parameter {@link Constants#USER_PARAMETER}
-     *            with the ID of the user who initiated processing.
+     * @param parameterBindings Contains at least the parameter {@link Constants#USER_PARAMETER} with the ID of the user who initiated processing.
      * @param userId id of user who initiated the processing.
-     * @param userEmailOrNull Email of user who initiated processing and will get a message after
-     *            the processing is finished. It may be null if the user doesn't have email and no
-     *            message will be send in such case.
+     * @param userEmailOrNull Email of user who initiated processing and will get a message after the processing is finished. It may be null if the
+     *            user doesn't have email and no message will be send in such case.
      */
     public void processDatasets(String sessionToken, String userSessionToken, String serviceKey,
             List<DatasetDescription> datasets, Map<String, String> parameterBindings,
@@ -109,11 +107,10 @@ public interface IDataStoreService
      * Schedules archiving of provided datasets.
      * 
      * @param userId id of user who initiated archiving.
-     * @param userEmailOrNull Email of user who initiated archiving and will get a message after the
-     *            task is finished. It may be null if the user doesn't have email and no message
-     *            will be send in such case.
-     * @param removeFromDataStore when set to <code>true</code> the data sets will be removed from
-     *            the data store after a successful archiving operation.
+     * @param userEmailOrNull Email of user who initiated archiving and will get a message after the task is finished. It may be null if the user
+     *            doesn't have email and no message will be send in such case.
+     * @param removeFromDataStore when set to <code>true</code> the data sets will be removed from the data store after a successful archiving
+     *            operation.
      */
     public void archiveDatasets(String sessionToken, String userSessionToken,
             List<DatasetDescription> datasets, String userId, String userEmailOrNull,
@@ -123,9 +120,8 @@ public interface IDataStoreService
      * Schedules unarchiving of provided datasets.
      * 
      * @param userId id of user who initiated unarchiving.
-     * @param userEmailOrNull Email of user who initiated unarchiving and will get a message after
-     *            the task is finished. It may be null if the user doesn't have email and no message
-     *            will be send in such case.
+     * @param userEmailOrNull Email of user who initiated unarchiving and will get a message after the task is finished. It may be null if the user
+     *            doesn't have email and no message will be send in such case.
      */
     public void unarchiveDatasets(String sessionToken, String userSessionToken,
             List<DatasetDescription> datasets, String userId, String userEmailOrNull);
@@ -136,8 +132,7 @@ public interface IDataStoreService
      * @param sessionToken The sessionToken
      * @param serviceKey The service that should compute the link
      * @param dataSet The data set we want the link for
-     * @return A LinkModel that describes the link. The session Id needs to be filled in to retrieve
-     *         the link.
+     * @return A LinkModel that describes the link. The session Id needs to be filled in to retrieve the link.
      */
     public LinkModel retrieveLinkFromDataSet(String sessionToken, String serviceKey,
             DatasetDescription dataSet);
@@ -145,8 +140,8 @@ public interface IDataStoreService
     /**
      * Gets the link from a service that supports the IReportingPluginTask#createLink method.
      * <p>
-     * <i> Ensure that you call {@link #cleanupSession(String)} on closing of the user sesssion
-     * <var>userSessionToken</var> so that DSS gets the chance to cleanup session files. </i>
+     * <i> Ensure that you call {@link #cleanupSession(String)} on closing of the user sesssion <var>userSessionToken</var> so that DSS gets the
+     * chance to cleanup session files. </i>
      * 
      * @param sessionToken The sessionToken.
      * @param userSessionToken The session token of the user that initiated the processing.
@@ -170,4 +165,18 @@ public interface IDataStoreService
      */
     public void cleanupSession(String userSessionToken);
 
+    /**
+     * Searches for the specified sequence snippet. If no preferred sequence database is specified the first available one will be used. If the
+     * preferred sequence database doesn't exist or isn't available also the first available database will be used.
+     * 
+     * @param preferredSequenceDatabaseOrNull The key of the preferred sequence database or <code>null</code>.
+     * @param sequenceSnippet Snippet of nucleotid or aminoacid sequence.
+     * @param optionalParametersOrNull Optional parameters. Can be <code>null</code>. The semantics depends on the type of the used sequence database.
+     * @since 10
+     */
+    @Conversational(progress = Progress.AUTOMATIC)
+    public List<SequenceSearchResult> searchForDataSetsWithSequences(String sessionToken,
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet,
+            Map<String, String> optionalParametersOrNull);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SequenceSearchResultWithFullDataSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SequenceSearchResultWithFullDataSet.java
new file mode 100644
index 0000000000000000000000000000000000000000..a796500f26e34e0653098fa1e5f96d461fe471ae
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SequenceSearchResultWithFullDataSet.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 ETH Zuerich, SIS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
+
+/**
+ * Result of a sequence search.
+ * 
+ * @author Franz-Josef Elmer
+ */
+public class SequenceSearchResultWithFullDataSet implements Serializable
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private AbstractExternalData dataSet;
+
+    private SequenceSearchResult searchResult;
+
+    public AbstractExternalData getDataSet()
+    {
+        return dataSet;
+    }
+
+    public void setDataSet(AbstractExternalData dataSet)
+    {
+        this.dataSet = dataSet;
+    }
+
+    public SequenceSearchResult getSearchResult()
+    {
+        return searchResult;
+    }
+
+    public void setSearchResult(SequenceSearchResult searchResult)
+    {
+        this.searchResult = searchResult;
+    }
+
+    @Override
+    public String toString()
+    {
+        return searchResult.toString();
+    }
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java
index d3cbd3e5cecb99a7c967e5f18e45cd3b95482dc0..b30e2ea5bff158625dae20abb57693cc8c2bccef 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -45,12 +46,14 @@ import ch.systemsx.cisd.openbis.generic.server.business.ManagerTestTool;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.event.DeleteDataSetEventBuilder;
 import ch.systemsx.cisd.openbis.generic.shared.CommonTestUtils;
 import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SequenceSearchResultWithFullDataSet;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
@@ -76,6 +79,12 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 @Friend(toClasses = DataSetTable.class)
 public final class DataSetTableTest extends AbstractBOTest
 {
+    private static final Map<String, String> OPTIONAL_PARAMETERS = Collections.singletonMap("greeting", "hi");
+
+    private static final String SEQUENCE_SNIPPET = "GATTACA";
+
+    private static final String SEQUENCE_DATABASE = "MY_DB";
+
     private IDataStoreServiceFactory dssFactory;
 
     private DataStorePE dss1;
@@ -153,6 +162,76 @@ public final class DataSetTableTest extends AbstractBOTest
             });
     }
 
+    @Test
+    public void testSearchForDataSetsWithSequences()
+    {
+        DataStorePE store1 = new DataStorePE();
+        store1.setRemoteUrl("http://abc1.de");
+        DataStorePE store2 = new DataStorePE();
+        store2.setRemoteUrl("http://abc2.de");
+        store2.setSessionToken("session-2");
+        DataStorePE store3 = new DataStorePE();
+        prepareListDataStores(store1, store2, store3);
+        prepareSearchSequenceDatabase(store1, dataStoreService1, "ds1", "ds2");
+        prepareSearchSequenceDatabase(store2, dataStoreService2, "ds3");
+        ExternalDataPE ds1 = createDataSet("ds1", store1);
+        ExternalDataPE ds2 = createDataSet("ds2", store1);
+        ExternalDataPE ds3 = createDataSet("ds3", store2);
+        prepareFindFullDatasets(new ExternalDataPE[] { ds1, ds2, ds3 }, new ExternalDataPE[] { ds1, ds3 }, false, false);
+
+        List<SequenceSearchResultWithFullDataSet> results =
+                createDataSetTable().searchForDataSetsWithSequences(SEQUENCE_DATABASE, SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+
+        assertEquals("Database: test-db, Data set: ds1, path: ds1/path, identifier: [id-ds1], position: 42",
+                results.get(0).getSearchResult().toString());
+        assertEquals(ds1.getCode(), results.get(0).getDataSet().getCode());
+        assertEquals("/G1/P1/exp1", results.get(0).getDataSet().getExperiment().getIdentifier());
+        assertEquals("Database: test-db, Data set: ds3, path: ds3/path, identifier: [id-ds3], position: 42",
+                results.get(1).getSearchResult().toString());
+        assertEquals(ds3.getCode(), results.get(1).getDataSet().getCode());
+        assertEquals("/G1/P1/exp1", results.get(1).getDataSet().getExperiment().getIdentifier());
+        assertEquals(2, results.size());
+        context.assertIsSatisfied();
+    }
+
+    private void prepareListDataStores(final DataStorePE... dataStores)
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(dataStoreDAO).listDataStores();
+                    will(returnValue(Arrays.asList(dataStores)));
+                }
+            });
+    }
+
+    private void prepareSearchSequenceDatabase(final DataStorePE dataStore, final IDataStoreService service,
+            final String... foundDataSets)
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(dssFactory).create(dataStore.getRemoteUrl());
+                    will(returnValue(service));
+
+                    one(service).searchForDataSetsWithSequences(dataStore.getSessionToken(),
+                            SEQUENCE_DATABASE, SEQUENCE_SNIPPET, OPTIONAL_PARAMETERS);
+                    List<SequenceSearchResult> results = new ArrayList<SequenceSearchResult>();
+                    for (String foundDataSet : foundDataSets)
+                    {
+                        SequenceSearchResult result = new SequenceSearchResult();
+                        result.setSequenceDatabaseName("test-db");
+                        result.setDataSetCode(foundDataSet);
+                        result.setPathInDataSet(foundDataSet + "/path");
+                        result.setPositionInSequence(42);
+                        result.setSequenceIdentifier("id-" + foundDataSet);
+                        results.add(result);
+                    }
+                    will(returnValue(results));
+                }
+            });
+    }
+
     @Test
     public final void testLoadBySampleTechIdWithNullSampleId()
     {
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
index 9075cacc810bca7b6b22e5d4fa18691b0a335d66..75153ba64d53ec09b8e87fd9d37b72524ff028d9 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
@@ -38,18 +38,18 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignments;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Role;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SequenceSearchResult;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.IExperimentId;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.IMetaprojectId;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.project.IProjectId;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.ISampleId;
-import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 
@@ -397,6 +397,21 @@ public interface IGeneralInformationService extends IRpcService
     public List<DataSet> getDataSetMetaData(String sessionToken, List<String> dataSetCodes,
             EnumSet<DataSetFetchOption> fetchOptions);
 
+    /**
+     * Searches for data sets which have nucleotid or amoniacid sequences in there files. 
+     * If no preferred sequence database is specified the first available one will be used. If the
+     * preferred sequence database doesn't exist or isn't available also the first available database will be used.
+     * 
+     * @param preferredSequenceDatabaseOrNull The key of the preferred sequence database or <code>null</code>.
+     * @param sequenceSnippet A snippet of a sequence to search for.
+     * @param optionalParametersOrNull Optional parameters. Can be <code>null</code>. 
+     *          The semantics depends on the type of the used sequence database.
+     * @since 1.29
+     */
+    public List<SequenceSearchResult> searchForDataSetsWithSequences(String sessionToken, 
+            String preferredSequenceDatabaseOrNull, String sequenceSnippet, 
+            Map<String, String> optionalParametersOrNull);
+    
     /**
      * Return all data sets matching specified search criteria. Note, that for returned container data sets the contained data sets have only code,
      * type and registration date set.
@@ -405,7 +420,7 @@ public interface IGeneralInformationService extends IRpcService
      * @since 1.8
      */
     public List<DataSet> searchForDataSets(String sessionToken, SearchCriteria searchCriteria);
-
+    
     /**
      * Return all data sets matching specified search criteria and visible to user <var>userId</var>. Note, that for returned container data sets the
      * contained data sets have only code, type and registration date set.
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SequenceSearchResult.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SequenceSearchResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..bec456d9040047cdcb482fa411cafd3f7b912fb0
--- /dev/null
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/SequenceSearchResult.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2014 ETH Zuerich, SIS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.api.v1.dto;
+
+import java.io.Serializable;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * Result of a sequence search. Returns the code of the data set where the sequence has been found,
+ * the path of the file inside the data set which has the found sequence, and the sequence identifier.
+ *
+ * @author Franz-Josef Elmer
+ */
+@JsonObject("SequenceSearchResult")
+public class SequenceSearchResult implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+    
+    private String sequenceDatabaseName;
+    
+    private String dataSetCode;
+    
+    private String pathInDataSet;
+    
+    private String sequenceIdentifier;
+    
+    private int positionInSequence;
+
+    public String getSequenceDatabaseName()
+    {
+        return sequenceDatabaseName;
+    }
+
+    public void setSequenceDatabaseName(String sequenceDatabaseKey)
+    {
+        this.sequenceDatabaseName = sequenceDatabaseKey;
+    }
+
+    public String getDataSetCode()
+    {
+        return dataSetCode;
+    }
+
+    public void setDataSetCode(String dataSet)
+    {
+        this.dataSetCode = dataSet;
+    }
+
+    public String getPathInDataSet()
+    {
+        return pathInDataSet;
+    }
+
+    public void setPathInDataSet(String pathInDataSet)
+    {
+        this.pathInDataSet = pathInDataSet;
+    }
+
+    public String getSequenceIdentifier()
+    {
+        return sequenceIdentifier;
+    }
+
+    public void setSequenceIdentifier(String sequenceIdentifier)
+    {
+        this.sequenceIdentifier = sequenceIdentifier;
+    }
+
+    public int getPositionInSequence()
+    {
+        return positionInSequence;
+    }
+
+    public void setPositionInSequence(int positionInSequence)
+    {
+        this.positionInSequence = positionInSequence;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Database: " + sequenceDatabaseName + ", Data set: " + dataSetCode + ", path: " + pathInDataSet 
+                + ", identifier: [" + sequenceIdentifier + "], position: " + positionInSequence;
+    }
+
+}