From 720346552f6fc555f1c93d965e0063d0a344230a Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Tue, 4 Dec 2012 14:37:32 +0000
Subject: [PATCH] bug revealed by ImageBase64EncodingTest fixed. Faster test
 written for this bug.

SVN: 27853
---
 .../bo/datasetlister/DatasetLister.java       |  60 ++++--
 .../datasetlister/DatasetListerFastTest.java  | 181 ++++++++++++++++++
 2 files changed, 223 insertions(+), 18 deletions(-)
 create mode 100644 openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetListerFastTest.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
index 639d46d4a6b..b21fdab5eef 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetLister.java
@@ -998,41 +998,65 @@ public class DatasetLister extends AbstractLister implements IDatasetLister
     @Override
     public IDatasetLocationNode listLocationsByDatasetCode(String datasetCode)
     {
-        DataIterator<DatasetLocationNodeRecord> queryResult =
-                query.listLocationsByDatasetCode(datasetCode);
+        TableMap<Long, DatasetLocationNodeRecord> records = loadRawLocationData(datasetCode);
 
         Map<Long, DatasetLocationNode> nodeMap = new HashMap<Long, DatasetLocationNode>();
         DatasetLocationNode rootNode = null;
-
-        while (queryResult.hasNext())
+        for (DatasetLocationNodeRecord record : records)
         {
-            DatasetLocationNodeRecord record = queryResult.next();
-
             DatasetLocation location = new DatasetLocation();
             location.setDatasetCode(record.code);
             location.setDataSetLocation(record.location);
             location.setDataStoreCode(record.data_store_code);
             location.setDataStoreUrl(record.data_store_url);
-
             DatasetLocationNode node = new DatasetLocationNode(location);
-
-            if (record.ctnr_id != null)
+            if (datasetCode.equals(record.code))
             {
-                DatasetLocationNode parentNode = nodeMap.get(record.ctnr_id);
-                if (parentNode != null)
-                {
-                    parentNode.addContained(node);
-                }
+                rootNode = node;
             }
-
             nodeMap.put(record.id, node);
+        }
+
+        linkContainedData(records, nodeMap);
+
+        return rootNode;
+    }
 
-            if (rootNode == null)
+    private void linkContainedData(TableMap<Long, DatasetLocationNodeRecord> records,
+            Map<Long, DatasetLocationNode> nodeMap)
+    {
+        Set<Entry<Long, DatasetLocationNode>> entrySet = nodeMap.entrySet();
+        for (Entry<Long, DatasetLocationNode> entry : entrySet)
+        {
+            Long id = entry.getKey();
+            DatasetLocationNode node = entry.getValue();
+            Long containerId = records.tryGet(id).ctnr_id;
+            if (containerId != null)
             {
-                rootNode = node;
+                DatasetLocationNode containerNode = nodeMap.get(containerId);
+                if (containerNode != null)
+                {
+                    containerNode.addContained(node);
+                }
             }
         }
+    }
 
