From ddeb74bf92374d7d9f65d99288388f17b057c517 Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Tue, 10 Aug 2010 10:58:52 +0000
Subject: [PATCH] LMS-1632 Generalize the graph generation code to accept
 tabular data, either from a file or from the DB.

SVN: 17377
---
 .../AbstractTabularDataGraphServlet.java      | 202 ++++++++++++++++++
 .../server/ImagingDataGraphServlet.java       | 194 +++++++++++++++++
 .../server/TabularDataGraphServlet.java       | 156 +-------------
 .../graph/AbstractTabularDataGraph.java       |   6 +-
 ...bularDataGraphCollectionConfiguration.java |   4 +-
 .../server/graph/TabularDataHeatmap.java      |   4 +-
 .../server/graph/TabularDataHistogram.java    |   4 +-
 .../server/graph/TabularDataScatterplot.java  |   4 +-
 ...baseImageAnalysisGraphReportingPlugin.java | 152 +++++++++++++
 ...sedImageAnalysisGraphReportingPlugin.java} |  18 +-
 10 files changed, 579 insertions(+), 165 deletions(-)
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractTabularDataGraphServlet.java
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ImagingDataGraphServlet.java
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DatabaseImageAnalysisGraphReportingPlugin.java
 rename screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/{ImageAnalysisGraphReportingPlugin.java => FileBasedImageAnalysisGraphReportingPlugin.java} (86%)

diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractTabularDataGraphServlet.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractTabularDataGraphServlet.java
new file mode 100644
index 00000000000..c755bb227fa
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractTabularDataGraphServlet.java
@@ -0,0 +1,202 @@
+/*
+ * 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.openbis.dss.generic.server;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+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.ITabularData;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public abstract class AbstractTabularDataGraphServlet extends AbstractDatasetDownloadServlet
+{
+    private static final long serialVersionUID = 1L;
+
+    public static final String DATASET_CODE_PARAM = "dataset";
+
+    public static final String GRAPH_TYPE_CODE = "type";
+
+    protected TabularDataGraphCollectionConfiguration configuration;
+
+    private static final String PROPERTIES_FILE_KEY = "properties-file";
+
+    public static final String FILE_PATH_PARAM = "file";
+
+    /**
+     * A utility class for dealing with the URL parameters required to generate an image. This class
+     * makes sure all the required parameters are in the request (it throws exceptions otherwise),
+     * and it defaults values for all optional parameters if they are not in the request.
+     * 
+     * @author Chandrasekhar Ramakrishnan
+     */
+    protected static class RequestParams
+    {
+        // optional parameters
+        public final static String WIDTH_PARAM = "w";
+
+        public final static String HEIGHT_PARAM = "h";
+
+        private final String sessionId;
+
+        private final String datasetCode;
+
+        private final String filePathOrNull;
+
+        private final String graphName;
+
+        private final int width;
+
+        private final int height;
+
+        public RequestParams(HttpServletRequest request)
+        {
+            sessionId = getRequiredParameter(request, SESSION_ID_PARAM);
+            datasetCode = getRequiredParameter(request, DATASET_CODE_PARAM);
+            filePathOrNull = getOptionalParameter(request, FILE_PATH_PARAM);
+            graphName = getRequiredParameter(request, GRAPH_TYPE_CODE);
+            width = getIntParam(request, WIDTH_PARAM, 0);
+            height = getIntParam(request, HEIGHT_PARAM, 0);
+        }
+
+        private static int getIntParam(HttpServletRequest request, String paramName,
+                int defaultValue)
+        {
+            String value = request.getParameter(paramName);
+            if (value == null)
+                return defaultValue;
+
+            try
+            {
+                return Integer.valueOf(value);
+            } catch (NumberFormatException e)
+            {
+                throw new UserFailureException("parameter " + paramName
+                        + " should be an integer, but is: " + value);
+            }
+        }
+
+        private static String getOptionalParameter(final HttpServletRequest request,
+                String paramName)
+        {
+            String value = request.getParameter(paramName);
+            return value;
+        }
+
+        private static String getRequiredParameter(final HttpServletRequest request,
+                String paramName)
+        {
+            String value = request.getParameter(paramName);
+            if (value == null)
+            {
+                throw new UserFailureException("no value for the parameter " + paramName
+                        + " found in the URL");
+            }
+            return value;
+        }
+    }
+
+    /**
+     *
+     *
+     */
+    public AbstractTabularDataGraphServlet()
+    {
+        super();
+    }
+
+    /**
+     * @param applicationContext
+     */
+    public AbstractTabularDataGraphServlet(ApplicationContext applicationContext)
+    {
+        super(applicationContext);
+    }
+
+    @Override
+    protected synchronized void doSpecificInitialization(Enumeration<String> parameterNames,
+            ServletConfig servletConfig)
+    {
+        // Only initialize the db properties once
+        if (configuration != null)
+            return;
+
+        String propertiesFilePath = servletConfig.getInitParameter(PROPERTIES_FILE_KEY);
+        configuration =
+                TabularDataGraphCollectionConfiguration.getConfiguration(propertiesFilePath);
+    }
+
+    @Override
+    protected final void doGet(final HttpServletRequest request, final HttpServletResponse response)
+            throws ServletException, IOException
+    {
+        try
+        {
+            // Get the parameters from the request
+            RequestParams params = new RequestParams(request);
+            String sessionId = params.sessionId;
+            String datasetCode = params.datasetCode;
+            String filePathOrNull = params.filePathOrNull;
+
+            // Get the session and user from the request
+            HttpSession session = tryGetOrCreateSession(request, sessionId);
+            if (session == null)
+            {
+                printSessionExpired(response);
+                return;
+            }
+            // Check that the user has view access to the data
+            // NOTE: This throws an exception -- it may be nicer to return an image for a
+            // non-accessible dataset...
+            ensureDatasetAccessible(datasetCode, session, sessionId);
+
+            // Get the tabular data
+            ITabularData fileLines = getDatasetLines(datasetCode, filePathOrNull);
+
+            // Generate an image into the stream
+            ITabularDataGraph generator =
+                    configuration.getGraph(params.graphName, fileLines, response.getOutputStream());
+
+            if (params.height > 0 && params.width > 0)
+            {
+                generator.generateImage(params.width, params.height);
+            } else
+            {
+                generator.generateImage();
+            }
+
+        } catch (Exception e)
+        {
+            e.printStackTrace();
+            printErrorResponse(response, "Invalid Request");
+        }
+    }
+
+    protected abstract ITabularData getDatasetLines(String dataSetCode, String filePathOrNull)
+            throws IOException;
+
+}
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ImagingDataGraphServlet.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ImagingDataGraphServlet.java
new file mode 100644
index 00000000000..3aa322e29f9
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ImagingDataGraphServlet.java
@@ -0,0 +1,194 @@
+/*
+ * 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.openbis.dss.generic.server;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
+import ch.systemsx.cisd.openbis.dss.shared.DssScreeningUtils;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.PlateUtils;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.IImagingQueryDAO;
+
+/**
+ * Create a graph from the imaging database.
+ * <p>
+ * TODO 2010-08-09, CR, LMS-1692, This implementation is inefficient. The better way to implement
+ * this would be to lazily get feature vectors necessary for generating the graph, not to egerly get
+ * all feature vectors.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class ImagingDataGraphServlet extends AbstractTabularDataGraphServlet
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private IImagingQueryDAO imagingDbDao;
+
+    private IEncapsulatedOpenBISService openBisService;
+
+    /**
+     * An CSV-file-like interface to feature data from the database.
+     * 
+     * @author Chandrasekhar Ramakrishnan
+     */
+    private final class ImagingTabularData implements ITabularData
+    {
+        private static final String WELL_NAME_COLUMN = "WellName";
+
+        private static final String WELL_ROW_COLUMN = "Row";
+
+        private static final String WELL_COLUMN_COLUMN = "Column";
+
+        private final IImagingQueryDAO dao;
+
+        private final IEncapsulatedOpenBISService service;
+
+        private final String dataSetCode;
+
+        private String[] headerTokens;
+
+        private ArrayList<String[]> lines;
+
+        private ImagingTabularData(IImagingQueryDAO dao, IEncapsulatedOpenBISService service,
+                String dataSetCode)
+        {
+            this.dao = dao;
+            this.service = service;
+            this.dataSetCode = dataSetCode;
+            initialize();
+        }
+
+        private void initialize()
+        {
+            final FeatureTableBuilder tableBuilder = new FeatureTableBuilder(dao, service);
+            tableBuilder.addFeatureVectorsOfDataSet(dataSetCode);
+
+            List<String> featureNames = tableBuilder.getFeatureNames();
+            int headerTokensLength = featureNames.size() + 3;
+            headerTokens = new String[headerTokensLength];
+            headerTokens[0] = WELL_NAME_COLUMN;
+            headerTokens[1] = WELL_ROW_COLUMN;
+            headerTokens[2] = WELL_COLUMN_COLUMN;
+
+            int i = 1;
+            for (String name : featureNames)
+            {
+                headerTokens[i++] = name;
+            }
+
+            lines = new ArrayList<String[]>();
+
+            final List<FeatureTableRow> rows = tableBuilder.createFeatureTableRows();
+            for (FeatureTableRow row : rows)
+            {
+                String[] line = new String[headerTokensLength];
+                WellPosition pos = row.getWellPosition();
+                String rowLetter = PlateUtils.translateRowNumberIntoLetterCode(pos.getWellRow());
+                String columnNumber = Integer.toString(row.getWellPosition().getWellColumn());
+                line[0] = rowLetter + columnNumber;
+                line[1] = rowLetter;
+                line[2] = columnNumber;
+                i = 1;
+                float[] values = row.getFeatureValues();
+                for (float value : values)
+                {
+                    line[i++] = Float.toString(value);
+                }
+                lines.add(line);
+            }
+            // final ImgDatasetDTO dataSet = dao.tryGetDatasetByPermId(dataSetCode);
+            // if (dataSet == null)
+            // {
+            // throw new UserFailureException("Unkown data set " + dataSetCode);
+            // }
+            //
+            // final List<ImgFeatureDefDTO> featureDefinitions =
+            // dao.listFeatureDefsByDataSetId(dataSet.getId());
+            //
+            // int headersLength = featureDefinitions.size();
+            // headerTokens = new String[headersLength];
+            // lines = new ArrayList<String[]>();
+            // int featureDefCount = 0;
+            // for (ImgFeatureDefDTO featureDefinition : featureDefinitions)
+            // {
+            // headerTokens[featureDefCount++] = featureDefinition.getName();
+            // }
+            // int numRows = dataSet.getFieldNumberOfRows();
+            // int numCols = dataSet.getFieldNumberOfColumns();
+            // for (int row = 0; row < numRows; ++row)
+            // {
+            // for (int col = 0; col < numCols; ++col)
+            // {
+            // for (ImgFeatureDefDTO featureDefinition : featureDefinitions)
+            // {
+            // List<ImgFeatureValuesDTO> featureValues =
+            // dao.getFeatureValues(featureDefinition);
+            // }
+            // }
+            // }
+        }
+
+        public List<String[]> getDataLines()
+        {
+            return lines;
+        }
+
+        public String[] getHeaderTokens()
+        {
+            return headerTokens;
+        }
+
+    }
+
+    @Override
+    protected ITabularData getDatasetLines(String dataSetCode, String filePathOrNull)
+            throws IOException
+    {
+        return new ImagingTabularData(getDAO(), getService(), dataSetCode);
+    }
+
+    private IImagingQueryDAO getDAO()
+    {
+        synchronized (this)
+        {
+            if (imagingDbDao == null)
+            {
+                imagingDbDao = DssScreeningUtils.createQuery();
+            }
+        }
+        return imagingDbDao;
+    }
+
+    private IEncapsulatedOpenBISService getService()
+    {
+        synchronized (this)
+        {
+            if (openBisService == null)
+            {
+                openBisService = ServiceProvider.getOpenBISService();
+            }
+        }
+        return openBisService;
+    }
+
+}
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 a3da0caf8f7..7fc440aef44 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
@@ -18,168 +18,30 @@ package ch.systemsx.cisd.openbis.dss.generic.server;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Enumeration;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
 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.openbis.dss.generic.server.plugins.tasks.ITabularData;
 import ch.systemsx.cisd.utils.CsvFileReaderHelper;
 
 /**
  * @author Chandrasekhar Ramakrishnan
  */
