From b4f620a673d7a41cfa708cdd5bc68452fcff3ef2 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Fri, 23 Apr 2010 13:59:51 +0000
Subject: [PATCH] [LMS-1491] listing feature vectors; introduced
 CsvFileReaderHelper

SVN: 15605
---
 .../server/TabularDataGraphServlet.java       |  37 +--
 ...bularDataGraphCollectionConfiguration.java |  12 +-
 .../server/DssServiceRpcScreening.java        | 212 +++++++++++++++++-
 .../shared/api/v1/dto/FeatureVector.java      |   7 +
 .../api/v1/dto/FeatureVectorDataset.java      |  18 ++
 .../cisd/utils/CsvFileReaderHelper.java       | 152 +++++++++++++
 .../server/DssServiceRpcScreeningTest.java    | 130 +++++++++++
 7 files changed, 526 insertions(+), 42 deletions(-)
 create mode 100644 screening/source/java/ch/systemsx/cisd/utils/CsvFileReaderHelper.java
 create mode 100644 screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java

diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java
index 0e9ce3ec0fc..5a57b75a30f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/TabularDataGraphServlet.java
@@ -17,12 +17,8 @@
 package ch.systemsx.cisd.openbis.dss.generic.server;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.List;
 
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
@@ -30,12 +26,11 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import com.csvreader.CsvReader;
-
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.generic.server.graph.ITabularDataGraph;
 import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphCollectionConfiguration;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+import ch.systemsx.cisd.utils.CsvFileReaderHelper;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -185,34 +180,6 @@ public class TabularDataGraphServlet extends AbstractDatasetDownloadServlet
      */
     private DatasetFileLines getDatasetFileLines(String path) throws IOException
     {
-        File file = new File(path);
-        CsvReader reader = getCsvReader(file);
-        List<String[]> lines = new ArrayList<String[]>();
-        while (reader.readRecord())
-        {
-            lines.add(reader.getValues());
-        }
-
-        return new DatasetFileLines(file, path, lines);
-    }
-
-    /**
-     * Get a CsvReader for parsing a tabular data file.
-     */
-    private CsvReader getCsvReader(File file) throws IOException
-    {
-        if (file.isFile() == false)
-        {
-            throw new UserFailureException(file + " does not exist or is not a file.");
-        }
-        FileInputStream fileInputStream = new FileInputStream(file);
-
-        CsvReader csvReader = new CsvReader(fileInputStream, Charset.defaultCharset());
-        csvReader.setDelimiter(configuration.getColumnDelimiter());
-        csvReader.setSkipEmptyRecords(true);
-        csvReader.setUseComments(configuration.isIgnoreComments());
-        csvReader.setComment(configuration.getCommentDelimiter());
-
-        return csvReader;
+        return CsvFileReaderHelper.getDatasetFileLines(new File(path), configuration);
     }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataGraphCollectionConfiguration.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataGraphCollectionConfiguration.java
index 77b57e02b1d..32297581ed5 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataGraphCollectionConfiguration.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataGraphCollectionConfiguration.java
@@ -32,11 +32,12 @@ import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphConfigu
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PropertyParametersUtil;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PropertyParametersUtil.SectionProperties;
+import ch.systemsx.cisd.utils.CsvFileReaderHelper.ICsvFileReaderConfiguration;
 
 /**
  * @author Chandrasekhar Ramakrishnan
  */
-public class TabularDataGraphCollectionConfiguration
+public class TabularDataGraphCollectionConfiguration implements ICsvFileReaderConfiguration
 {
     private static final String SEPARATOR_PROPERTY_KEY = "separator";
 
@@ -252,9 +253,6 @@ public class TabularDataGraphCollectionConfiguration
         return columnDelimiter;
     }
 
-    /**
-     * Should comments be ignored?
-     */
     public boolean isIgnoreComments()
     {
         return ignoreComments;
@@ -265,6 +263,11 @@ public class TabularDataGraphCollectionConfiguration
         return comment;
     }
 