-        return rootNode;
+    private TableMap<Long, DatasetLocationNodeRecord> loadRawLocationData(String datasetCode)
+    {
+        DataIterator<DatasetLocationNodeRecord> queryResult =
+                query.listLocationsByDatasetCode(datasetCode);
+        TableMap<Long, DatasetLocationNodeRecord> records =
+                new TableMap<Long, DatasetLocationNodeRecord>(queryResult,
+                        new IKeyExtractor<Long, DatasetLocationNodeRecord>()
+                            {
+                                @Override
+                                public Long getKey(DatasetLocationNodeRecord r)
+                                {
+                                    return r.id;
+                                }
+                            });
+        queryResult.close();
+        return records;
     }
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetListerFastTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetListerFastTest.java
new file mode 100644
index 00000000000..46e9b72e138
--- /dev/null
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/DatasetListerFastTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2012 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.server.business.bo.datasetlister;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lemnik.eodsql.DataIterator;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.generic.server.business.bo.common.IEntityPropertiesEnricher;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IDatasetLocationNode;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+public class DatasetListerFastTest extends AssertJUnit
+{
+    private static final String DSS_URL = "dss-url";
+
+    private static final String DSS_CODE = "DSS";
+
+    private Mockery context;
+
+    private IDatasetListingQuery query;
+
+    private DatasetLister datasetLister;
+
+    @BeforeMethod
+    public void setUp()
+    {
+        context = new Mockery();
+        query = context.mock(IDatasetListingQuery.class);
+        IEntityPropertiesEnricher propertiesEnricher =
+                context.mock(IEntityPropertiesEnricher.class);
+        datasetLister =
+                new DatasetLister(42L, new DatabaseInstance(), query, propertiesEnricher, null,
+                        null, null);
+    }
+
+    @AfterMethod
+    public void afterMethod(Method m)
+    {
+        try
+        {
+            context.assertIsSatisfied();
+        } catch (Throwable t)
+        {
+            // assert expectations were met, including the name of the failed method
+            throw new Error(m.getName() + "() : ", t);
+        }
+    }
+
+    @Test
+    public void testListLocationsByDatasetCode()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(query).listLocationsByDatasetCode("ds-1");
+                    will(returnValue(new WrappingDataIterator<DatasetLocationNodeRecord>(Arrays
+                            .<DatasetLocationNodeRecord> asList(
+                                    location(2L, "ds-c1", "a/b/c/1", 1L),
+                                    location(3L, "ds-c2", "a/b/c/2", 1L),
+                                    location(1L, "ds-1", null, null)))));
+                }
+            });
+
+        IDatasetLocationNode location = datasetLister.listLocationsByDatasetCode("ds-1");
+
+        assertEquals("ds-1", location.getLocation().getDataSetCode());
+        assertEquals(null, location.getLocation().getDataSetLocation());
+        assertEquals(DSS_CODE, location.getLocation().getDataStoreCode());
+        assertEquals(DSS_URL, location.getLocation().getDataStoreUrl());
+        assertEquals(true, location.isContainer());
+        List<IDatasetLocationNode> components =
+                new ArrayList<IDatasetLocationNode>(location.getComponents());
+        Collections.sort(components, new Comparator<IDatasetLocationNode>()
+            {
+                @Override
+                public int compare(IDatasetLocationNode n1, IDatasetLocationNode n2)
+                {
+                    return n1.getLocation().getDataSetCode()
+                            .compareTo(n2.getLocation().getDataSetCode());
+                }
+            });
+        assertEquals("ds-c1", components.get(0).getLocation().getDataSetCode());
+        assertEquals("a/b/c/1", components.get(0).getLocation().getDataSetLocation());
+        assertEquals("ds-c2", components.get(1).getLocation().getDataSetCode());
+        assertEquals("a/b/c/2", components.get(1).getLocation().getDataSetLocation());
+    }
+
+    private DatasetLocationNodeRecord location(long id, String code, String location,
+            Long containerID)
+    {
+        DatasetLocationNodeRecord record = new DatasetLocationNodeRecord();
+        record.id = id;
+        record.code = code;
+        record.data_store_code = DSS_CODE;
+        record.data_store_url = DSS_URL;
+        record.location = location;
+        record.ctnr_id = containerID;
+        return record;
+    }
+
+    private static final class WrappingDataIterator<E> implements DataIterator<E>
+    {
+        private final Collection<E> collection;
+
+        private final Iterator<E> iterator;
+
+        public WrappingDataIterator(Collection<E> collection)
+        {
+            this.collection = collection;
+            iterator = collection.iterator();
+        }
+
+        @Override
+        public boolean hasNext()
+        {
+            return iterator.hasNext();
+        }
+
+        @Override
+        public E next()
+        {
+            return iterator.next();
+        }
+
+        @Override
+        public void remove()
+        {
+            iterator.remove();
+        }
+
+        @Override
+        public Iterator<E> iterator()
+        {
+            return collection.iterator();
+        }
+
+        @Override
+        public void close()
+        {
+        }
+
+        @Override
+        public boolean isClosed()
+        {
+            return false;
+        }
+    }
+
+}
-- 
GitLab