/**
  * Get the only object field from the object Used for finding the HashMap from the HashSet
  *
  * @param source
  * @return null if non or duplicates found
  * @throws SnapshotException
  */
 private IInstance resolveNextField(IObject source) throws SnapshotException {
   final ISnapshot snapshot = source.getSnapshot();
   IInstance ret = null;
   for (int i : snapshot.getOutboundReferentIds(source.getObjectId())) {
     if (!snapshot.isArray(i) && !snapshot.isClass(i)) {
       IObject o = snapshot.getObject(i);
       if (o instanceof IInstance) {
         if (ret != null) {
           ret = null;
           break;
         }
         ret = (IInstance) o;
       }
     }
   }
   return ret;
 }
  @Override
  public int[] extractEntryIds(IObject list) throws SnapshotException {
    IProgressListener listener = new VoidProgressListener();
    // If there isn't a size, then use an upper limit in case there is a loop
    int size = super.hasSize() ? getSize(list) : 10000000;

    String taskMsg =
        MessageUtil.format(
            Messages.ExtractListValuesQuery_CollectingElements, size, list.getTechnicalName());
    listener.beginTask(taskMsg, size);

    ArrayInt result = new ArrayInt();
    int loopingLimit = size;

    IObject header = (IObject) list.resolveValue("header"); // LinkedList$Header //$NON-NLS-1$
    if (header == null)
      header = (IObject) list.resolveValue("voidLink"); // LinkedList$Link IBM VM //$NON-NLS-1$
    if (header == null)
      header = (IObject) list.resolveValue("first"); // LinkedList$Node Java 7 //$NON-NLS-1$
    if (header == null) {}

    if (header == null) {
      // Look for the only object field
      header = resolveNextFields(list);
    }
    if (header == null) return null;

    IObject previous = header;
    IObject current = header;

    if (current.getClazz().getName().equals("java.util.LinkedList$Entry")
        || //$NON-NLS-1$
        current.getClazz().getName().equals("java.util.LinkedList$Link")
        || //$NON-NLS-1$
        current
            .getClazz()
            .getName()
            .equals("java.util.concurrent.LinkedBlockingQueue$Node")) // $NON-NLS-1$
    {
      // Skip over header link for pre Java 7 implementations
      current = (IObject) header.resolveValue("next"); // $NON-NLS-1$;
      if (current == null) {
        // Try without using field names
        final ISnapshot snapshot = header.getSnapshot();
        for (int i : snapshot.getOutboundReferentIds(header.getObjectId())) {
          IObject o = snapshot.getObject(i);
          // Exclude the class
          if (i != header.getClazz().getObjectId()) {
            if (o.getClazz().equals(header.getClazz())) {
              // same type as header, so possible next field
              // don't care whether we get current or previous -
              // just circle the wrong way
              current = o;
              break;
            }
          }
        }
      }
    } else {
      header = null;
    }

    while (current != null && current != header && loopingLimit-- > 0) {
      // Find the element
      IObject ref = (IObject) current.resolveValue("element"); // $NON-NLS-1$
      if (ref == null) ref = (IObject) current.resolveValue("data"); // IBM VM //$NON-NLS-1$
      if (ref == null) ref = (IObject) current.resolveValue("item"); // Java 7 //$NON-NLS-1$
      if (current.equals(ref)) {
        // java.util.concurrent.LinkedTransferQueue has a spurious link
        ref = null;
      }

      // Find the next link
      IObject next = (IObject) current.resolveValue("next"); // $NON-NLS-1$

      if (next == null) {
        // Try without using field names
        final ISnapshot snapshot = current.getSnapshot();
        for (int i : snapshot.getOutboundReferentIds(current.getObjectId())) {
          IObject o = snapshot.getObject(i);
          // Exclude the previous field and the class
          if (i != previous.getObjectId() && i != current.getClazz().getObjectId()) {
            if (o.getClazz().equals(current.getClazz())) {
              // same type as current, so possible next field
              if (next != null) {
                // Uncertain, so give up
                next = null;
                break;
              }
              next = o;
            } else {
              // possible element
              if (ref == null) ref = o;
            }
          }
        }
      }

      if (ref != null) result.add(ref.getObjectId());
      previous = current;
      current = next;
      listener.worked(1);
      // If the user cancels then just return what we have got so far
      if (listener.isCanceled()) break;
    }

    listener.done();

    return result.toArray();
  }