-public class TabularDataGraphServlet extends AbstractDatasetDownloadServlet
+public class TabularDataGraphServlet extends AbstractTabularDataGraphServlet
 {
-    // Required servlet parameters
-    public final static String DATASET_CODE_PARAM = "dataset";
-
-    public final static String FILE_PATH_PARAM = "file";
-
-    public final static String GRAPH_TYPE_CODE = "type";
-
     private static final long serialVersionUID = 1L;
 
-    private TabularDataGraphCollectionConfiguration configuration;
-
-    private final static String PROPERTIES_FILE_KEY = "properties-file";
-
     /**
-     * A utility class for dealing with the URL parameters required to generate an image. This class
-     * makes sure all the required parameters are in the request (it throws exceptions otherwise),
-     * and it defaults values for all optional parameters if they are not in the request.
-     * 
-     * @author Chandrasekhar Ramakrishnan
+     * Return the tabular data from a file as a DatasetFileLines.
      */
-    private static class RequestParams
-    {
-        // optional parameters
-        public final static String WIDTH_PARAM = "w";
-
-        public final static String HEIGHT_PARAM = "h";
-
-        private final String sessionId;
-
-        private final String datasetCode;
-
-        private final String filePath;
-
-        private final String graphName;
-
-        private final int width;
-
-        private final int height;
-
-        public RequestParams(HttpServletRequest request)
-        {
-            sessionId = getRequiredParameter(request, SESSION_ID_PARAM);
-            datasetCode = getRequiredParameter(request, DATASET_CODE_PARAM);
-            filePath = getRequiredParameter(request, FILE_PATH_PARAM);
-            graphName = getRequiredParameter(request, GRAPH_TYPE_CODE);
-            width = getIntParam(request, WIDTH_PARAM, 0);
-            height = getIntParam(request, HEIGHT_PARAM, 0);
-        }
-
-        private static int getIntParam(HttpServletRequest request, String paramName,
-                int defaultValue)
-        {
-            String value = request.getParameter(paramName);
-            if (value == null)
-                return defaultValue;
-
-            try
-            {
-                return Integer.valueOf(value);
-            } catch (NumberFormatException e)
-            {
-                throw new UserFailureException("parameter " + paramName
-                        + " should be an integer, but is: " + value);
-            }
-        }
-
-        private static String getRequiredParameter(final HttpServletRequest request,
-                String paramName)
-        {
-            String value = request.getParameter(paramName);
-            if (value == null)
-            {
-                throw new UserFailureException("no value for the parameter " + paramName
-                        + " found in the URL");
-            }
-            return value;
-        }
-    }
-
     @Override
-    protected synchronized void doSpecificInitialization(Enumeration<String> parameterNames,
-            ServletConfig servletConfig)
+    protected ITabularData getDatasetLines(String dataSetCode, String pathOrNull)
+            throws IOException
     {
-        // Only initialize the db properties once
-        if (configuration != null)
-            return;
-
-        String propertiesFilePath = servletConfig.getInitParameter(PROPERTIES_FILE_KEY);
-        configuration =
-                TabularDataGraphCollectionConfiguration.getConfiguration(propertiesFilePath);
-    }
-
-    @Override
-    protected final void doGet(final HttpServletRequest request, final HttpServletResponse response)
-            throws ServletException, IOException
-    {
-        try
+        if (pathOrNull == null)
         {
-            // Get the parameters from the request
-            RequestParams params = new RequestParams(request);
-            String sessionId = params.sessionId;
-            String datasetCode = params.datasetCode;
-            String filePath = params.filePath;
-
-            // Get the session and user from the request
-            HttpSession session = tryGetOrCreateSession(request, sessionId);
-            if (session == null)
-            {
-                printSessionExpired(response);
-                return;
-            }
-            // Check that the user has view access to the data
-            // NOTE: This throws an exception -- it may be nicer to return an image for a
-            // non-accessible dataset...
-            ensureDatasetAccessible(datasetCode, session, sessionId);
-
-            // Get the tabular data
-            DatasetFileLines fileLines = getDatasetFileLines(filePath);
-
-            // Generate an image image into the stream
-            ITabularDataGraph generator =
-                    configuration.getGraph(params.graphName, fileLines, response.getOutputStream());
-
-            if (params.height > 0 && params.width > 0)
-            {
-                generator.generateImage(params.width, params.height);
-            } else
-            {
-                generator.generateImage();
-            }
-
-        } catch (Exception e)
-        {
-            e.printStackTrace();
-            printErrorResponse(response, "Invalid Request");
+            throw new UserFailureException("No value for the parameter " + FILE_PATH_PARAM
+                    + " found in the URL");
         }
-    }
-
-    /**
-     * Return the tabular data as a DatasetFileLines.
-     */
-    private DatasetFileLines getDatasetFileLines(String path) throws IOException
-    {
-        return CsvFileReaderHelper.getDatasetFileLines(new File(path), configuration);
+        return CsvFileReaderHelper.getDatasetFileLines(new File(pathOrNull), configuration);
     }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/AbstractTabularDataGraph.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/AbstractTabularDataGraph.java
index db83f51b5e4..d01086793ea 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/AbstractTabularDataGraph.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/AbstractTabularDataGraph.java
@@ -32,7 +32,7 @@ import org.jfree.chart.plot.XYPlot;
 import org.jfree.data.general.Dataset;
 import org.jfree.data.xy.DefaultXYDataset;
 
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
 
 /**
  * Abstract superclass for the different kinds of graphs.
@@ -44,11 +44,11 @@ abstract class AbstractTabularDataGraph<T extends TabularDataGraphConfiguration>
 {
     protected final T configuration;
 
-    protected final DatasetFileLines fileLines;
+    protected final ITabularData fileLines;
 
     protected final OutputStream out;
 
-    protected AbstractTabularDataGraph(T configuration, DatasetFileLines fileLines, OutputStream out)
+    protected AbstractTabularDataGraph(T configuration, ITabularData fileLines, OutputStream out)
     {
         this.configuration = configuration;
         this.fileLines = fileLines;
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 6521373bd4a..bd66d97e497 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
@@ -31,7 +31,7 @@ import ch.systemsx.cisd.common.utilities.PropertyParametersUtil;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.common.utilities.PropertyParametersUtil.SectionProperties;
 import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphConfiguration.GraphType;
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
 import ch.systemsx.cisd.utils.CsvFileReaderHelper.ICsvFileReaderConfiguration;
 
 /**
@@ -222,7 +222,7 @@ public class TabularDataGraphCollectionConfiguration implements ICsvFileReaderCo
      * @param fileLines The data to generate a graph from
      * @param out The stream to write the graph to
      */
-    public ITabularDataGraph getGraph(String graphName, DatasetFileLines fileLines, OutputStream out)
+    public ITabularDataGraph getGraph(String graphName, ITabularData fileLines, OutputStream out)
     {
         TabularDataGraphConfiguration config = graphTypeMap.get(graphName);
         if (null == config)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHeatmap.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHeatmap.java
index d8f83735aef..2cd95f05f0a 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHeatmap.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHeatmap.java
@@ -40,7 +40,7 @@ import org.jfree.ui.RectangleEdge;
 import org.jfree.ui.RectangleInsets;
 
 import ch.systemsx.cisd.bds.hcs.Location;
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -52,7 +52,7 @@ public class TabularDataHeatmap extends AbstractTabularDataGraph<TabularDataHeat
      * @param configuration
      */
     public TabularDataHeatmap(TabularDataHeatmapConfiguration configuration,
-            DatasetFileLines fileLines, OutputStream out)
+            ITabularData fileLines, OutputStream out)
     {
         super(configuration, fileLines, out);
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHistogram.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHistogram.java
index afeadce9c61..91b32532964 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHistogram.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataHistogram.java
@@ -28,7 +28,7 @@ import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.data.general.Dataset;
 import org.jfree.data.statistics.HistogramDataset;
 
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -41,7 +41,7 @@ public class TabularDataHistogram extends
      * @param configuration
      */
     public TabularDataHistogram(TabularDataHistogramConfiguration configuration,
-            DatasetFileLines fileLines, OutputStream out)
+            ITabularData fileLines, OutputStream out)
     {
         super(configuration, fileLines, out);
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataScatterplot.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataScatterplot.java
index 98adb20c9dd..fa68501d706 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataScatterplot.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/graph/TabularDataScatterplot.java
@@ -29,7 +29,7 @@ import org.jfree.data.xy.XYDataset;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
 
-import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.DatasetFileLines;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.ITabularData;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -42,7 +42,7 @@ public class TabularDataScatterplot extends
      * @param configuration
      */
     public TabularDataScatterplot(TabularDataScatterplotConfiguration configuration,
-            DatasetFileLines fileLines, OutputStream out)
+            ITabularData fileLines, OutputStream out)
     {
         super(configuration, fileLines, out);
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DatabaseImageAnalysisGraphReportingPlugin.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DatabaseImageAnalysisGraphReportingPlugin.java
new file mode 100644
index 00000000000..b0b7400e664
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DatabaseImageAnalysisGraphReportingPlugin.java
@@ -0,0 +1,152 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
+import ch.systemsx.cisd.openbis.dss.generic.server.AbstractTabularDataGraphServlet;
+import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphCollectionConfiguration;
+import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphConfiguration;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractDataMergingReportingPlugin;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.SimpleTableModelBuilder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GeneratedImageTableCell;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
+
+/**
+ * Reporting plugin that returns a table in which each column contains a graph. The number and
+ * format of the graphs can be configured in a properties file.
+ * <p>
+ * This plugin reads data from a the imaging database. The
+ * {@link FileBasedImageAnalysisGraphReportingPlugin} reads from a file.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class DatabaseImageAnalysisGraphReportingPlugin extends AbstractDataMergingReportingPlugin
+{
+    private static final long serialVersionUID = 1L;
+
+    private final String graphServletPath;
+
+    private final TabularDataGraphCollectionConfiguration configuration;
+
+    // Keys for the properties
+    private final String SERVLET_PATH_PROP = "servlet-path";
+
+    private final static String PROPERTIES_FILE_KEY = "properties-file";
+
+    public DatabaseImageAnalysisGraphReportingPlugin(Properties properties, File storeRoot)
+    {
+        super(properties, storeRoot, SEMICOLON_SEPARATOR);
+        graphServletPath = properties.getProperty(SERVLET_PATH_PROP, "datastore_server_graph/");
+        String propertiesFilePath = properties.getProperty(PROPERTIES_FILE_KEY);
+        if (propertiesFilePath == null)
+        {
+            throw new EnvironmentFailureException(
+                    "DatabaseImageAnalysisGraphReportingPlugin requires a properties file (specified with the "
+                            + PROPERTIES_FILE_KEY + "key).");
+        }
+
+        configuration =
+                TabularDataGraphCollectionConfiguration.getConfiguration(propertiesFilePath);
+    }
+
+    public TableModel createReport(List<DatasetDescription> datasets)
+    {
+        SimpleTableModelBuilder builder = new SimpleTableModelBuilder();
+        addHeaders(builder);
+        if (datasets.isEmpty())
+        {
+            return builder.getTableModel();
+        }
+        for (DatasetDescription dataset : datasets)
+        {
+            builder.addRow(createRow(dataset));
+        }
+        return builder.getTableModel();
+    }
+
+    /**
+     * Add the headers to the table -- these depend on the configuration
+     */
+    private void addHeaders(SimpleTableModelBuilder builder)
+    {
+        builder.addHeader("Data Set Code");
+        builder.addHeader("Sample Code");
+        int width = getThumbnailWidth();
+        for (String graphTypeCode : getGraphTypeCodes())
+        {
+            TabularDataGraphConfiguration graphConfig =
+                    configuration.getGraphConfiguration(graphTypeCode);
+            builder.addHeader(graphConfig.getTitle(), width);
+        }
+    }
+
+    private List<ISerializableComparable> createRow(DatasetDescription dataset)
+    {
+        List<ISerializableComparable> row = new ArrayList<ISerializableComparable>();
+
+        // The data set and sample code
+        row.add(SimpleTableModelBuilder.asText(dataset.getDatasetCode()));
+        row.add(SimpleTableModelBuilder.asText(dataset.getSampleCode()));
+
+        for (String graphTypeCode : getGraphTypeCodes())
+        {
+
+            GeneratedImageTableCell imageCell =
+                    new GeneratedImageTableCell(graphServletPath, getImageWidth(),
+                            getImageHeight(), getThumbnailWidth(), getThumbnailHeight());
+            imageCell.addParameter(AbstractTabularDataGraphServlet.DATASET_CODE_PARAM, dataset
+                    .getDatasetCode());
+            imageCell.addParameter(AbstractTabularDataGraphServlet.GRAPH_TYPE_CODE, graphTypeCode);
+
+            row.add(imageCell);
+        }
+
+        return row;
+    }
+
+    private List<String> getGraphTypeCodes()
+    {
+        return configuration.getGraphNames();
+    }
+
+    private int getImageWidth()
+    {
+        return configuration.getImageWidth();
+    }
+
+    private int getImageHeight()
+    {
+        return configuration.getImageHeight();
+    }
+
+    private int getThumbnailWidth()
+    {
+        return configuration.getThumbnailWidth();
+    }
+
+    private int getThumbnailHeight()
+    {
+        return configuration.getThumbnailHeight();
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisGraphReportingPlugin.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/FileBasedImageAnalysisGraphReportingPlugin.java
similarity index 86%
rename from screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisGraphReportingPlugin.java
rename to screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/FileBasedImageAnalysisGraphReportingPlugin.java
index 936d4f4975c..1c2d1dc5f67 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ImageAnalysisGraphReportingPlugin.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/FileBasedImageAnalysisGraphReportingPlugin.java
@@ -23,7 +23,7 @@ import java.util.Properties;
 
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.openbis.dss.generic.server.TabularDataGraphServlet;
+import ch.systemsx.cisd.openbis.dss.generic.server.AbstractTabularDataGraphServlet;
 import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphCollectionConfiguration;
 import ch.systemsx.cisd.openbis.dss.generic.server.graph.TabularDataGraphConfiguration;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractDataMergingReportingPlugin;
@@ -36,10 +36,13 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
 /**
  * Reporting plugin that returns a table in which each column contains a graph. The number and
  * format of the graphs can be configured in a properties file.
+ * <p>
+ * This plugin reads data from a file. The {@link DatabaseImageAnalysisGraphReportingPlugin} reads
+ * from the imaging db.
  * 
  * @author Chandrasekhar Ramakrishnan
  */
-public class ImageAnalysisGraphReportingPlugin extends AbstractDataMergingReportingPlugin
+public class FileBasedImageAnalysisGraphReportingPlugin extends AbstractDataMergingReportingPlugin
 {
     private static final long serialVersionUID = 1L;
 
@@ -52,7 +55,7 @@ public class ImageAnalysisGraphReportingPlugin extends AbstractDataMergingReport
 
     private final static String PROPERTIES_FILE_KEY = "properties-file";
 
-    public ImageAnalysisGraphReportingPlugin(Properties properties, File storeRoot)
+    public FileBasedImageAnalysisGraphReportingPlugin(Properties properties, File storeRoot)
     {
         super(properties, storeRoot, SEMICOLON_SEPARATOR);
         graphServletPath = properties.getProperty(SERVLET_PATH_PROP, "datastore_server_graph/");
@@ -60,7 +63,7 @@ public class ImageAnalysisGraphReportingPlugin extends AbstractDataMergingReport
         if (propertiesFilePath == null)
         {
             throw new EnvironmentFailureException(
-                    "ImageAnalysisGraphReportingPlugin requires a properties file (specified with the "
+                    "DatabaseImageAnalysisGraphReportingPlugin requires a properties file (specified with the "
                             + PROPERTIES_FILE_KEY + "key).");
         }
 
@@ -121,10 +124,11 @@ public class ImageAnalysisGraphReportingPlugin extends AbstractDataMergingReport
             GeneratedImageTableCell imageCell =
                     new GeneratedImageTableCell(graphServletPath, getImageWidth(),
                             getImageHeight(), getThumbnailWidth(), getThumbnailHeight());
-            imageCell.addParameter(TabularDataGraphServlet.DATASET_CODE_PARAM, dataset
+            imageCell.addParameter(AbstractTabularDataGraphServlet.DATASET_CODE_PARAM, dataset
                     .getDatasetCode());
-            imageCell.addParameter(TabularDataGraphServlet.FILE_PATH_PARAM, file.getAbsolutePath());
-            imageCell.addParameter(TabularDataGraphServlet.GRAPH_TYPE_CODE, graphTypeCode);
+            imageCell.addParameter(AbstractTabularDataGraphServlet.FILE_PATH_PARAM, file
+                    .getAbsolutePath());
+            imageCell.addParameter(AbstractTabularDataGraphServlet.GRAPH_TYPE_CODE, graphTypeCode);
 
             row.add(imageCell);
         }
-- 
GitLab