Bug 491109 Some collections queries fail for some collections from PHD

Improve ArrayDeque and TreeMap/TreeSet

Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=491109
Change-Id: I3b78689c60cc257d657579519df19ac42aab400d
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/HashSetCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/HashSetCollectionExtractor.java
index 98431e0..a39515a 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/HashSetCollectionExtractor.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/HashSetCollectionExtractor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2015 SAP AG, IBM Corporation and others
+ * Copyright (c) 2008, 2023 SAP AG, IBM Corporation and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
  * which accompanies this distribution, and is available at
@@ -61,7 +61,10 @@
     {
         if (size_attribute != null)
         {
-            return ExtractionUtils.toInteger(coll.resolveValue(size_attribute));
+            Integer ret = ExtractionUtils.toInteger(coll.resolveValue(size_attribute));
+            if (ret != null)
+                return ret;
+            return getNumberOfNotNullElements(coll);
         }
         else
         {
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/IBM6ArrayListCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/IBM6ArrayListCollectionExtractor.java
index 2f5ca10..6d163cc 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/IBM6ArrayListCollectionExtractor.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/IBM6ArrayListCollectionExtractor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others
+ * Copyright (c) 2008, 2023 SAP AG, IBM Corporation and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
  * which accompanies this distribution, and is available at
@@ -18,6 +18,7 @@
 import org.eclipse.mat.collect.ArrayInt;
 import org.eclipse.mat.snapshot.ISnapshot;
 import org.eclipse.mat.snapshot.model.IObject;
+import org.eclipse.mat.snapshot.model.IObjectArray;
 
 public class IBM6ArrayListCollectionExtractor extends FieldArrayCollectionExtractor
 {
@@ -62,7 +63,16 @@
         Integer lastIndex = (Integer) coll.resolveValue(this.lastIndex);
 
         if (lastIndex == null)
+        {
+            if (firstIndex == null)
+            {
+                IObjectArray arr = extractEntries(coll);
+                if (arr == null)
+                    return null;
+                return ExtractionUtils.getNumberOfNotNullArrayElements(arr);
+            }
             return null;
+        }
         else if (firstIndex == null || lastIndex <= 0)
             return lastIndex;
         else
@@ -87,15 +97,23 @@
         Integer size = getSize(coll);
         if (size == null)
         {
-            return new int[0];
+            // PHD?
+            return ExtractionUtils.referenceArrayToIds(snapshot, referenceArray);
         }
         ArrayInt arr = new ArrayInt(size);
         if (size > 0)
         {
+            Object firstIdx = coll.resolveValue(this.firstIndex);
+            Object lastIdx = coll.resolveValue(this.lastIndex);
+            if (!((firstIdx instanceof Integer) && (lastIdx instanceof Integer)))
+            {
+                // PHD?
+                return ExtractionUtils.referenceArrayToIds(snapshot, referenceArray);
+            }
             // For ArrayBlockingQueue, first == last & size > 0 means do everything
             // For ArrayList, first == last means size == 0, but wouldn't get here
-            int firstIndex = (Integer) coll.resolveValue(this.firstIndex);
-            int lastIndex = (Integer) coll.resolveValue(this.lastIndex);
+            int firstIndex = (Integer) firstIdx;
+            int lastIndex = (Integer) lastIdx;
             int end = getCapacity(coll);
             for (int i = firstIndex; i < (firstIndex < lastIndex  ? lastIndex : end); i++)
             {
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/TreeMapCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/TreeMapCollectionExtractor.java
index 7a8d01d..c629842 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/TreeMapCollectionExtractor.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/TreeMapCollectionExtractor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2015 SAP AG, IBM Corporation and others
+ * Copyright (c) 2008, 2023 SAP AG, IBM Corporation and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
  * which accompanies this distribution, and is available at
@@ -60,8 +60,22 @@
             rootf = sizeField.substring(0, dot + 1) + rootf;
         }
         IObject root = (IObject) treeMap.resolveValue(rootf);
+        boolean noFieldNames = root == null;
         if (root == null)
-            return new int[0];
+        {
+            if (dot > 0)
+            {
+                root = ExtractionUtils.followOnlyOutgoingReferencesExceptLast(rootf, treeMap);
+                if (root != null)
+                    root = ExtractionUtils.followOnlyNonArrayOutgoingReference(root);
+            }
+            else
+            {
+                root = ExtractionUtils.followOnlyNonArrayOutgoingReference(treeMap);
+            }
+            if (root == null || !root.getClazz().getName().endsWith("$Entry")) //$NON-NLS-1$
+                return new int[0];
+        }
 
         Stack<IObject> stack = new Stack<IObject>();
         stack.push(root);
@@ -93,6 +107,18 @@
                 {
                     stack.push(right);
                 }
+                else if (noFieldNames)
+                {
+                    // All nodes of same type as root
+                    for (int o : current.getSnapshot().getOutboundReferentIds(current.getObjectId()))
+                    {
+                        if (current.getSnapshot().getClassOf(o).equals(root.getClazz()))
+                        {
+                            if (!visited.contains(o))
+                                stack.push(current.getSnapshot().getObject(o));
+                        }
+                    }
+                }
             }
         }
 
@@ -106,7 +132,13 @@
 
     public Integer getSize(IObject coll) throws SnapshotException
     {
-        return ExtractionUtils.toInteger(coll.resolveValue(sizeField));
+        Integer ret = ExtractionUtils.toInteger(coll.resolveValue(sizeField));
+        if (ret != null)
+            return ret;
+        int e[] = this.extractEntryIds(coll);
+        if (e != null)
+            return e.length;
+        return null;
     }
 
     public Integer getNumberOfNotNullElements(IObject coll) throws SnapshotException
diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest4.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest4.java
index 38d3dbf..a1144d3 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest4.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest4.java
@@ -88,7 +88,7 @@
     public void testCollections6() throws SnapshotException

     {

         ISnapshot snapshot = TestSnapshots.getSnapshot(snapfile, false);

-        assumeThat(snapshot.getSnapshotInfo().getProperty("$heapFormat"), not(equalTo((Serializable)"DTFJ-PHD")));

+        //assumeThat(snapshot.getSnapshotInfo().getProperty("$heapFormat"), not(equalTo((Serializable)"DTFJ-PHD")));

         testCollections6(snapshot, null);

     }

 }