+    public boolean isSkipEmptyRecords()
+    {
+        return true;
+    }
+
     public int getImageWidth()
     {
         return imageWidth;
@@ -289,4 +292,5 @@ public class TabularDataGraphCollectionConfiguration
     {
         return graphNames;
     }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
index e78779680fb..97046e3fc7f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java
@@ -19,9 +19,18 @@ package ch.systemsx.cisd.openbis.dss.screening.server;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.csvreader.CsvReader;
 
 import ch.systemsx.cisd.bds.hcs.Geometry;
 import ch.systemsx.cisd.bds.hcs.HCSDatasetLoader;
@@ -29,16 +38,20 @@ import ch.systemsx.cisd.bds.hcs.Location;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDssServiceRpc;
 import ch.systemsx.cisd.openbis.dss.generic.server.images.ImageChannelsUtils;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
 import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
 import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVector;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDataset;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IImageDatasetIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
+import ch.systemsx.cisd.utils.CsvFileReaderHelper;
 
 /**
  * Implementation of the screening API interface using RPC. The instance will be created in spring
@@ -72,11 +85,44 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
     public List<String> listAvailableFeatureNames(String sessionToken,
             List<? extends IFeatureVectorDatasetIdentifier> featureDatasets)
     {
-        // TODO Auto-generated method stub
-
+        try
+        {
+            List<String> result = new ArrayList<String>(); // keep the order
+            for (IFeatureVectorDatasetIdentifier dataset : featureDatasets)
+            {
+                // add only new feature names
+                String[] featureNames = extractFeatureNames(sessionToken, dataset);
+                for (String featureName : featureNames)
+                {
+                    if (result.contains(featureName) == false)
+                    {
+                        result.add(featureName);
+                    }
+                }
+            }
+            return result;
+        } catch (IOException ex)
+        {
+            // FIXME handle exceptions
+            ex.printStackTrace();
+        }
         return null;
     }
 
+    private String[] extractFeatureNames(String sessionToken,
+            IFeatureVectorDatasetIdentifier dataset) throws IOException
+    {
+        return extractFeatureNames(getDatasetFile(sessionToken, dataset));
+    }
+
+    private File getDatasetFile(String sessionToken, IDatasetIdentifier dataset)
+    {
+        // FIXME return file in subdirectory
+        return checkAccessAndGetRootDirectory(sessionToken, dataset.getDatasetCode());
+    }
+
+    //
+
     public List<ImageDatasetMetadata> listImageMetadata(String sessionToken,
             List<? extends IImageDatasetIdentifier> imageDatasets)
     {
@@ -88,10 +134,30 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
             List<? extends IFeatureVectorDatasetIdentifier> featureDatasets,
             List<String> featureNames)
     {
-        // TODO Auto-generated method stub
+        try
+        {
+            List<FeatureVectorDataset> result = new ArrayList<FeatureVectorDataset>();
+
+            for (IFeatureVectorDatasetIdentifier dataset : featureDatasets)
+            {
+                result.add(createFeatureVectorDataset(sessionToken, dataset, featureNames));
+            }
+            return result;
+        } catch (IOException ex)
+        {
+            // FIXME handle exceptions
+            ex.printStackTrace();
+        }
         return null;
     }
 
+    private FeatureVectorDataset createFeatureVectorDataset(String sessionToken,
+            IFeatureVectorDatasetIdentifier dataset, List<String> featureNames) throws IOException
+    {
+        return createFeatureVectorDataset(getDatasetFile(sessionToken, dataset), dataset,
+                featureNames);
+    }
+
     public InputStream loadImage(String sessionToken, PlateImageReference imageReference)
     {
         ExternalData imageDataset =
@@ -193,4 +259,144 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc implements
         return dataset.getDataSetType().getCode().equals(ScreeningConstants.IMAGE_DATASET_TYPE);
     }
 
+    //
+    // helper methods and classes
+    //
+
+    // exposed for testing
+    static String[] extractFeatureNames(File datasetFile) throws IOException
+    {
+        CsvReader reader = null;
+        try
+        {
+            reader = CsvFileReaderHelper.getCsvReader(datasetFile);
+            if (reader.readHeaders())
+            {
+                return reader.getHeaders();
+            }
+            return new String[0]; // empty file
+        } finally
+        {
+            if (reader != null)
+            {
+                reader.close();
+            }
+        }
+    }
+
+    // exposed for testing
+    static FeatureVectorDataset createFeatureVectorDataset(File datasetFile,
+            IFeatureVectorDatasetIdentifier dataset, List<String> featureNames) throws IOException
+    {
+        DatasetFileLines fileLines = CsvFileReaderHelper.getDatasetFileLines(datasetFile);
+        String[] headerTokens = fileLines.getHeaderTokens();
+
+        List<String> existingFeatureNames = new ArrayList<String>();
+        Set<String> columnNames = new HashSet<String>(Arrays.asList(headerTokens));
+        for (String featureName : featureNames)
+        {
+            if (columnNames.contains(featureName))
+            {
+                existingFeatureNames.add(featureName);
+            }
+        }
+
+        Map<String, Integer> indexByName = new HashMap<String, Integer>();
+        for (int i = 0; i < headerTokens.length; i++)
+        {
+            indexByName.put(headerTokens[i].toLowerCase(), i);
+        }
+
+        FeatureVectorDatasetBuilder builder =
+                new FeatureVectorDatasetBuilder(dataset, existingFeatureNames);
+        for (String[] dataLine : fileLines.getDataLines())
+        {
+            FeatureVector vector =
+                    tryExtractFeatureVector(dataLine, indexByName, existingFeatureNames);
+            if (vector != null)
+            {
+                builder.addFeatureVector(vector);
+            } else
+            {
+                operationLog.warn("wrong format or well not found");
+            }
+        }
+        return builder.create();
+    }
+
+    private static FeatureVector tryExtractFeatureVector(String[] dataLine,
+            Map<String, Integer> indexByName, List<String> featureNames)
+    {
+        WellPosition wellPositionOrNull = tryExtractWellPosition(dataLine, indexByName);
+
+        if (wellPositionOrNull != null)
+        {
+            double[] values = new double[featureNames.size()];
+            for (int i = 0; i < featureNames.size(); i++)
+            {
+                try
+                {
+                    int index = indexByName.get(featureNames.get(i));
+                    values[i] = Double.parseDouble(dataLine[index]);
+                } catch (NumberFormatException ex)
+                {
+                    // skip this feature
+                    return null;
+                }
+            }
+            return new FeatureVector(wellPositionOrNull, values);
+        }
+        return null;
+    }
+
+    private static WellPosition tryExtractWellPosition(String[] fileLine,
+            Map<String, Integer> indexByName)
+    {
+        String coordinate;
+        Integer wellIndexOrNull = indexByName.get("WellName".toLowerCase());
+        if (wellIndexOrNull != null)
+        {
+            coordinate = fileLine[wellIndexOrNull];
+        } else
+        {
+            Integer rowIndexOrNull = indexByName.get("row".toLowerCase());
+            Integer colIndexOrNull = indexByName.get("col".toLowerCase());
+            if (rowIndexOrNull == null || colIndexOrNull == null)
+            {
+                operationLog.warn("well position missing");
+                return null;
+            }
+            coordinate = fileLine[rowIndexOrNull] + fileLine[colIndexOrNull];
+        }
+
+        Location location = Location.tryCreateLocationFromMatrixCoordinate(coordinate);
+        return new WellPosition(location.getY(), location.getX());
+    }
+
+    private static class FeatureVectorDatasetBuilder
+    {
+        private final IFeatureVectorDatasetIdentifier dataset;
+
+        private final List<String> featureNames;
+
+        private final List<FeatureVector> featureVectors;
+
+        public FeatureVectorDatasetBuilder(IFeatureVectorDatasetIdentifier dataset,
+                List<String> featureNames)
+        {
+            this.dataset = dataset;
+            this.featureNames = featureNames;
+            this.featureVectors = new ArrayList<FeatureVector>();
+        }
+
+        public void addFeatureVector(FeatureVector vector)
+        {
+            featureVectors.add(vector);
+        }
+
+        public FeatureVectorDataset create()
+        {
+            return new FeatureVectorDataset(dataset, featureNames, featureVectors);
+        }
+    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVector.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVector.java
index 6d35e3a512b..a68a1a0b5a3 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVector.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVector.java
@@ -1,6 +1,7 @@
 package ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto;
 
 import java.io.Serializable;
+import java.util.Arrays;
 
 /**
  * Feature vector for one well.
@@ -32,4 +33,10 @@ public class FeatureVector implements Serializable
     {
         return values;
     }
+
+    @Override
+    public String toString()
+    {
+        return "wellPosition: " + wellPosition + ", values: " + Arrays.toString(values);
+    }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVectorDataset.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVectorDataset.java
index 5dfde08b5ff..bb13e2ec41f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVectorDataset.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/dto/FeatureVectorDataset.java
@@ -43,4 +43,22 @@ public class FeatureVectorDataset implements Serializable
     {
         return featureVectors;
     }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append("datasetCode: " + dataset.getDatasetCode());
+        sb.append(", storeUrl: " + dataset.getDatastoreServerUrl());
+        sb.append("\n\tfeatures: ");
+        for (int i = 0; i < featureNames.size(); i++)
+        {
+            sb.append(featureNames.get(i) + ", ");
+        }
+        for (int i = 0; i < featureVectors.size(); i++)
+        {
+            sb.append("\n\t" + featureVectors.get(i));
+        }
+        return sb.toString();
+    }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/utils/CsvFileReaderHelper.java b/screening/source/java/ch/systemsx/cisd/utils/CsvFileReaderHelper.java
new file mode 100644
index 00000000000..1bc83d35184
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/utils/CsvFileReaderHelper.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2010 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.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.csvreader.CsvReader;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+
+/**
+ * @author Piotr Buczek
+ */
+public class CsvFileReaderHelper
+{
+
+    /**
+     * Configuration for reading csv file.
+     * 
+     * @author Piotr Buczek
+     */
+    public interface ICsvFileReaderConfiguration
+    {
+
+        public boolean isIgnoreComments();
+
+        public boolean isSkipEmptyRecords();
+
+        public char getColumnDelimiter();
+
+        public char getCommentDelimiter();
+    }
+
+    /**
+     * Get a CsvReader for parsing a tabular data file with default configuration.
+     */
+    public static CsvReader getCsvReader(File file) throws IOException
+    {
+        return getCsvReader(file, new DefaultCsvFileReaderConfiguration());
+    }
+
+    /**
+     * Get a CsvReader for parsing a tabular data file with specified <var>configuration</var>.
+     */
+    public static CsvReader getCsvReader(File file, ICsvFileReaderConfiguration configuration)
+            throws IOException
+    {
+        if (file.isFile() == false)
+        {
+            throw new UserFailureException(file + " does not exist or is not a file.");
+        }
+        FileInputStream fileInputStream = new FileInputStream(file);
+
+        CsvReader csvReader = new CsvReader(fileInputStream, Charset.defaultCharset());
+        csvReader.setDelimiter(configuration.getColumnDelimiter());
+        csvReader.setUseComments(configuration.isIgnoreComments());
+        csvReader.setComment(configuration.getCommentDelimiter());
+        csvReader.setSkipEmptyRecords(configuration.isSkipEmptyRecords());
+
+        return csvReader;
+    }
+
+    /**
+     * Return the tabular data as a DatasetFileLines with default configuration.
+     */
+    public static DatasetFileLines getDatasetFileLines(File file) throws IOException
+    {
+        return getDatasetFileLines(file, new DefaultCsvFileReaderConfiguration());
+    }
+
+    /**
+     * Return the tabular data as a DatasetFileLines with specified <var>configuration</var>.
+     */
+    public static DatasetFileLines getDatasetFileLines(File file,
+            ICsvFileReaderConfiguration configuration) throws IOException
+    {
+        CsvReader reader = null;
+        try
+        {
+            reader = CsvFileReaderHelper.getCsvReader(file, configuration);
+            List<String[]> lines = new ArrayList<String[]>();
+
+            while (reader.readRecord())
+            {
+                lines.add(reader.getValues());
+            }
+
+            return new DatasetFileLines(file, file.getPath(), lines);
+        } finally
+        {
+            if (reader != null)
+            {
+                reader.close();
+            }
+        }
+    }
+
+    /**
+     * Default configuration for reading csv file:
+     * <ul>
+     * <li>';' - column delimiter
+     * <li>'#' - comment delimiter
+     * <li>ignoring empty records
+     * </ul>
+     * 
+     * @author Piotr Buczek
+     */
+    public static class DefaultCsvFileReaderConfiguration implements ICsvFileReaderConfiguration
+    {
+
+        public char getColumnDelimiter()
+        {
+            return ';';
+        }
+
+        public char getCommentDelimiter()
+        {
+            return '#';
+        }
+
+        public boolean isIgnoreComments()
+        {
+            return true;
+        }
+
+        public boolean isSkipEmptyRecords()
+        {
+            return true;
+        }
+
+    }
+}
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java
new file mode 100644
index 00000000000..7ba1e20c2a2
--- /dev/null
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.screening.server;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase;
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDataset;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVectorDatasetIdentifier;
+
+/**
+ * Test cases for the {@link DssServiceRpcScreening}.
+ * 
+ * @author Piotr Buczek
+ */
+public class DssServiceRpcScreeningTest extends AbstractFileSystemTestCase
+{
+
+    private static final String EXAMPLE1 =
+            "wellName;f0;f1;f2\n" + "A01;1.0;1.1;1.2\n" + "C7;2.0;2.1;2.2\n" + "D7;3.0;3.1;3.2\n"
+                    + "D8;A3.0;3.1;3.2\n";
+
+    private static final String EXAMPLE2 =
+            "row;col;f0;f1;f2\n" + "A;01;1.0;1.1;1.2\n" + "C;7;2.0;2.1;2.2\n" + "D;7;3.0;3.1;3.2\n"
+                    + "D;8;A3.0;3.1;3.2\n";
+
+    @Test
+    public void testExtractFeatureNames()
+    {
+        File datasetFile = new File(workingDirectory, "scrDataset");
+        FileUtilities.writeToFile(datasetFile, EXAMPLE1);
+        try
+        {
+            String[] names = DssServiceRpcScreening.extractFeatureNames(datasetFile);
+            assertEquals("[wellName, f0, f1, f2]", Arrays.toString(names));
+        } catch (IOException ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testCreateFeatureVectorDataset()
+    {
+        File datasetFile = new File(workingDirectory, "scrDataset");
+        final String datasetCode = "CODE";
+        final String url = "URL";
+        final String[] fileData =
+            { EXAMPLE1, EXAMPLE2 };
+        try
+        {
+            for (String data : fileData)
+            {
+                FileUtilities.writeToFile(datasetFile, data);
+                IFeatureVectorDatasetIdentifier dataset =
+                        createFeatureVectorDatasetIdentifier(datasetCode, url);
+                FeatureVectorDataset result =
+                        DssServiceRpcScreening.createFeatureVectorDataset(datasetFile, dataset,
+                                Arrays.asList(new String[]
+                                    { "f0", "f2", "f3" }));
+
+                assertEquals(dataset, result.getDataset());
+
+                assertEquals(2, result.getFeatureNames().size());
+                assertEquals("f0", result.getFeatureNames().get(0));
+                assertEquals("f2", result.getFeatureNames().get(1));
+
+                assertEquals(3, result.getFeatureVectors().size());
+
+                assertEquals("[1, 1]", result.getFeatureVectors().get(0).getWellPosition()
+                        .toString());
+                assertEquals("[1.0, 1.2]", Arrays.toString(result.getFeatureVectors().get(0)
+                        .getValues()));
+
+                assertEquals("[3, 7]", result.getFeatureVectors().get(1).getWellPosition()
+                        .toString());
+                assertEquals("[2.0, 2.2]", Arrays.toString(result.getFeatureVectors().get(1)
+                        .getValues()));
+
+                assertEquals("[4, 7]", result.getFeatureVectors().get(2).getWellPosition()
+                        .toString());
+                assertEquals("[3.0, 3.2]", Arrays.toString(result.getFeatureVectors().get(2)
+                        .getValues()));
+            }
+
+        } catch (IOException ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    private IFeatureVectorDatasetIdentifier createFeatureVectorDatasetIdentifier(
+            final String datasetCode, final String url)
+    {
+        return new IFeatureVectorDatasetIdentifier()
+            {
+
+                public String getDatasetCode()
+                {
+                    return datasetCode;
+                }
+
+                public String getDatastoreServerUrl()
+                {
+                    return url;
+                }
+
+            };
+    }
+
+}
-- 
GitLab