From cb9e1df99590b587a0e3d9c99b57bebe6141a96e Mon Sep 17 00:00:00 2001
From: tpylak <tpylak>
Date: Wed, 14 Oct 2009 08:29:15 +0000
Subject: [PATCH] LMS-1204 Calculated Columns: proper columns sorting for
 integers, longs and strings

SVN: 12957
---
 .../specific/GridCustomColumnDefinition.java  | 13 ++-
 .../calculator/GridExpressionUtils.java       | 18 ++--
 .../web/server/calculator/RowCalculator.java  | 16 ++++
 .../shared/basic/GridCustomColumnValue.java   |  6 +-
 .../generic/shared/basic/GridRowModel.java    | 10 +--
 .../generic/shared/basic/PrimitiveValue.java  | 88 +++++++++++++++++++
 .../server/calculator/RowCalculatorTest.java  |  3 +-
 .../client/web/server/calculator/RowTest.java |  4 +-
 .../web/server/util/TSVRendererTest.java      |  3 +-
 9 files changed, 140 insertions(+), 21 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PrimitiveValue.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
index d3200002d98..28f147584f6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
@@ -20,6 +20,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.PrimitiveValue;
 
 /**
  * Column definition for a grid custom column.
@@ -52,13 +53,19 @@ public class GridCustomColumnDefinition<T> implements IColumnDefinitionUI<T>
 
     public Comparable<?> getComparableValue(GridRowModel<T> rowModel)
     {
-        return getValue(rowModel);
+        return getPrimitiveValue(rowModel).getComparableValue();
     }
 
-    public String getValue(GridRowModel<T> rowModel)
+    private PrimitiveValue getPrimitiveValue(GridRowModel<T> rowModel)
     {
         String columnId = columnMetadata.getCode();
-        return rowModel.findColumnValue(columnId);
+        PrimitiveValue value = rowModel.findColumnValue(columnId);
+        return value;
+    }
+
+    public String getValue(GridRowModel<T> rowModel)
+    {
+        return getPrimitiveValue(rowModel).toString();
     }
 
     public String getHeader()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java
index df4daa2fcc0..ad541a2bb5a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/GridExpressionUtils.java
@@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue
 import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.PrimitiveValue;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 
 /**
@@ -120,12 +121,13 @@ public class GridExpressionUtils
         }
         for (T rowData : allRows)
         {
-            HashMap<String, String> customColumnValues = new HashMap<String, String>();
+            HashMap<String, PrimitiveValue> customColumnValues =
+                    new HashMap<String, PrimitiveValue>();
             for (GridCustomColumn customColumn : customColumns)
             {
                 String columnId = customColumn.getCode();
                 RowCalculator<T> calculator = calculators.get(columnId);
-                String value = evalCustomColumn(rowData, customColumn, calculator);
+                PrimitiveValue value = evalCustomColumn(rowData, customColumn, calculator);
                 customColumnValues.put(columnId, value);
             }
             result.add(new GridRowModel<T>(rowData, customColumnValues));
@@ -133,7 +135,8 @@ public class GridExpressionUtils
         return result;
     }
 
-    private static List<GridCustomColumnInfo> extractColumnInfos(List<GridCustomColumn> customColumns)
+    private static List<GridCustomColumnInfo> extractColumnInfos(
+            List<GridCustomColumn> customColumns)
     {
         List<GridCustomColumnInfo> result = new ArrayList<GridCustomColumnInfo>();
         for (GridCustomColumn column : customColumns)
@@ -146,7 +149,7 @@ public class GridExpressionUtils
         return result;
     }
 
-    private static <T> String evalCustomColumn(T rowData, GridCustomColumn customColumn,
+    private static <T> PrimitiveValue evalCustomColumn(T rowData, GridCustomColumn customColumn,
             RowCalculator<T> calculator)
     {
         // NOTE: we do not allow a calculated column to reference other calculated columns. It's
@@ -155,14 +158,15 @@ public class GridExpressionUtils
         // dependencies create a DAG. Then the columns should be evaluated in a topological
         // order.
         GridRowModel<T> rowDataWithEmptyCustomColumns =
-                new GridRowModel<T>(rowData, new HashMap<String, String>());
+                new GridRowModel<T>(rowData, new HashMap<String, PrimitiveValue>());
         try
         {
             calculator.setRowData(rowDataWithEmptyCustomColumns);
-            return calculator.evalAsString();
+
+            return calculator.getTypedResult();
         } catch (Exception ex)
         {
-            return createCustomColumnErrorMessage(customColumn, ex);
+            return new PrimitiveValue(createCustomColumnErrorMessage(customColumn, ex));
         }
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java
index f218b30d64f..685def5e1a6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculator.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.common.evaluator.EvaluatorException;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.PrimitiveValue;
 
 /**
  * @author Franz-Josef Elmer
@@ -61,6 +62,21 @@ class RowCalculator<T>
         row.setRowData(rowData);
     }
 
+    public PrimitiveValue getTypedResult()
+    {
+        Object value = evaluator.eval();
+        if (value instanceof Long)
+        {
+            return new PrimitiveValue((Long) value);
+        } else if (value instanceof Double)
+        {
+            return new PrimitiveValue((Double) value);
+        } else
+        {
+            return new PrimitiveValue(value.toString());
+        }
+    }
+
     public boolean evalToBoolean() throws EvaluatorException
     {
         return evaluator.evalToBoolean();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridCustomColumnValue.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridCustomColumnValue.java
index 80b76150653..9b9364afba1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridCustomColumnValue.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridCustomColumnValue.java
@@ -27,7 +27,7 @@ public class GridCustomColumnValue implements IsSerializable
 {
     private String columnId;
 
-    private String value;
+    private PrimitiveValue value;
 
     public String getColumnId()
     {
@@ -39,12 +39,12 @@ public class GridCustomColumnValue implements IsSerializable
         this.columnId = columnId;
     }
 
-    public String getValue()
+    public PrimitiveValue getValue()
     {
         return value;
     }
 
-    public void setValue(String value)
+    public void setValue(PrimitiveValue value)
     {
         this.value = value;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridRowModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridRowModel.java
index b33e42176bc..2c8f9637a64 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridRowModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/GridRowModel.java
@@ -23,7 +23,6 @@ import java.util.Map.Entry;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
-
 /**
  * Stores the original object which will be a basis to calculate a grid row together with calculated
  * all custom columns values.
@@ -38,16 +37,17 @@ public class GridRowModel<T> implements IsSerializable
     // displaying serialization warnings in GWT 1.5. It was fixed in GWT 1.6
     private List<GridCustomColumnValue> calculatedColumnValues;
 
-    public GridRowModel(T originalObject, HashMap<String, String> calculatedColumnMap)
+    public GridRowModel(T originalObject,
+            HashMap<String, PrimitiveValue> calculatedColumnMap)
     {
         this.originalObject = originalObject;
         this.calculatedColumnValues = asList(calculatedColumnMap);
     }
 
-    private List<GridCustomColumnValue> asList(HashMap<String, String> map)
+    private List<GridCustomColumnValue> asList(HashMap<String, PrimitiveValue> map)
     {
         List<GridCustomColumnValue> result = new ArrayList<GridCustomColumnValue>();
-        for (Entry<String, String> entry : map.entrySet())
+        for (Entry<String, PrimitiveValue> entry : map.entrySet())
         {
             GridCustomColumnValue column = new GridCustomColumnValue();
             column.setColumnId(entry.getKey());
@@ -74,7 +74,7 @@ public class GridRowModel<T> implements IsSerializable
         this.calculatedColumnValues = calculatedColumnValues;
     }
 
-    public String findColumnValue(String columnId)
+    public PrimitiveValue findColumnValue(String columnId)
     {
         for (GridCustomColumnValue value : calculatedColumnValues)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PrimitiveValue.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PrimitiveValue.java
new file mode 100644
index 00000000000..8f5964e13b6
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PrimitiveValue.java
@@ -0,0 +1,88 @@
+/*
+ * 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.generic.shared.basic;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Stores one primitive value: Double, Long or String.
+ * <p>
+ * Such a type is needed becaus GWT does not support serialization fields of Object or Serializable
+ * type.
+ * </p>
+ * 
+ * @author Tomasz Pylak
+ */
+public class PrimitiveValue implements IsSerializable
+{
+    private Double doubleValueOrNull;
+
+    private Long longValueOrNull;
+
+    private String stringValueOrNull;
+
+    public PrimitiveValue(Double value)
+    {
+        doubleValueOrNull = value;
+    }
+
+    public PrimitiveValue(Long value)
+    {
+        longValueOrNull = value;
+    }
+
+    public PrimitiveValue(String value)
+    {
+        stringValueOrNull = value;
+    }
+
+    public Comparable<?> getComparableValue()
+    {
+        if (doubleValueOrNull != null)
+        {
+            return doubleValueOrNull;
+        } else if (longValueOrNull != null)
+        {
+            return longValueOrNull;
+        } else
+        {
+            return stringValueOrNull;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        if (doubleValueOrNull != null)
+        {
+            return doubleValueOrNull.toString();
+        } else if (longValueOrNull != null)
+        {
+            return longValueOrNull.toString();
+        } else
+        {
+            return stringValueOrNull;
+        }
+    }
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private PrimitiveValue()
+    {
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java
index b939c79e444..62c737c7805 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowCalculatorTest.java
@@ -30,6 +30,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.PrimitiveValue;
 
 /**
  * @author Franz-Josef Elmer
@@ -235,6 +236,6 @@ public class RowCalculatorTest extends AssertJUnit
     {
         Data data = new Data();
         data.setValue(value);
-        return new GridRowModel<Data>(data, new HashMap<String, String>());
+        return new GridRowModel<Data>(data, new HashMap<String, PrimitiveValue>());
     }
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java
index 6c402d9f35e..d73eb60951f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/calculator/RowTest.java
@@ -30,6 +30,7 @@ import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.PrimitiveValue;
 
 /**
  * @author Franz-Josef Elmer
@@ -230,7 +231,8 @@ public class RowTest extends AssertJUnit
     private GridRowModel<Data> createData(double value)
     {
         Data originalObject = new Data(value);
-        return new GridRowModel<Data>(originalObject, new HashMap<String, String>());
+        return new GridRowModel<Data>(originalObject,
+                new HashMap<String, PrimitiveValue>());
     }
 
     @Test
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java
index 16ddac28d56..d819c809053 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/TSVRendererTest.java
@@ -28,6 +28,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnIn
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.PrimitiveValue;
 
 /**
  * Tests of {@link TSVRenderer}
@@ -54,7 +55,7 @@ public class TSVRendererTest
         List<GridRowModel<T>> list = new ArrayList<GridRowModel<T>>();
         for (T entity : entities)
         {
-            list.add(new GridRowModel<T>(entity, new HashMap<String, String>()));
+            list.add(new GridRowModel<T>(entity, new HashMap<String, PrimitiveValue>()));
         }
         return new GridRowModels<T>(list, new ArrayList<GridCustomColumnInfo>());
     }
-- 
GitLab