/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * 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
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tom Schindl <tom.schindl@bestsolution.at> - bug 153993, bug 167323, bug 175192
 *     Lasse Knudsen, bug 205700
 *     Micah Hainline, bug 210448
 *     Michael Schneider, bug 210747
 *     Bruce Sutton, bug 221768
 *     Matthew Hall, bug 221988
 *     Julien Desgats, bug 203950
 *     Alexander Fedorov <alexander.fedorov@arsysop.ru> - Bug 548314
 *******************************************************************************/

package org.eclipse.jface.viewers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.internal.InternalPolicy;
import org.eclipse.jface.util.Policy;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TreeEvent;
import org.eclipse.swt.events.TreeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Widget;

/**
 * Abstract base implementation for tree-structure-oriented viewers (trees and
 * table trees).
 * <p>
 * Nodes in the tree can be in either an expanded or a collapsed state,
 * depending on whether the children on a node are visible. This class
 * introduces public methods for controlling the expanding and collapsing of
 * nodes.
 * </p>
 * <p>
 * As of 3.2, AbstractTreeViewer supports multiple equal elements (each with a
 * different parent chain) in the tree. This support requires that clients
 * enable the element map by calling <code>setUseHashlookup(true)</code>.
 * </p>
 * <p>
 * Content providers for abstract tree viewers must implement one of the
 * interfaces <code>ITreeContentProvider</code> or (as of 3.2, to support
 * multiple equal elements) <code>ITreePathContentProvider</code>.
 * </p>
 * <p>
 * <strong> This class is not intended to be subclassed outside of the JFace
 * viewers framework.</strong>
 * </p>
 *
 * @see TreeViewer
 */
public abstract class AbstractTreeViewer extends ColumnViewer {

	/**
	 * Constant indicating that all levels of the tree should be expanded or
	 * collapsed.
	 *
	 * @see #expandToLevel(int)
	 * @see #collapseToLevel(Object, int)
	 */
	public static final int ALL_LEVELS = -1;

	/**
	 * List of registered tree listeners (element type:
	 * <code>TreeListener</code>).
	 */
	private ListenerList<ITreeViewerListener> treeListeners = new ListenerList<>();

	/**
	 * The level to which the tree is automatically expanded each time the
	 * viewer's input is changed (that is, by <code>setInput</code>). A value
	 * of 0 means that auto-expand is off.
	 *
	 * @see #setAutoExpandLevel
	 */
	private int expandToLevel = 0;

	/**
	 * Indicates if filters should be checked to determine expandability of
	 * a tree node.
	 */
	private boolean isExpandableCheckFilters = false;

	/**
	 * Safe runnable used to update an item.
	 */
	class UpdateItemSafeRunnable extends SafeRunnable {
		private Object element;

		private Item item;

		UpdateItemSafeRunnable(Item item, Object element) {
			this.item = item;
			this.element = element;
		}

		@Override
		public void run() {
			doUpdateItem(item, element);
		}

	}

	/**
	 * Creates an abstract tree viewer. The viewer has no input, no content
	 * provider, a default label provider, no sorter, no filters, and has
	 * auto-expand turned off.
	 */
	protected AbstractTreeViewer() {
		// do nothing
	}

	/**
	 * Adds the given child elements to this viewer as children of the given
	 * parent element. If this viewer does not have a sorter, the elements are
	 * added at the end of the parent's list of children in the order given;
	 * otherwise, the elements are inserted at the appropriate positions.
	 * <p>
	 * This method should be called (by the content provider) when elements have
	 * been added to the model, in order to cause the viewer to accurately
	 * reflect the model. This method only affects the viewer, not the model.
	 * </p>
	 *
	 * @param parentElementOrTreePath
	 *            the parent element
	 * @param childElements
	 *            the child elements to add
	 */
	public void add(Object parentElementOrTreePath, Object... childElements) {
		Assert.isNotNull(parentElementOrTreePath);
		assertElementsNotNull(childElements);
		if (checkBusy())
			return;
		Widget[] widgets = internalFindItems(parentElementOrTreePath);
		// If parent hasn't been realized yet, just ignore the add.
		if (widgets.length == 0) {
			return;
		}

		for (Widget widget : widgets) {
			internalAdd(widget, parentElementOrTreePath, childElements);
		}
	}

	/**
	 * Find the items for the given element of tree path
	 *
	 * @param parentElementOrTreePath
	 *            the element or tree path
	 * @return the items for that element
	 *
	 * @since 3.3
	 */
	final protected Widget[] internalFindItems(Object parentElementOrTreePath) {
		Widget[] widgets;
		if (parentElementOrTreePath instanceof TreePath) {
			TreePath path = (TreePath) parentElementOrTreePath;
			Widget w = internalFindItem(path);
			if (w == null) {
				widgets = new Widget[] {};
			} else {
				widgets = new Widget[] { w };
			}
		} else {
			widgets = findItems(parentElementOrTreePath);
		}
		return widgets;
	}

	/**
	 * Return the item at the given path or <code>null</code>
	 *
	 * @param path
	 *            the path
	 * @return {@link Widget} the item at that path
	 */
	private Widget internalFindItem(TreePath path) {
		Widget[] widgets = findItems(path.getLastSegment());
		for (Widget widget : widgets) {
			if (widget instanceof Item) {
				Item item = (Item) widget;
				TreePath p = getTreePathFromItem(item);
				if (p.equals(path)) {
					return widget;
				}
			}
		}
		return null;
	}

	/**
	 * Adds the given child elements to this viewer as children of the given
	 * parent element.
	 * <p>
	 * EXPERIMENTAL. Not to be used except by JDT. This method was added to
	 * support JDT's explorations into grouping by working sets. This method
	 * cannot be removed without breaking binary backwards compatibility, but
	 * should not be called by clients.
	 * </p>
	 *
	 * @param widget
	 *            the widget for the parent element
	 * @param parentElementOrTreePath
	 *            the parent element
	 * @param childElements
	 *            the child elements to add
	 * @since 3.1
	 */
	protected void internalAdd(Widget widget, Object parentElementOrTreePath,
			Object[] childElements) {
		Object parent;
		TreePath path;
		if (parentElementOrTreePath instanceof TreePath) {
			path = (TreePath) parentElementOrTreePath;
			parent = path.getLastSegment();
		} else {
			parent = parentElementOrTreePath;
			path = null;
		}

		// optimization!
		// if the widget is not expanded we just invalidate the subtree
		if (widget instanceof Item) {
			Item ti = (Item) widget;
			if (!getExpanded(ti)) {
				boolean needDummy = isExpandable(ti, path, parent);
				boolean haveDummy = false;
				// remove all children
				Item[] items = getItems(ti);
				for (Item item : items) {
					if (item.getData() != null) {
						disassociate(item);
						item.dispose();
					} else {
						if (needDummy && !haveDummy) {
							haveDummy = true;
						} else {
							item.dispose();
						}
					}
				}
				// append a dummy if necessary
				if (needDummy && !haveDummy) {
					newItem(ti, SWT.NULL, -1);
				}
				return;
			}
		}

		if (childElements.length > 0) {
			// TODO: Add filtering back?
			Object[] filtered = filter(parentElementOrTreePath, childElements);
			ViewerComparator comparator = getComparator();
			if (comparator != null) {
				if (comparator instanceof TreePathViewerSorter) {
					TreePathViewerSorter tpvs = (TreePathViewerSorter) comparator;
					if (path == null) {
						path = internalGetSorterParentPath(widget, comparator);
					}
					tpvs.sort(this, path, filtered);
				} else {
					comparator.sort(this, filtered);
				}
			}
			createAddedElements(widget, filtered);
			if (InternalPolicy.DEBUG_LOG_EQUAL_VIEWER_ELEMENTS) {
				Item[] children = getChildren(widget);
				Object[] elements = new Object[children.length];
				for (int i = 0; i < children.length; i++) {
					elements[i] = children[i].getData();
				}
				assertElementsNotNull(parent, elements);
			}
		}
	}

	/**
	 * Filter the children elements.
	 *
	 * @param parentElementOrTreePath
	 *            the parent element or path
	 * @param elements
	 *            the child elements
	 * @return the filter list of children
	 */
	private Object[] filter(Object parentElementOrTreePath, Object[] elements) {
		ViewerFilter[] filters = getFilters();
		if (filters != null) {
			List<Object> filtered = new ArrayList<>(elements.length);
			for (Object element : elements) {
				boolean add = true;
				for (ViewerFilter filter : filters) {
					add = filter.select(this, parentElementOrTreePath,
							element);
					if (!add) {
						break;
					}
				}
				if (add) {
					filtered.add(element);
				}
			}
			return filtered.toArray();
		}
		return elements;
	}

	/**
	 * Create the new elements in the parent widget. If the child already exists
	 * do nothing.
	 *
	 * @param widget
	 * @param elements
	 *            Sorted list of elements to add.
	 */
	private void createAddedElements(Widget widget, Object[] elements) {

		if (elements.length == 1) {
			if (equals(elements[0], widget.getData())) {
				return;
			}
		}

		ViewerComparator comparator = getComparator();
		TreePath parentPath = internalGetSorterParentPath(widget, comparator);
		Item[] items = getChildren(widget);

		// Optimize for the empty case
		if (items.length == 0) {
			for (Object element : elements) {
				createTreeItem(widget, element, -1);
			}
			return;
		}

		// Optimize for no comparator
		if (comparator == null) {
			for (Object element : elements) {
				if (itemExists(items, element)) {
					internalRefresh(element);
				} else {
					createTreeItem(widget, element, -1);
				}
			}
			return;
		}
		// As the items are sorted already we optimize for a
		// start position. This is the insertion position relative to the
		// original item array.
		int indexInItems = 0;

		// Count of elements we have added. See bug 205700 for why this is needed.
		int newItems = 0;

		elementloop: for (Object element : elements) {
			// update the index relative to the original item array
			indexInItems = insertionPosition(items, comparator,
					indexInItems, element, parentPath);
			if (indexInItems == items.length) {
				createTreeItem(widget, element, -1);
				newItems++;
			} else {
				// Search for an item for the element. The comparator might
				// regard elements as equal when they are not.

				// Use a separate index variable to search within the existing
				// elements that compare equally, see
				// TreeViewerTestBug205700.testAddEquallySortedElements.
				int insertionIndexInItems = indexInItems;
				while( insertionIndexInItems < items.length
						&& internalCompare(comparator, parentPath, element,
								items[insertionIndexInItems].getData()) == 0) {
					// As we cannot assume the sorter is consistent with
					// equals() - therefore we can
					// just check against the item prior to this index (if
					// any)
					if (items[insertionIndexInItems].getData().equals(element)) {
						// Found the item for the element.
						// Refresh the element in case it has new children.
						internalRefresh(element);
						// Do not create a new item - continue with the next element.
						continue elementloop;
					}
					insertionIndexInItems++;
				}
				// Did we get to the end?
				if (insertionIndexInItems == items.length) {
					createTreeItem(widget, element, -1);
					newItems++;
				} else {
					// InsertionIndexInItems is the index in the original array. We
					// need to correct by the number of new items we have
					// created. See bug 205700.
					createTreeItem(widget, element, insertionIndexInItems + newItems);
					newItems++;
				}
			}
		}
	}

	/**
	 * See if element is the data of one of the elements in items.
	 *
	 * @param items
	 * @param element
	 * @return <code>true</code> if the element matches.
	 */
	private boolean itemExists(Item[] items, Object element) {
		if (usingElementMap()) {
			Widget[] existingItems = findItems(element);
			// optimization for two common cases
			if (existingItems.length == 0) {
				return false;
			} else if (existingItems.length == 1) {
				if (items.length > 0 && existingItems[0] instanceof Item) {
					Item existingItem = (Item) existingItems[0];
					return getParentItem(existingItem) == getParentItem(items[0]);
				}
			}
		}
		for (Item item : items) {
			if (item.getData().equals(element)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns the index where the item should be inserted. It uses sorter to
	 * determine the correct position, if sorter is not assigned, returns the
	 * index of the element after the last.
	 *
	 * @param items
	 *            the items to search
	 * @param comparator
	 *            The comparator to use.
	 * @param lastInsertion
	 *            the start index to start search for position from this allows
	 *            optimizing search for multiple elements that are sorted
	 *            themselves.
	 * @param element
	 *            element to find position for.
	 * @param parentPath
	 *            the tree path for the element's parent or <code>null</code>
	 *            if the element is a root element or the sorter is not a
	 *            {@link TreePathViewerSorter}
	 * @return the index to use when inserting the element.
	 *
	 */

	private int insertionPosition(Item[] items, ViewerComparator comparator,
			int lastInsertion, Object element, TreePath parentPath) {

		int size = items.length;
		if (comparator == null) {
			return size;
		}
		int min = lastInsertion, max = size - 1;

		while (min <= max) {
			int mid = (min + max) / 2;
			Object data = items[mid].getData();
			int compare = internalCompare(comparator, parentPath, data, element);
			if (compare == 0) {
				return mid;// Return if we already match
			}
			if (compare < 0) {
				min = mid + 1;
			} else {
				max = mid - 1;
			}
		}
		return min;

	}

	/**
	 * Returns the index where the item should be inserted. It uses sorter to
	 * determine the correct position, if sorter is not assigned, returns the
	 * index of the element after the last.
	 *
	 * @param parent
	 *            The parent widget
	 * @param sorter
	 *            The sorter to use.
	 * @param startIndex
	 *            the start index to start search for position from this allows
	 *            optimizing search for multiple elements that are sorted
	 *            themselves.
	 * @param element
	 *            element to find position for.
	 * @param currentSize
	 *            the current size of the collection
	 * @return the index to use when inserting the element.
	 *
	 */

	/**
	 * Returns the index where the item should be inserted.
	 *
	 * @param parent
	 *            The parent widget the element will be inserted into.
	 * @param element
	 *            The element to insert.
	 * @return the index of the element
	 */
	protected int indexForElement(Widget parent, Object element) {
		ViewerComparator comparator = getComparator();
		TreePath parentPath = internalGetSorterParentPath(parent, comparator);

		Item[] items = getChildren(parent);
		int count = items.length;

		if (comparator == null) {
			return count;
		}
		int min = 0, max = count - 1;

		while (min <= max) {
			int mid = (min + max) / 2;
			Object data = items[mid].getData();
			int compare = internalCompare(comparator, parentPath, data, element);
			if (compare == 0) {
				// find first item > element
				while (compare == 0) {
					++mid;
					if (mid >= count) {
						break;
					}
					data = items[mid].getData();
					compare = internalCompare(comparator, parentPath, data,
							element);
				}
				return mid;
			}
			if (compare < 0) {
				min = mid + 1;
			} else {
				max = mid - 1;
			}
		}
		return min;
	}

	/**
	 * Return the tree path that should be used as the parent path for the given
	 * widget and sorter. A <code>null</code> is returned if either the sorter
	 * is not a {@link TreePathViewerSorter} or if the parent widget is not an
	 * {@link Item} (i.e. is the root of the tree).
	 *
	 * @param parent
	 *            the parent widget
	 * @param comparator
	 *            the sorter
	 * @return the tree path that should be used as the parent path for the
	 *         given widget and sorter
	 */
	private TreePath internalGetSorterParentPath(Widget parent,
			ViewerComparator comparator) {
		TreePath path;
		if (comparator instanceof TreePathViewerSorter
				&& parent instanceof Item) {
			Item item = (Item) parent;
			path = getTreePathFromItem(item);
		} else {
			path = null;
		}
		return path;
	}

	/**
	 * Compare the two elements using the given sorter. If the sorter is a
	 * {@link TreePathViewerSorter}, the provided tree path will be used. If
	 * the tree path is null and the sorter is a tree path sorter, then the
	 * elements are root elements
	 *
	 * @param comparator
	 *            the sorter
	 * @param parentPath
	 *            the path of the elements' parent
	 * @param e1
	 *            the first element
	 * @param e2
	 *            the second element
	 * @return the result of comparing the two elements
	 */
	private int internalCompare(ViewerComparator comparator,
			TreePath parentPath, Object e1, Object e2) {
		if (comparator instanceof TreePathViewerSorter) {
			TreePathViewerSorter tpvs = (TreePathViewerSorter) comparator;
			return tpvs.compare(this, parentPath, e1, e2);
		}
		return comparator.compare(this, e1, e2);
	}

	@Override
	protected Object[] getSortedChildren(Object parentElementOrTreePath) {
		Object[] result = getFilteredChildren(parentElementOrTreePath);
		ViewerComparator comparator = getComparator();
		if (parentElementOrTreePath != null
				&& comparator instanceof TreePathViewerSorter) {
			TreePathViewerSorter tpvs = (TreePathViewerSorter) comparator;

			// be sure we're not modifying the original array from the model
			result = result.clone();

			TreePath path = null;
			if (parentElementOrTreePath instanceof TreePath) {
				path = (TreePath) parentElementOrTreePath;
			} else {
				Object parent = parentElementOrTreePath;
				Widget w = internalGetWidgetToSelect(parent);
				if (w != null) {
					path = internalGetSorterParentPath(w, comparator);
				}
			}
			tpvs.sort(this, path, result);
		} else if (comparator != null) {
			// be sure we're not modifying the original array from the model
			result = result.clone();
			comparator.sort(this, result);
		}
		return result;
	}

	/**
	 * Adds the given child element to this viewer as a child of the given
	 * parent element. If this viewer does not have a sorter, the element is
	 * added at the end of the parent's list of children; otherwise, the element
	 * is inserted at the appropriate position.
	 * <p>
	 * This method should be called (by the content provider) when a single
	 * element has been added to the model, in order to cause the viewer to
	 * accurately reflect the model. This method only affects the viewer, not
	 * the model. Note that there is another method for efficiently processing
	 * the simultaneous addition of multiple elements.
	 * </p>
	 *
	 * @param parentElementOrTreePath
	 *            the parent element or path
	 * @param childElement
	 *            the child element
	 */
	public void add(Object parentElementOrTreePath, Object childElement) {
		add(parentElementOrTreePath, new Object[] { childElement });
	}

	/**
	 * Adds the given SWT selection listener to the given SWT control.
	 *
	 * @param control
	 *            the SWT control
	 * @param listener
	 *            the SWT selection listener
	 * @deprecated
	 */
	@Deprecated
	protected void addSelectionListener(Control control,
			SelectionListener listener) {
		// do nothing
	}

	/**
	 * Adds a listener for expand and collapse events in this viewer. Has no
	 * effect if an identical listener is already registered.
	 *
	 * @param listener
	 *            a tree viewer listener
	 */
	public void addTreeListener(ITreeViewerListener listener) {
		treeListeners.add(listener);
	}

	/**
	 * Adds the given SWT tree listener to the given SWT control.
	 *
	 * @param control
	 *            the SWT control
	 * @param listener
	 *            the SWT tree listener
	 */
	protected abstract void addTreeListener(Control control,
			TreeListener listener);

	@Override
	protected void associate(Object element, Item item) {
		Object data = item.getData();
		if (data != null && data != element && equals(data, element)) {
			// workaround for PR 1FV62BT
			// assumption: elements are equal but not identical
			// -> remove from map but don't touch children
			unmapElement(data, item);
			item.setData(element);
			mapElement(element, item);
		} else {
			// recursively disassociate all
			super.associate(element, item);
		}
	}

	/**
	 * Collapses all nodes of the viewer's tree, starting with the root. This
	 * method is equivalent to <code>collapseToLevel(ALL_LEVELS)</code>.
	 */
	public void collapseAll() {
		Object root = getRoot();
		if (root != null) {
			collapseToLevel(root, ALL_LEVELS);
		}
	}

	/**
	 * Collapses the subtree rooted at the given element or tree path to the
	 * given level.
	 *
	 * @param elementOrTreePath
	 *            the element or tree path
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to collapse
	 *            all levels of the tree
	 */
	public void collapseToLevel(Object elementOrTreePath, int level) {
		Assert.isNotNull(elementOrTreePath);
		Widget w = internalGetWidgetToSelect(elementOrTreePath);
		if (w != null) {
			internalCollapseToLevel(w, level);
		}
	}

	/**
	 * Creates all children for the given widget.
	 * <p>
	 * The default implementation of this framework method assumes that
	 * <code>widget.getData()</code> returns the element corresponding to the
	 * node. Note: the node is not visually expanded! You may have to call
	 * <code>parent.setExpanded(true)</code>.
	 * </p>
	 *
	 * @param widget
	 *            the widget
	 */
	protected void createChildren(final Widget widget) {
		createChildren(widget, true);
	}

	/**
	 * Creates all children for the given widget.
	 * <p>
	 * The default implementation of this framework method assumes that
	 * <code>widget.getData()</code> returns the element corresponding to the
	 * node. Note: the node is not visually expanded! You may have to call
	 * <code>parent.setExpanded(true)</code>.
	 * </p>
	 *
	 * @param widget
	 *            the widget
	 * @param materialize
	 * 			  true if children are expected to be fully materialized
	 */
	void createChildren(final Widget widget, boolean materialize) {
		boolean oldBusy = isBusy();
		setBusy(true);
		try {
			final Item[] items = getChildren(widget);
			if (items != null && items.length > 0) {
				Object data = items[0].getData();
				if (data != null) {
					return; // children already there!
				}
			}

			// fix for PR 1FW89L7:
			// don't complain and remove all "dummies" ...
			if (items != null) {
				for (Item item : items) {
					if (item.getData() != null) {
						disassociate(item);
						Assert.isTrue(item.getData() == null, "Second or later child is non -null");//$NON-NLS-1$

					}
					item.dispose();
				}
			}
			Object d = widget.getData();
			if (d != null) {
				Object parentElement = d;
				Object[] children;
				if (isTreePathContentProvider() && widget instanceof Item) {
					TreePath path = getTreePathFromItem((Item) widget);
					children = getSortedChildren(path);
				} else {
					children = getSortedChildren(parentElement);
				}
				for (Object element : children) {
					createTreeItem(widget, element, -1);
				}
			}
		} finally {
			setBusy(oldBusy);
		}
	}

	/**
	 * Creates a single item for the given parent and synchronizes it with the
	 * given element.
	 *
	 * @param parent
	 *            the parent widget
	 * @param element
	 *            the element
	 * @param index
	 *            if non-negative, indicates the position to insert the item
	 *            into its parent
	 */
	protected void createTreeItem(Widget parent, Object element, int index) {
		Item item = newItem(parent, SWT.NULL, index);
		updateItem(item, element);
		updatePlus(item, element);
	}

	/**
	 * The <code>AbstractTreeViewer</code> implementation of this method also
	 * recurses over children of the corresponding element.
	 */
	@Override
	protected void disassociate(Item item) {
		super.disassociate(item);
		// recursively unmapping the items is only required when
		// the hash map is used. In the other case disposing
		// an item will recursively dispose its children.
		if (usingElementMap()) {
			disassociateChildren(item);
		}
	}

	/**
	 * Disassociates the children of the given SWT item from their corresponding
	 * elements.
	 *
	 * @param item
	 *            the widget
	 */
	private void disassociateChildren(Item item) {
		Item[] items = getChildren(item);
		for (Item child : items) {
			if (child.getData() != null) {
				disassociate(child);
			}
		}
	}

	@Override
	protected Widget doFindInputItem(Object element) {
		// compare with root
		Object root = getRoot();
		if (root == null) {
			return null;
		}

		if (equals(root, element)) {
			return getControl();
		}
		return null;
	}

	@Override
	protected Widget doFindItem(Object element) {
		// compare with root
		Object root = getRoot();
		if (root == null) {
			return null;
		}

		Item[] items = getChildren(getControl());
		if (items != null) {
			for (Item item : items) {
				Widget o = internalFindItem(item, element);
				if (o != null) {
					return o;
				}
			}
		}
		return null;
	}

	/**
	 * Copies the attributes of the given element into the given SWT item.
	 *
	 * @param item
	 *            the SWT item
	 * @param element
	 *            the element
	 */
	protected void doUpdateItem(final Item item, Object element) {
		if (item.isDisposed()) {
			unmapElement(element, item);
			return;
		}

		int columnCount = doGetColumnCount();
		if (columnCount == 0)// If no columns are created then fake one
			columnCount = 1;

		ViewerRow viewerRowFromItem = getViewerRowFromItem(item);

		boolean isVirtual = (getControl().getStyle() & SWT.VIRTUAL) != 0;

		// If the control is virtual, we cannot use the cached viewer row object. See bug 188663.
		if (isVirtual) {
			viewerRowFromItem = (ViewerRow) viewerRowFromItem.clone();
		}

		for (int column = 0; column < columnCount; column++) {
			ViewerColumn columnViewer = getViewerColumn(column);
			ViewerCell cellToUpdate = updateCell(viewerRowFromItem, column,
					element);

			// If the control is virtual, we cannot use the cached cell object. See bug 188663.
			if (isVirtual) {
				cellToUpdate = new ViewerCell(cellToUpdate.getViewerRow(), cellToUpdate.getColumnIndex(), element);
			}

			columnViewer.refresh(cellToUpdate);

			// clear cell (see bug 201280)
			updateCell(null, 0, null);

			// As it is possible for user code to run the event
			// loop check here.
			if (item.isDisposed()) {
				unmapElement(element, item);
				return;
			}

		}
	}

	/**
	 * Returns <code>true</code> if the given list and array of items refer to
	 * the same model elements. Order is unimportant.
	 * <p>
	 * This method is not intended to be overridden by subclasses.
	 * </p>
	 *
	 * @param items
	 *            the list of items
	 * @param current
	 *            the array of items
	 * @return <code>true</code> if the refer to the same elements,
	 *         <code>false</code> otherwise
	 *
	 * @since 3.1 in TreeViewer, moved to AbstractTreeViewer in 3.3
	 */
	protected boolean isSameSelection(List<Item> items, Item[] current) {
		// If they are not the same size then they are not equivalent
		int n = items.size();
		if (n != current.length) {
			return false;
		}

		CustomHashtable itemSet = newHashtable(n * 2 + 1);
		for (Item item : items) {
			Object element = item.getData();
			itemSet.put(element, element);
		}

		// Go through the items of the current collection
		// If there is a mismatch return false
		for (Item c : current) {
			if (c.getData() == null || !itemSet.containsKey(c.getData())) {
				return false;
			}
		}

		return true;
	}



	@Override
	protected void doUpdateItem(Widget widget, Object element, boolean fullMap) {
		boolean oldBusy = isBusy();
		setBusy(true);
		try {
			if (widget instanceof Item) {
				Item item = (Item) widget;

				// ensure that back pointer is correct
				if (fullMap) {
					associate(element, item);
				} else {
					Object data = item.getData();
					if (data != null) {
						unmapElement(data, item);
					}
					item.setData(element);
					mapElement(element, item);
				}

				// update icon and label
				SafeRunnable.run(new UpdateItemSafeRunnable(item, element));
			}
		} finally {
			setBusy(oldBusy);
		}
	}

	/**
	 * Expands all nodes of the viewer's tree, starting with the root. This
	 * method is equivalent to <code>expandToLevel(ALL_LEVELS)</code>.
	 */
	public void expandAll() {
		expandToLevel(ALL_LEVELS, false);
	}

	/**
	 * Expands all nodes of the viewer's tree, starting with the root. This method
	 * is equivalent to <code>expandToLevel(ALL_LEVELS)</code>.
	 *
	 * @param disableRedraw
	 *            <code>true</code> when drawing operations should be disabled
	 *            during expansion.
	 * @since 3.14
	 */
	public void expandAll(boolean disableRedraw) {
		expandToLevel(ALL_LEVELS, disableRedraw);
	}

	/**
	 * Expands the root of the viewer's tree to the given level.
	 *
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to expand all
	 *            levels of the tree
	 */
	public void expandToLevel(int level) {
		expandToLevel(level, false);
	}

	/**
	 * Expands the root of the viewer's tree to the given level.
	 *
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to expand all
	 *            levels of the tree
	 * @param disableRedraw
	 *            <code>true</code> when drawing operations should be disabled
	 *            during expansion.
	 * @since 3.14
	 */
	public void expandToLevel(int level, boolean disableRedraw) {
		BusyIndicator.showWhile(getControl().getDisplay(), () -> {
			expandToLevel(getRoot(), level, disableRedraw);
		});
	}

	/**
	 * Expands all ancestors of the given element or tree path so that the given
	 * element becomes visible in this viewer's tree control, and then expands
	 * the subtree rooted at the given element to the given level.
	 *
	 * @param elementOrTreePath
	 *            the element
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to expand all
	 *            levels of the tree
	 */
	public void expandToLevel(Object elementOrTreePath, int level) {
		expandToLevel(elementOrTreePath, level, false);
	}

	/**
	 * Expands all ancestors of the given element or tree path so that the given
	 * element becomes visible in this viewer's tree control, and then expands the
	 * subtree rooted at the given element to the given level.
	 *
	 * @param elementOrTreePath
	 *            the element
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to expand all
	 *            levels of the tree
	 * @param disableRedraw
	 *            <code>true</code> when drawing operations should be disabled
	 *            during expansion.
	 * @since 3.14
	 */
	public void expandToLevel(Object elementOrTreePath, int level, boolean disableRedraw) {
		if (checkBusy())
			return;
		Control control = getControl();
		try {
			if (disableRedraw) {
				control.setRedraw(false);
			}
			Widget w = internalExpand(elementOrTreePath, true);
			if (w != null) {
				internalExpandToLevel(w, level);
			}
		} finally {
			if (disableRedraw) {
				control.setRedraw(true);
			}
		}
	}

	/**
	 * Fires a tree collapsed event. Only listeners registered at the time this
	 * method is called are notified.
	 *
	 * @param event
	 *            the tree expansion event
	 * @see ITreeViewerListener#treeCollapsed
	 */
	protected void fireTreeCollapsed(final TreeExpansionEvent event) {
		boolean oldBusy = isBusy();
		setBusy(true);
		try {
			for (ITreeViewerListener l : treeListeners) {
				SafeRunnable.run(new SafeRunnable() {
					@Override
					public void run() {
						l.treeCollapsed(event);
					}
				});
			}
		} finally {
			setBusy(oldBusy);
		}
	}

	/**
	 * Fires a tree expanded event. Only listeners registered at the time this
	 * method is called are notified.
	 *
	 * @param event
	 *            the tree expansion event
	 * @see ITreeViewerListener#treeExpanded
	 */
	protected void fireTreeExpanded(final TreeExpansionEvent event) {
		boolean oldBusy = isBusy();
		setBusy(true);
		try {
			for (ITreeViewerListener l : treeListeners) {
				SafeRunnable.run(new SafeRunnable() {
					@Override
					public void run() {
						l.treeExpanded(event);
					}
				});
			}
		} finally {
			setBusy(oldBusy);
		}
	}

	/**
	 * Returns the auto-expand level.
	 *
	 * @return non-negative level, or <code>ALL_LEVELS</code> if all levels of
	 *         the tree are expanded automatically
	 * @see #setAutoExpandLevel
	 */
	public int getAutoExpandLevel() {
		return expandToLevel;
	}

	/**
	 * Returns the SWT child items for the given SWT widget.
	 *
	 * @param widget
	 *            the widget
	 * @return the child items
	 */
	protected abstract Item[] getChildren(Widget widget);

	/**
	 * Get the child for the widget at index. Note that the default
	 * implementation is not very efficient and should be overridden if this
	 * class is implemented.
	 *
	 * @param widget
	 *            the widget to check
	 * @param index
	 *            the index of the widget
	 * @return Item or <code>null</code> if widget is not a type that can
	 *         contain items.
	 *
	 * @throws ArrayIndexOutOfBoundsException
	 *             if the index is not valid.
	 * @since 3.1
	 */
	protected Item getChild(Widget widget, int index) {
		return getChildren(widget)[index];
	}

	/**
	 * Returns whether the given SWT item is expanded or collapsed.
	 *
	 * @param item
	 *            the item
	 * @return <code>true</code> if the item is considered expanded and
	 *         <code>false</code> if collapsed
	 */
	protected abstract boolean getExpanded(Item item);

	/**
	 * Returns a list of elements corresponding to expanded nodes in this
	 * viewer's tree, including currently hidden ones that are marked as
	 * expanded but are under a collapsed ancestor.
	 * <p>
	 * This method is typically used when preserving the interesting state of a
	 * viewer; <code>setExpandedElements</code> is used during the restore.
	 * </p>
	 *
	 * @return the array of expanded elements
	 * @see #setExpandedElements
	 */
	public Object[] getExpandedElements() {
		ArrayList<Item> items = new ArrayList<>();
		internalCollectExpandedItems(items, getControl());
		ArrayList<Object> result = new ArrayList<>(items.size());
		for (Item item : items) {
			Object data = item.getData();
			if (data != null) {
				result.add(data);
			}
		}
		return result.toArray();
	}

	/**
	 * Returns whether the node corresponding to the given element or tree path
	 * is expanded or collapsed.
	 *
	 * @param elementOrTreePath
	 *            the element
	 * @return <code>true</code> if the node is expanded, and
	 *         <code>false</code> if collapsed
	 */
	public boolean getExpandedState(Object elementOrTreePath) {
		Assert.isNotNull(elementOrTreePath);
		Widget item = internalGetWidgetToSelect(elementOrTreePath);
		if (item instanceof Item) {
			return getExpanded((Item) item);
		}
		return false;
	}

	/**
	 * Returns the number of child items of the given SWT control.
	 *
	 * @param control
	 *            the control
	 * @return the number of children
	 */
	protected abstract int getItemCount(Control control);

	/**
	 * Returns the number of child items of the given SWT item.
	 *
	 * @param item
	 *            the item
	 * @return the number of children
	 */
	protected abstract int getItemCount(Item item);

	/**
	 * Returns the child items of the given SWT item.
	 *
	 * @param item
	 *            the item
	 * @return the child items
	 */
	protected abstract Item[] getItems(Item item);

	/**
	 * Returns the item after the given item in the tree, or <code>null</code>
	 * if there is no next item.
	 *
	 * @param item
	 *            the item
	 * @param includeChildren
	 *            <code>true</code> if the children are considered in
	 *            determining which item is next, and <code>false</code> if
	 *            subtrees are ignored
	 * @return the next item, or <code>null</code> if none
	 */
	protected Item getNextItem(Item item, boolean includeChildren) {
		if (item == null) {
			return null;
		}
		if (includeChildren && getExpanded(item)) {
			Item[] children = getItems(item);
			if (children != null && children.length > 0) {
				return children[0];
			}
		}

		// next item is either next sibling or next sibling of first
		// parent that has a next sibling.
		Item parent = getParentItem(item);
		if (parent == null) {
			return null;
		}
		Item[] siblings = getItems(parent);
		if (siblings != null) {
			if (siblings.length <= 1) {
				return getNextItem(parent, false);
			}

			for (int i = 0; i < siblings.length; i++) {
				if (siblings[i] == item && i < (siblings.length - 1)) {
					return siblings[i + 1];
				}
			}
		}
		return getNextItem(parent, false);
	}

	/**
	 * Returns the parent item of the given item in the tree, or
	 * <code>null</code> if there is no parent item.
	 *
	 * @param item
	 *            the item
	 * @return the parent item, or <code>null</code> if none
	 */
	protected abstract Item getParentItem(Item item);

	/**
	 * Returns the item before the given item in the tree, or <code>null</code>
	 * if there is no previous item.
	 *
	 * @param item
	 *            the item
	 * @return the previous item, or <code>null</code> if none
	 */
	protected Item getPreviousItem(Item item) {
		// previous item is either right-most visible descendent of previous
		// sibling or parent
		Item parent = getParentItem(item);
		if (parent == null) {
			return null;
		}
		Item[] siblings = getItems(parent);
		if (siblings.length == 0 || siblings[0] == item) {
			return parent;
		}
		Item previous = siblings[0];
		for (int i = 1; i < siblings.length; i++) {
			if (siblings[i] == item) {
				return rightMostVisibleDescendent(previous);
			}
			previous = siblings[i];
		}
		return null;
	}

	@Override
	protected Object[] getRawChildren(Object parentElementOrTreePath) {
		boolean oldBusy = isBusy();
		setBusy(true);
		try {
			Object parent;
			TreePath path;
			if (parentElementOrTreePath instanceof TreePath) {
				path = (TreePath) parentElementOrTreePath;
				parent = path.getLastSegment();
			} else {
				parent = parentElementOrTreePath;
				path = null;
			}
			if (parent != null) {
				if (equals(parent, getRoot())) {
					return super.getRawChildren(parent);
				}
				IContentProvider cp = getContentProvider();
				if (cp instanceof ITreePathContentProvider) {
					ITreePathContentProvider tpcp = (ITreePathContentProvider) cp;
					if (path == null) {
						// A path was not provided so try and find one
						Widget w = findItem(parent);
						if (w instanceof Item) {
							Item item = (Item) w;
							path = getTreePathFromItem(item);
						}
						if (path == null) {
							path = new TreePath(new Object[] { parent });
						}
					}
					Object[] result = tpcp.getChildren(path);
					if (result != null) {
						assertElementsNotNull(parent, result);
						return result;
					}
				} else if (cp instanceof ITreeContentProvider) {
					ITreeContentProvider tcp = (ITreeContentProvider) cp;
					Object[] result = tcp.getChildren(parent);
					if (result != null) {
						assertElementsNotNull(parent, result);
						return result;
					}
				}
			}
			return new Object[0];
		} finally {
			setBusy(oldBusy);
		}
	}

	/**
	 * Asserts that the given array of elements is itself non- <code>null</code>
	 * and contains no <code>null</code> elements.
	 *
	 * @param parent
	 *            the parent element
	 * @param elements
	 *            the array to check
	 *
	 * @see #assertElementsNotNull(Object[])
	 */
	private void assertElementsNotNull(Object parent, Object[] elements) {
		Assert.isNotNull(elements);
		for (Object element : elements) {
			Assert.isNotNull(element);
		}

		if (InternalPolicy.DEBUG_LOG_EQUAL_VIEWER_ELEMENTS
				&& elements.length > 1) {
			CustomHashtable elementSet = newHashtable(elements.length * 2);
			for (Object element : elements) {
				Object old = elementSet.put(element, element);
				if (old != null) {
					String message = "Sibling elements in viewer must not be equal:\n  " //$NON-NLS-1$
							+ old + ",\n  " + element + ",\n  parent: " + parent; //$NON-NLS-1$ //$NON-NLS-2$
					Policy.getLog().log(
							new Status(IStatus.WARNING, Policy.JFACE, message,
									new RuntimeException()));
					return;
				}
			}
		}
	}

	/**
	 * Returns all selected items for the given SWT control.
	 *
	 * @param control
	 *            the control
	 * @return the list of selected items
	 */
	protected abstract Item[] getSelection(Control control);

	@SuppressWarnings("rawtypes")
	@Override
	protected List getSelectionFromWidget() {
		Widget[] items = getSelection(getControl());
		List<Object> list = new ArrayList<>(items.length);
		for (Widget item : items) {
			Object e = item.getData();
			if (e != null) {
				list.add(e);
			}
		}
		return list;
	}

	/*
	 * Overridden in AbstractTreeViewer to fix bug 108102 (code copied from
	 * StructuredViewer to avoid introducing new API)
	 */
	@Override
	protected void handleDoubleSelect(SelectionEvent event) {
		// handle case where an earlier selection listener disposed the control.
		Control control = getControl();
		if (control != null && !control.isDisposed()) {
			// If the double-clicked element can be obtained from the event, use
			// it
			// otherwise get it from the control. Some controls like List do
			// not have the notion of item.
			// For details, see bug 90161 [Navigator] DefaultSelecting folders
			// shouldn't always expand first one
			ISelection selection;
			if (event.item != null && event.item.getData() != null) {

				// changes to fix bug 108102 follow
				TreePath treePath = getTreePathFromItem((Item) event.item);
				selection = new TreeSelection(treePath);
				// end of changes

			} else {
				selection = getSelection();
				updateSelection(selection);
			}
			fireDoubleClick(new DoubleClickEvent(this, selection));
		}
	}

	/**
	 * Handles a tree collapse event from the SWT widget.
	 *
	 * @param event
	 *            the SWT tree event
	 */
	protected void handleTreeCollapse(TreeEvent event) {
		if (event.item.getData() != null) {
			fireTreeCollapsed(new TreeExpansionEvent(this, event.item.getData()));
		}
	}

	/**
	 * Handles a tree expand event from the SWT widget.
	 *
	 * @param event
	 *            the SWT tree event
	 */
	protected void handleTreeExpand(TreeEvent event) {
		createChildren(event.item);
		if (event.item.getData() != null) {
			fireTreeExpanded(new TreeExpansionEvent(this, event.item.getData()));
		}
	}

	@Override
	protected void hookControl(Control control) {
		super.hookControl(control);
		addTreeListener(control, new TreeListener() {
			@Override
			public void treeExpanded(TreeEvent event) {
				handleTreeExpand(event);
			}

			@Override
			public void treeCollapsed(TreeEvent event) {
				handleTreeCollapse(event);
			}
		});
	}

	@Override
	protected void inputChanged(Object input, Object oldInput) {
		preservingSelection(() -> {
			Control tree = getControl();
			tree.setRedraw(false);
			try {
				removeAll(tree);
				tree.setData(getRoot());
				internalInitializeTree(tree);
			} finally {
				tree.setRedraw(true);
			}
		});
	}

	/**
	 * Initializes the tree with root items, expanding to the appropriate
	 * level if necessary.
	 *
	 * @param tree the tree control
	 * @since 3.3
	 */
	protected void internalInitializeTree(Control tree) {
		createChildren(tree);
		internalExpandToLevel(tree, expandToLevel);
	}

	/**
	 * Recursively collapses the subtree rooted at the given widget to the given
	 * level.
	 * <p>
	 * Note that the default implementation of this method does not call
	 * <code>setRedraw</code>.
	 * </p>
	 *
	 * @param widget the widget
	 * @param level  non-negative level, or <code>ALL_LEVELS</code> to collapse all
	 *               levels of the tree
	 */
	protected void internalCollapseToLevel(Widget widget, int level) {
		if (level == ALL_LEVELS || level > 0) {

			if (widget instanceof Item) {
				Item item = (Item) widget;
				setExpanded(item, false);
				Object element = item.getData();
				if (element != null && level == ALL_LEVELS) {
					if (optionallyPruneChildren(item, element)) {
						return;
					}
				}
			}

			if (level == ALL_LEVELS || level > 1) {
				Item[] children = getChildren(widget);
				if (children != null) {
					int nextLevel = (level == ALL_LEVELS ? ALL_LEVELS
							: level - 1);
					for (Item element : children) {
						internalCollapseToLevel(element, nextLevel);
					}
				}
			}
		}
	}

	/**
	 * Recursively collects all expanded items from the given widget.
	 *
	 * @param result
	 *            a list (element type: <code>Item</code>) into which to
	 *            collect the elements
	 * @param widget
	 *            the widget
	 */
	private void internalCollectExpandedItems(List<Item> result, Widget widget) {
		Item[] items = getChildren(widget);
		for (Item item : items) {
			// Disregard dummy nodes (see bug 287765)
			if (item.getData() != null) {
				if (getExpanded(item)) {
					result.add(item);
				}
				internalCollectExpandedItems(result, item);
			}
		}
	}

	/**
	 * Tries to create a path of tree items for the given element or tree path.
	 * This method recursively walks up towards the root of the tree and in the
	 * case of an element (rather than a tree path) assumes that
	 * <code>getParent</code> returns the correct parent of an element.
	 *
	 * @param elementOrPath
	 *            the element
	 * @param expand
	 *            <code>true</code> if all nodes on the path should be
	 *            expanded, and <code>false</code> otherwise
	 * @return Widget
	 */
	protected Widget internalExpand(Object elementOrPath, boolean expand) {

		if (elementOrPath == null) {
			return null;
		}

		Widget w = internalGetWidgetToSelect(elementOrPath);
		if (w == null) {
			if (equals(elementOrPath, getRoot())) { // stop at root
				return null;
			}
			// my parent has to create me
			Object parent = getParentElement(elementOrPath);
			if (parent != null) {
				Widget pw = internalExpand(parent, false);
				if (pw != null) {
					// let my parent create me
					createChildren(pw);
					Object element = internalToElement(elementOrPath);
					w = internalFindChild(pw, element);
				}
			}
		}
		if (expand && w instanceof Item) {
			// expand parent items top-down
			Item item = getParentItem((Item) w);
			LinkedList<Item> toExpandList = new LinkedList<>();
			while (item != null) {
				if (!getExpanded(item)) {
					toExpandList.addFirst(item);
				}
				item = getParentItem(item);
			}
			for (Item toExpand : toExpandList) {
				setExpanded(toExpand, true);
			}
		}
		return w;
	}

	/**
	 * If the argument is a tree path, returns its last segment, otherwise
	 * return the argument
	 *
	 * @param elementOrPath
	 *            an element or a tree path
	 * @return the element, or the last segment of the tree path
	 */
	private Object internalToElement(Object elementOrPath) {
		if (elementOrPath instanceof TreePath) {
			return ((TreePath) elementOrPath).getLastSegment();
		}
		return elementOrPath;
	}

	/**
	 * This method takes a tree path or an element. If the argument is not a
	 * tree path, returns the parent of the given element or <code>null</code>
	 * if the parent is not known. If the argument is a tree path with more than
	 * one segment, returns its parent tree path, otherwise returns
	 * <code>null</code>.
	 *
	 * @param elementOrTreePath
	 * @return the parent element, or parent path, or <code>null</code>
	 *
	 * @since 3.2
	 */
	protected Object getParentElement(Object elementOrTreePath) {
		if (elementOrTreePath instanceof TreePath) {
			TreePath treePath = (TreePath) elementOrTreePath;
			return (treePath).getParentPath();
		}
		IContentProvider cp = getContentProvider();
		if (cp instanceof ITreePathContentProvider) {
			ITreePathContentProvider tpcp = (ITreePathContentProvider) cp;
			TreePath[] paths = tpcp.getParents(elementOrTreePath);
			if (paths.length > 0) {
				if (paths[0].getSegmentCount() == 0) {
					return getRoot();
				}
				return paths[0].getLastSegment();
			}
		}
		if (cp instanceof ITreeContentProvider) {
			ITreeContentProvider tcp = (ITreeContentProvider) cp;
			return tcp.getParent(elementOrTreePath);
		}
		return null;
	}

	/**
	 * Returns the widget to be selected for the given element or tree path.
	 *
	 * @param elementOrTreePath
	 *            the element or tree path to select
	 * @return the widget to be selected, or <code>null</code> if not found
	 *
	 * @since 3.1
	 */
	protected Widget internalGetWidgetToSelect(Object elementOrTreePath) {
		if (elementOrTreePath instanceof TreePath) {
			TreePath treePath = (TreePath) elementOrTreePath;
			if (treePath.getSegmentCount() == 0) {
				return getControl();
			}
			Widget[] candidates = findItems(treePath.getLastSegment());
			for (Widget candidate : candidates) {
				if (!(candidate instanceof Item)) {
					continue;
				}
				if (treePath.equals(getTreePathFromItem((Item) candidate), getComparer())) {
					return candidate;
				}
			}
			return null;
		}
		return findItem(elementOrTreePath);
	}

	/**
	 * Recursively expands the subtree rooted at the given widget to the given
	 * level.
	 * <p>
	 * Note that the default implementation of this method does not call
	 * <code>setRedraw</code>.
	 * </p>
	 *
	 * @param widget the widget
	 * @param level  non-negative level, or <code>ALL_LEVELS</code> to collapse all
	 *               levels of the tree
	 */
	protected void internalExpandToLevel(Widget widget, int level) {
		if (level == ALL_LEVELS || level > 0) {
			if (widget instanceof Item && widget.getData() != null
					&& !isExpandable((Item) widget, null, widget.getData())) {
				return;
			}
			createChildren(widget, false);
			if (widget instanceof Item) {
				setExpanded((Item) widget, true);
			}
			if (level == ALL_LEVELS || level > 1) {
				Item[] children = getChildren(widget);
				if (children != null) {
					int newLevel = (level == ALL_LEVELS ? ALL_LEVELS
							: level - 1);
					for (Item element : children) {
						internalExpandToLevel(element, newLevel);
					}
				}
			}
		}
	}

	/**
	 * Non-recursively tries to find the given element as a child of the given
	 * parent (item or tree).
	 *
	 * @param parent
	 *            the parent item
	 * @param element
	 *            the element
	 * @return Widget
	 */
	private Widget internalFindChild(Widget parent, Object element) {
		Item[] items = getChildren(parent);
		for (Item item : items) {
			Object data = item.getData();
			if (data != null && equals(data, element)) {
				return item;
			}
		}
		return null;
	}

	/**
	 * Recursively tries to find the given element.
	 *
	 * @param parent
	 *            the parent item
	 * @param element
	 *            the element
	 * @return Widget
	 */
	private Widget internalFindItem(Item parent, Object element) {

		// compare with node
		Object data = parent.getData();
		if (data != null) {
			if (equals(data, element)) {
				return parent;
			}
		}
		// recurse over children
		Item[] items = getChildren(parent);
		for (Item item : items) {
			Widget o = internalFindItem(item, element);
			if (o != null) {
				return o;
			}
		}
		return null;
	}

	@Override
	protected void internalRefresh(Object element) {
		internalRefresh(element, true);
	}

	@Override
	protected void internalRefresh(Object element, boolean updateLabels) {
		// If element is null, do a full refresh.
		if (element == null) {
			internalRefresh(getControl(), getRoot(), true, updateLabels);
			return;
		}
		Widget[] items = findItems(element);
		if (items.length != 0) {
			for (Widget item : items) {
				// pick up structure changes too
				internalRefresh(item, element, true, updateLabels);
			}
		}
	}

	/**
	 * Refreshes the tree starting at the given widget.
	 * <p>
	 * EXPERIMENTAL. Not to be used except by JDT. This method was added to
	 * support JDT's explorations into grouping by working sets. This method
	 * cannot be removed without breaking binary backwards compatibility, but
	 * should not be called by clients.
	 * </p>
	 *
	 * @param widget
	 *            the widget
	 * @param element
	 *            the element
	 * @param doStruct
	 *            <code>true</code> if structural changes are to be picked up,
	 *            and <code>false</code> if only label provider changes are of
	 *            interest
	 * @param updateLabels
	 *            <code>true</code> to update labels for existing elements,
	 *            <code>false</code> to only update labels as needed, assuming
	 *            that labels for existing elements are unchanged.
	 * @since 3.1
	 */
	protected void internalRefresh(Widget widget, Object element,
			boolean doStruct, boolean updateLabels) {

		if (widget instanceof Item) {
			if (doStruct) {
				updatePlus((Item) widget, element);
			}
			if (updateLabels || !equals(element, widget.getData())) {
				doUpdateItem(widget, element, true);
			} else {
				associate(element, (Item) widget);
			}
		}

		if (doStruct) {
			internalRefreshStruct(widget, element, updateLabels);
		} else {
			Item[] children = getChildren(widget);
			if (children != null) {
				for (Item item : children) {
					Object data = item.getData();
					if (data != null) {
						internalRefresh(item, data, doStruct, updateLabels);
					}
				}
			}
		}
	}

	/**
	 * Update the structure and recurse. Items are updated in updateChildren, as
	 * needed.
	 *
	 * @param widget
	 * @param element
	 * @param updateLabels
	 */
	/* package */void internalRefreshStruct(Widget widget, Object element,
			boolean updateLabels) {
		updateChildren(widget, element, null, updateLabels);
		Item[] children = getChildren(widget);
		if (children != null) {
			for (Item item : children) {
				Object data = item.getData();
				if (data != null) {
					internalRefreshStruct(item, data, updateLabels);
				}
			}
		}
	}

	/**
	 * Removes the given elements from this viewer.
	 * <p>
	 * EXPERIMENTAL. Not to be used except by JDT. This method was added to
	 * support JDT's explorations into grouping by working sets. This method
	 * cannot be removed without breaking binary backwards compatibility, but
	 * should not be called by clients.
	 * </p>
	 *
	 * @param elementsOrPaths
	 *            the elements or element paths to remove
	 * @since 3.1
	 */
	protected void internalRemove(Object[] elementsOrPaths) {
		Object input = getInput();
		for (Object element : elementsOrPaths) {
			if (equals(element, input)) {
				setInput(null);
				return;
			}
			Widget[] childItems = internalFindItems(element);
			if (childItems.length > 0) {
				for (Widget childItem : childItems) {
					if (childItem instanceof Item) {
						disassociate((Item) childItem);
						childItem.dispose();
					}
				}
			} else {
				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=210747
				Object parent = getParentElement(element);
				if (parent != null
						&& !equals(parent, getRoot())
						&& !(parent instanceof TreePath && ((TreePath) parent)
								.getSegmentCount() == 0)) {
					Widget[] parentItems = internalFindItems(parent);
					for (Widget parentItem : parentItems) {
						if (parentItem instanceof Item) {
							updatePlus((Item) parentItem, parent);
						}
					}
				}
			}
		}
	}

	/**
	 * Removes the given elements from this viewer, whenever those elements
	 * appear as children of the given parent.
	 *
	 * @param parent the parent element
	 * @param elements
	 *            the elements to remove
	 * @since 3.1
	 */
	protected void internalRemove(Object parent, Object[] elements) {

		CustomHashtable toRemove = new CustomHashtable(getComparer());
		for (Object element : elements) {
			toRemove.put(element, element);
		}

		// Find each place the parent appears in the tree
		Widget[] parentItemArray = findItems(parent);
		for (Widget parentItem : parentItemArray) {
			// May happen if parent element is a descendent of of a previously
			// removed element
			if (parentItem.isDisposed())
				continue;

			// Iterate over the child items and remove each one
			Item[] children = getChildren(parentItem);

			if (children.length == 1 && children[0].getData() == null &&
					parentItem instanceof Item) { // dummy node
				// Remove plus if parent element has no children
				updatePlus((Item) parentItem, parent);
			} else {
				for (Item child : children) {
					Object data = child.getData();
					if (data != null && toRemove.containsKey(data)) {
						disassociate(child);
						child.dispose();
					}
				}
			}
		}
	}

	/**
	 * Sets the expanded state of all items to correspond to the given set of
	 * expanded elements.
	 *
	 * @param expandedElements
	 *            the set (element type: <code>Object</code>) of elements
	 *            which are expanded
	 * @param widget
	 *            the widget
	 */
	private void internalSetExpanded(CustomHashtable expandedElements,
			Widget widget) {
		Item[] items = getChildren(widget);
		for (Item item : items) {
			Object data = item.getData();
			if (data != null) {
				// remove the element to avoid an infinite loop
				// if the same element appears on a child item
				boolean expanded = expandedElements.remove(data) != null;
				if (expanded != getExpanded(item)) {
					if (expanded) {
						createChildren(item);
					}
					setExpanded(item, expanded);
				}
			}
			if (expandedElements.size() > 0) {
				internalSetExpanded(expandedElements, item);
			}
		}
	}

	/**
	 * Sets the expanded state of all items to correspond to the given set of
	 * expanded tree paths.
	 *
	 * @param expandedTreePaths
	 *            the set (element type: <code>TreePath</code>) of elements
	 *            which are expanded
	 * @param widget
	 *            the widget
	 */
	private void internalSetExpandedTreePaths(
			CustomHashtable expandedTreePaths, Widget widget,
			TreePath currentPath) {
		Item[] items = getChildren(widget);
		for (Item item : items) {
			Object data = item.getData();
			TreePath childPath = data == null ? null : currentPath
					.createChildPath(data);
			if (data != null && childPath != null) {
				// remove the element to avoid an infinite loop
				// if the same element appears on a child item
				boolean expanded = expandedTreePaths.remove(childPath) != null;
				if (expanded != getExpanded(item)) {
					if (expanded) {
						createChildren(item);
					}
					setExpanded(item, expanded);
				}
			}
			internalSetExpandedTreePaths(expandedTreePaths, item, childPath);
		}
	}

	/**
	 * Return whether the tree node representing the given element or path can
	 * be expanded. Clients should query expandability by path if the viewer's
	 * content provider is an {@link ITreePathContentProvider}.
	 * <p>
	 * The default implementation of this framework method calls
	 * <code>hasChildren</code> on this viewer's content provider. It may be
	 * overridden if necessary.
	 * </p>
	 * @see #setExpandPreCheckFilters(boolean)
	 * @param elementOrTreePath
	 *            the element or path
	 * @return <code>true</code> if the tree node representing the given
	 *         element can be expanded, or <code>false</code> if not
	 */
	public boolean isExpandable(Object elementOrTreePath) {
		Object element;
		TreePath path;
		if (elementOrTreePath instanceof TreePath) {
			path = (TreePath) elementOrTreePath;
			element = path.getLastSegment();
		} else {
			element = elementOrTreePath;
			path = null;
		}
		IContentProvider cp = getContentProvider();
		if (cp instanceof ITreePathContentProvider) {
			ITreePathContentProvider tpcp = (ITreePathContentProvider) cp;
			if (path == null) {
				// A path was not provided so try and find one
				Widget w = findItem(element);
				if (w instanceof Item) {
					Item item = (Item) w;
					path = getTreePathFromItem(item);
				}
				if (path == null) {
					path = new TreePath(new Object[] { element });
				}
			}
			boolean hasChildren = tpcp.hasChildren(path);
			if (hasChildren && isExpandableCheckFilters && hasFilters()) {
				return getFilteredChildren(path).length > 0;
			}
			return hasChildren;
		}
		if (cp instanceof ITreeContentProvider) {
			ITreeContentProvider tcp = (ITreeContentProvider) cp;
			boolean hasChildren = tcp.hasChildren(element);
			if (hasChildren && isExpandableCheckFilters && hasFilters()) {
				return getFilteredChildren(element).length > 0;
			}
			return hasChildren;
		}
		return false;
	}

	/**
	 * Return whether the given element is expandable.
	 *
	 * @param item
	 *            the tree item for the element
	 * @param parentPath
	 *            the parent path if it is known or <code>null</code> if it
	 *            needs to be determines
	 * @param element
	 *            the element
	 * @return whether the given element is expandable
	 */
	private boolean isExpandable(Item item, TreePath parentPath, Object element) {
		Object elementOrTreePath = element;
		if (isTreePathContentProvider()) {
			if (parentPath != null) {
				elementOrTreePath = parentPath.createChildPath(element);
			} else {
				elementOrTreePath = getTreePathFromItem(item);
			}
		}
		return isExpandable(elementOrTreePath);
	}

	@Override
	protected void labelProviderChanged() {
		// we have to walk the (visible) tree and update every item
		Control tree = getControl();
		tree.setRedraw(false);
		// don't pick up structure changes, but do force label updates
		internalRefresh(tree, getRoot(), false, true);
		tree.setRedraw(true);
	}

	/**
	 * Creates a new item.
	 *
	 * @param parent
	 *            the parent widget
	 * @param style
	 *            SWT style bits
	 * @param index
	 *            if non-negative, indicates the position to insert the item
	 *            into its parent
	 * @return the newly-created item
	 */
	protected abstract Item newItem(Widget parent, int style, int index);

	/**
	 * Removes the given elements from this viewer. The selection is updated if
	 * required.
	 * <p>
	 * This method should be called (by the content provider) when elements have
	 * been removed from the model, in order to cause the viewer to accurately
	 * reflect the model. This method only affects the viewer, not the model.
	 * </p>
	 *
	 * @param elementsOrTreePaths the elements to remove
	 */
	public void remove(final Object... elementsOrTreePaths) {
		assertElementsNotNull(elementsOrTreePaths);
		if (elementsOrTreePaths.length == 0) {
			return;
		}
		if (checkBusy())
			return;
		preservingSelection(() -> internalRemove(elementsOrTreePaths));
	}

	/**
	 * Removes the given elements from this viewer whenever they appear as
	 * children of the given parent element. If the given elements also appear
	 * as children of some other parent, the other parent will remain unchanged.
	 * The selection is updated if required.
	 * <p>
	 * This method should be called (by the content provider) when elements have
	 * been removed from the model, in order to cause the viewer to accurately
	 * reflect the model. This method only affects the viewer, not the model.
	 * </p>
	 *
	 * @param parent
	 *            the parent of the elements to remove
	 * @param elements
	 *            the elements to remove
	 *
	 * @since 3.2
	 */
	public void remove(final Object parent, final Object... elements) {
		assertElementsNotNull(elements);
		if (elements.length == 0) {
			return;
		}
		if (checkBusy())
			return;
		preservingSelection(() -> internalRemove(parent, elements));
	}

	/**
	 * Removes the given element from the viewer. The selection is updated if
	 * necessary.
	 * <p>
	 * This method should be called (by the content provider) when a single
	 * element has been removed from the model, in order to cause the viewer to
	 * accurately reflect the model. This method only affects the viewer, not
	 * the model. Note that there is another method for efficiently processing
	 * the simultaneous removal of multiple elements.
	 * </p>
	 *
	 * @param elementsOrTreePaths
	 *            the element
	 */
	public void remove(Object elementsOrTreePaths) {
		remove(new Object[] { elementsOrTreePaths });
	}

	/**
	 * Removes all items from the given control.
	 *
	 * @param control
	 *            the control
	 */
	protected abstract void removeAll(Control control);

	/**
	 * Removes a listener for expand and collapse events in this viewer. Has no
	 * effect if an identical listener is not registered.
	 *
	 * @param listener
	 *            a tree viewer listener
	 */
	public void removeTreeListener(ITreeViewerListener listener) {
		treeListeners.remove(listener);
	}

	/**
	 * This implementation of reveal() reveals the given element or tree path.
	 */
	@Override
	public void reveal(Object elementOrTreePath) {
		Assert.isNotNull(elementOrTreePath);
		Widget w = internalExpand(elementOrTreePath, true);
		if (w instanceof Item) {
			showItem((Item) w);
		}
	}

	/**
	 * Returns the rightmost visible descendent of the given item. Returns the
	 * item itself if it has no children.
	 *
	 * @param item
	 *            the item to compute the descendent of
	 * @return the rightmost visible descendent or the item itself if it has no
	 *         children
	 */
	private Item rightMostVisibleDescendent(Item item) {
		Item[] children = getItems(item);
		if (getExpanded(item) && children != null && children.length > 0) {
			return rightMostVisibleDescendent(children[children.length - 1]);
		}
		return item;
	}

	@Override
	public Item scrollDown(int x, int y) {
		Item current = getItem(x, y);
		if (current != null) {
			Item next = getNextItem(current, true);
			showItem(next == null ? current : next);
			return next;
		}
		return null;
	}

	@Override
	public Item scrollUp(int x, int y) {
		Item current = getItem(x, y);
		if (current != null) {
			Item previous = getPreviousItem(current);
			showItem(previous == null ? current : previous);
			return previous;
		}
		return null;
	}

	/**
	 * Sets the auto-expand level to be used when the input of the viewer is set
	 * using {@link #setInput(Object)}. The value 0 means that there is no
	 * auto-expand; 1 means that the invisible root element is expanded (since
	 * most concrete subclasses do not show the root element, there is usually
	 * no practical difference between using the values 0 and 1); 2 means that
	 * top-level elements are expanded, but not their children; 3 means that
	 * top-level elements are expanded, and their children, but not
	 * grandchildren; and so on.
	 * <p>
	 * The value <code>ALL_LEVELS</code> means that all subtrees should be
	 * expanded.
	 * </p>
	 * <p>
	 * Note that in previous releases, the Javadoc for this method had an off-by
	 * one error. See bug 177669 for details.
	 * </p>
	 *
	 * @param level
	 *            non-negative level, or <code>ALL_LEVELS</code> to expand all
	 *            levels of the tree
	 */
	public void setAutoExpandLevel(int level) {
		expandToLevel = level;
	}

	/**
	 * Sets the content provider used by this <code>AbstractTreeViewer</code>.
	 * <p>
	 * Content providers for abstract tree viewers must implement either
	 * {@link ITreeContentProvider} or {@link ITreePathContentProvider}.
	 */
	@Override
	public void setContentProvider(IContentProvider provider) {
		// the actual check is in assertContentProviderType
		super.setContentProvider(provider);
	}

	@Override
	protected void assertContentProviderType(IContentProvider provider) {
		Assert.isTrue(provider instanceof ITreeContentProvider
				|| provider instanceof ITreePathContentProvider,
				"Instances of AbstractTreeViewer must have a content provider " //$NON-NLS-1$
						+ "of type ITreeContentProvider or ITreePathContentProvider"); //$NON-NLS-1$
	}

	/**
	 * Sets the expand state of the given item.
	 *
	 * @param item
	 *            the item
	 * @param expand
	 *            the expand state of the item
	 */
	protected abstract void setExpanded(Item item, boolean expand);

	/**
	 * Sets which nodes are expanded in this viewer's tree. The given list
	 * contains the elements that are to be expanded; all other nodes are to be
	 * collapsed.
	 * <p>
	 * This method is typically used when restoring the interesting state of a
	 * viewer captured by an earlier call to <code>getExpandedElements</code>.
	 * </p>
	 *
	 * @param elements
	 *            the array of expanded elements
	 * @see #getExpandedElements
	 */
	public void setExpandedElements(Object... elements) {
		assertElementsNotNull(elements);
		if (checkBusy()) {
			return;
		}
		CustomHashtable expandedElements = newHashtable(elements.length * 2 + 1);
		for (Object element : elements) {
			// Ensure item exists for element. This will materialize items for
			// each element and their parents, if possible. This is important
			// to support expanding of inner tree nodes without necessarily
			// expanding their parents.
			internalExpand(element, false);
			expandedElements.put(element, element);
		}
		// this will traverse all existing items, and create children for
		// elements that need to be expanded. If the tree contains multiple
		// equal elements, and those are in the set of elements to be expanded,
		// only the first item found for each element will be expanded.
		internalSetExpanded(expandedElements, getControl());
	}

	/**
	 * Sets which nodes are expanded in this viewer's tree. The given list
	 * contains the tree paths that are to be expanded; all other nodes are to
	 * be collapsed.
	 * <p>
	 * This method is typically used when restoring the interesting state of a
	 * viewer captured by an earlier call to <code>getExpandedTreePaths</code>.
	 * </p>
	 *
	 * @param treePaths
	 *            the array of expanded tree paths
	 * @see #getExpandedTreePaths()
	 *
	 * @since 3.2
	 */
	public void setExpandedTreePaths(TreePath... treePaths) {
		assertElementsNotNull((Object[]) treePaths);
		if (checkBusy())
			return;
		final IElementComparer comparer = getComparer();
		IElementComparer treePathComparer = new IElementComparer() {

			@Override
			public boolean equals(Object a, Object b) {
				return ((TreePath) a).equals(((TreePath) b), comparer);
			}


			@Override
			public int hashCode(Object element) {
				return ((TreePath) element).hashCode(comparer);
			}
		};
		CustomHashtable expandedTreePaths = new CustomHashtable(
				treePaths.length * 2 + 1, treePathComparer);
		for (TreePath treePath : treePaths) {
			// Ensure item exists for element. This will materialize items for
			// each element and their parents, if possible. This is important
			// to support expanding of inner tree nodes without necessarily
			// expanding their parents.
			internalExpand(treePath, false);
			expandedTreePaths.put(treePath, treePath);
		}
		// this will traverse all existing items, and create children for
		// elements that need to be expanded. If the tree contains multiple
		// equal elements, and those are in the set of elements to be expanded,
		// only the first item found for each element will be expanded.
		internalSetExpandedTreePaths(expandedTreePaths, getControl(),
				new TreePath(new Object[0]));
	}

	/**
	 * Sets whether the node corresponding to the given element or tree path is
	 * expanded or collapsed.
	 *
	 * @param elementOrTreePath
	 *            the element
	 * @param expanded
	 *            <code>true</code> if the node is expanded, and
	 *            <code>false</code> if collapsed
	 */
	public void setExpandedState(Object elementOrTreePath, boolean expanded) {
		Assert.isNotNull(elementOrTreePath);
		if (checkBusy())
			return;
		Widget item = internalExpand(elementOrTreePath, false);
		if (item instanceof Item) {
			if (expanded) {
				createChildren(item);
			}
			setExpanded((Item) item, expanded);
		}
	}

	/**
	 * Sets the selection to the given list of items.
	 *
	 * @param items
	 *            list of items (element type:
	 *            <code>org.eclipse.swt.widgets.Item</code>)
	 */
	protected abstract void setSelection(List<Item> items);

	/**
	 * This implementation of setSelectionToWidget accepts a list of elements or
	 * a list of tree paths.
	 */
	@Override
	protected void setSelectionToWidget(@SuppressWarnings("rawtypes") List v, boolean reveal) {
		if (v == null) {
			setSelection(new ArrayList<>(0));
			return;
		}
		int size = v.size();
		List<Item> newSelection = new ArrayList<>(size);
		for (int i = 0; i < size; ++i) {
			Object elementOrTreePath = v.get(i);
			// Use internalExpand since item may not yet be created. See
			// 1G6B1AR.
			Widget w = internalExpand(elementOrTreePath, false);
			if (w instanceof Item) {
				newSelection.add((Item) w);
			} else if (w == null && elementOrTreePath instanceof TreePath) {
				TreePath treePath = (TreePath) elementOrTreePath;
				Object element = treePath.getLastSegment();
				if (element != null) {
					w = internalExpand(element, false);
					if (w instanceof Item) {
						newSelection.add((Item) w);
					}
				}
			}
		}
		setSelection(newSelection);

		// Although setting the selection in the control should reveal it,
		// setSelection may be a no-op if the selection is unchanged,
		// so explicitly reveal items in the selection here.
		// See bug 100565 for more details.
		if (reveal && newSelection.size() > 0) {
			// Iterate backwards so the first item in the list
			// is the one guaranteed to be visible
			for (int i = (newSelection.size()-1); i >= 0; i--) {
				showItem(newSelection.get(i));
			}
		}
	}

	/**
	 * Shows the given item.
	 *
	 * @param item
	 *            the item
	 */
	protected abstract void showItem(Item item);

	/**
	 * Updates the tree items to correspond to the child elements of the given
	 * parent element. If null is passed for the children, this method obtains
	 * them (only if needed).
	 *
	 * @param widget
	 *            the widget
	 * @param parent
	 *            the parent element
	 * @param elementChildren
	 *            the child elements, or null
	 * @deprecated this is no longer called by the framework
	 */
	@Deprecated
	protected void updateChildren(Widget widget, Object parent,
			Object[] elementChildren) {
		updateChildren(widget, parent, elementChildren, true);
	}

	/**
	 * Updates the tree items to correspond to the child elements of the given
	 * parent element. If null is passed for the children, this method obtains
	 * them (only if needed).
	 *
	 * @param widget
	 *            the widget
	 * @param parent
	 *            the parent element
	 * @param elementChildren
	 *            the child elements, or null
	 * @param updateLabels
	 *            <code>true</code> to update labels for existing elements,
	 *            <code>false</code> to only update labels as needed, assuming
	 *            that labels for existing elements are unchanged.
	 * @since 2.1
	 */
	private void updateChildren(Widget widget, Object parent,
			Object[] elementChildren, boolean updateLabels) {
		// optimization! prune collapsed subtrees
		if (widget instanceof Item) {
			Item ti = (Item) widget;
			if (!getExpanded(ti)) {
				if (optionallyPruneChildren(ti, parent)) {
					// children were pruned, nothing left to do
					return;
				}
				// The following code is being executed if children were not pruned.
				// This is (as of 3.5) only the case for CheckboxTreeViewer.
				Item[] its = getItems(ti);
				if (isExpandable(ti, null, parent)) {
					if (its.length == 0) {
						// need dummy node
						newItem(ti, SWT.NULL, -1);
						return;
					} else if (its.length == 1 && its[0].getData() == null) {
						// dummy node exists, nothing left to do
						return;
					}
					// else fall through to normal update code below
				} else {
					for (Item it : its) {
						if (it.getData() != null) {
							disassociate(it);
						}
						it.dispose();
					}
					// nothing left to do
					return;
				}
			}
		}

		// If the children weren't passed in, get them now since they're needed
		// below.
		if (elementChildren == null) {
			if (isTreePathContentProvider() && widget instanceof Item) {
				TreePath path = getTreePathFromItem((Item) widget);
				elementChildren = getSortedChildren(path);
			} else {
				elementChildren = getSortedChildren(parent);
			}
		}

		Control tree = getControl();

		// WORKAROUND
		int oldCnt = -1;
		if (widget == tree) {
			oldCnt = getItemCount(tree);
		}

		Item[] items = getChildren(widget);

		// save the expanded elements
		CustomHashtable expanded = newHashtable(CustomHashtable.DEFAULT_CAPACITY); // assume
																					// num
																					// expanded
																					// is
																					// small
		for (Item item : items) {
			if (getExpanded(item)) {
				Object element = item.getData();
				if (element != null) {
					expanded.put(element, element);
				}
			}
		}

		int min = Math.min(elementChildren.length, items.length);

		// dispose of surplus items, optimizing for the case where elements have
		// been deleted but not reordered, or all elements have been removed.
		int numItemsToDispose = items.length - min;
		if (numItemsToDispose > 0) {
			CustomHashtable children = newHashtable(elementChildren.length * 2);
			for (Object elementChild : elementChildren) {
				children.put(elementChild, elementChild);
			}
			int i = 0;
			while (numItemsToDispose > 0 && i < items.length) {
				Object data = items[i].getData();
				if (data == null || !children.containsKey(data)) {
					if (data != null) {
						disassociate(items[i]);
					}
					items[i].dispose();
					if (i + 1 < items.length) {
						// The components at positions i+1 through
						// items.length-1 in the source array are copied into
						// positions i through items.length-2
						System.arraycopy(items, i + 1, items, i, items.length - (i+1));
					}
					numItemsToDispose--;
				} else {
					i++;
				}
			}
		}

		// compare first min items, and update item if necessary
		// need to do it in two passes:
		// 1: disassociate old items
		// 2: associate new items
		// because otherwise a later disassociate can remove a mapping made for
		// a previous associate,
		// making the map inconsistent
		for (int i = 0; i < min; ++i) {
			Item item = items[i];
			Object oldElement = item.getData();
			if (oldElement != null) {
				Object newElement = elementChildren[i];
				if (newElement != oldElement) {
					if (equals(newElement, oldElement)) {
						// update the data to be the new element, since
						// although the elements
						// may be equal, they may still have different labels
						// or children
						Object data = item.getData();
						if (data != null) {
							unmapElement(data, item);
						}
						item.setData(newElement);
						mapElement(newElement, item);
					} else {
						disassociate(item);
						// Clear the text and image to force a label update
						item.setImage(null);
						item.setText("");//$NON-NLS-1$

					}
				}
			}
		}

		for (int i = 0; i < min; ++i) {
			Item item = items[i];
			Object newElement = elementChildren[i];
			if (item.getData() == null) {
				// old and new elements are not equal
				associate(newElement, item);
				updatePlus(item, newElement);
				updateItem(item, newElement);
			} else {
				// old and new elements are equal
				updatePlus(item, newElement);
				if (updateLabels) {
					updateItem(item, newElement);
				} else {
					associate(newElement, item);
				}
			}
		}

		// Restore expanded state for items that changed position.
		// Make sure setExpanded is called after updatePlus, since
		// setExpanded(false) fails if item has no children.
		// Need to call setExpanded for both expanded and unexpanded
		// cases since the expanded state can change either way.
		// This needs to be done in a second loop, see bug 148025.
		for (int i = 0; i < min; ++i) {
			Item item = items[i];
			Object newElement = elementChildren[i];
			setExpanded(item, expanded.containsKey(newElement));
		}

		// add any remaining elements
		if (min < elementChildren.length) {
			for (int i = min; i < elementChildren.length; ++i) {
				createTreeItem(widget, elementChildren[i], -1);
			}

			// Need to restore expanded state in a separate pass
			// because createTreeItem does not return the new item.
			// Avoid doing this unless needed.
			if (expanded.size() > 0) {
				// get the items again, to include the new items
				items = getChildren(widget);
				for (int i = min; i < elementChildren.length; ++i) {
					// Restore expanded state for items that changed position.
					// Make sure setExpanded is called after updatePlus (called
					// in createTreeItem), since
					// setExpanded(false) fails if item has no children.
					// Only need to call setExpanded if element was expanded
					// since new items are initially unexpanded.
					if (expanded.containsKey(elementChildren[i])) {
						setExpanded(items[i], true);
					}
				}
			}
		}

		// WORKAROUND
		if (widget == tree && oldCnt == 0 && getItemCount(tree) != 0) {
			// System.out.println("WORKAROUND setRedraw");
			tree.setRedraw(false);
			tree.setRedraw(true);
		}
	}

	/** Returns true if children were pruned */
	/*package*/ boolean optionallyPruneChildren(Item item, Object element) {
		// need a dummy node if element is expandable;
		// but try to avoid recreating the dummy node
		boolean needDummy = isExpandable(item, null, element);
		boolean haveDummy = false;
		// remove all children
		Item[] items = getItems(item);
		for (Item child : items) {
			if (child.getData() != null) {
				disassociate(child);
				child.dispose();
			} else {
				if (needDummy && !haveDummy) {
					haveDummy = true;
				} else {
					child.dispose();
				}
			}
		}
		if (needDummy && !haveDummy) {
			newItem(item, SWT.NULL, -1);
		}
		return true;
	}

	/**
	 * Not to be called by clients. Return the items to be refreshed as part of
	 * an update. elementChildren are the new elements.
	 *
	 * @param widget
	 * @param elementChildren
	 * @since 3.4
	 * @return Item[]
	 *
	 * @deprecated This method was inadvertently released as API but is not
	 *             intended to be called by clients.
	 */
	@Deprecated
	public Item[] getChildren(Widget widget,  Object[] elementChildren) {
		return getChildren(widget);
	}

	/**
	 * Updates the "+"/"-" icon of the tree node from the given element. It
	 * calls <code>isExpandable</code> to determine whether an element is
	 * expandable.
	 *
	 * @param item
	 *            the item
	 * @param element
	 *            the element
	 */
	protected void updatePlus(Item item, Object element) {
		boolean hasPlus = getItemCount(item) > 0;
		boolean needsPlus = isExpandable(item, null, element);
		boolean removeAll = false;
		boolean addDummy = false;
		Object data = item.getData();
		if (data != null && equals(element, data)) {
			// item shows same element
			if (hasPlus != needsPlus) {
				if (needsPlus) {
					addDummy = true;
				} else {
					removeAll = true;
				}
			}
		} else {
			// item shows different element
			removeAll = true;
			addDummy = needsPlus;

			// we cannot maintain expand state so collapse it
			setExpanded(item, false);
		}
		if (removeAll) {
			// remove all children
			Item[] items = getItems(item);
			for (Item item2 : items) {
				if (item2.getData() != null) {
					disassociate(item2);
				}
				item2.dispose();
			}
		}
		if (addDummy) {
			newItem(item, SWT.NULL, -1); // append a dummy
		}
	}

	/**
	 * Gets the expanded elements that are visible to the user. An expanded
	 * element is only visible if the parent is expanded.
	 *
	 * @return the visible expanded elements
	 * @since 2.0
	 */
	public Object[] getVisibleExpandedElements() {
		ArrayList<Object> v = new ArrayList<>();
		internalCollectVisibleExpanded(v, getControl());
		return v.toArray();
	}

	private void internalCollectVisibleExpanded(ArrayList<Object> result, Widget widget) {
		Item[] items = getChildren(widget);
		for (Item item : items) {
			if (getExpanded(item)) {
				Object data = item.getData();
				if (data != null) {
					result.add(data);
				}
				// Only recurse if it is expanded - if
				// not then the children aren't visible
				internalCollectVisibleExpanded(result, item);
			}
		}
	}

	/**
	 * Returns the tree path for the given item.
	 * @param item
	 * @return {@link TreePath}
	 *
	 * @since 3.2
	 */
	protected TreePath getTreePathFromItem(Item item) {
		LinkedList<Object> segments = new LinkedList<>();
		while (item != null) {
			Object segment = item.getData();
			Assert.isNotNull(segment);
			segments.addFirst(segment);
			item = getParentItem(item);
		}
		return new TreePath(segments.toArray());
	}

	/**
	 * The <code>AbstractTreeViewer</code> implementation of this method returns
	 * the result as an <code>ITreeSelection</code>.
	 * <p>
	 * Call {@link #getStructuredSelection()} instead to get an instance of
	 * <code>ITreeSelection</code> directly.
	 * </p>
	 * Subclasses do not typically override this method, but implement
	 * <code>getSelectionFromWidget(List)</code> instead. If they override this
	 * method, they should return an <code>ITreeSelection</code> as well.
	 *
	 * @since 3.2
	 */
	@Override
	public ISelection getSelection() {
		Control control = getControl();
		if (control == null || control.isDisposed()) {
			return TreeSelection.EMPTY;
		}
		Widget[] items = getSelection(getControl());
		ArrayList<TreePath> list = new ArrayList<>(items.length);
		for (Widget item : items) {
			if (item.getData() != null) {
				list.add(getTreePathFromItem((Item) item));
			}
		}
		return new TreeSelection(list.toArray(new TreePath[list.size()]), getComparer());
	}

	/**
	 * Returns the <code>ITreeSelection</code> of this viewer.
	 * <p>
	 * Subclasses whose {@link #getSelection()} specifies to return a more
	 * specific type should also override this method and return that type.
	 * </p>
	 *
	 * @return ITreeSelection
	 * @throws ClassCastException
	 *             if the selection of the viewer is not an instance of
	 *             ITreeSelection
	 * @since 3.11
	 */
	@Override
	public ITreeSelection getStructuredSelection() throws ClassCastException {
		ISelection selection = getSelection();
		if (selection instanceof ITreeSelection) {
			return (ITreeSelection) selection;
		}
		throw new ClassCastException(
				getClass().getName() + " should return an instance of ITreeSelection from its getSelection() method."); //$NON-NLS-1$
	}

	@Override
	protected void setSelectionToWidget(ISelection selection, boolean reveal) {
		if (selection instanceof ITreeSelection) {
			ITreeSelection treeSelection = (ITreeSelection) selection;
			setSelectionToWidget(Arrays.asList(treeSelection.getPaths()), reveal);
		} else {
			super.setSelectionToWidget(selection, reveal);
		}
	}

	/**
	 * Returns a list of tree paths corresponding to expanded nodes in this
	 * viewer's tree, including currently hidden ones that are marked as
	 * expanded but are under a collapsed ancestor.
	 * <p>
	 * This method is typically used when preserving the interesting state of a
	 * viewer; <code>setExpandedElements</code> is used during the restore.
	 * </p>
	 *
	 * @return the array of expanded tree paths
	 * @see #setExpandedElements
	 *
	 * @since 3.2
	 */
	public TreePath[] getExpandedTreePaths() {
		ArrayList<Item> items = new ArrayList<>();
		internalCollectExpandedItems(items, getControl());
		ArrayList<TreePath> result = new ArrayList<>(items.size());
		for (Item item : items) {
			TreePath treePath = getTreePathFromItem(item);
			if (treePath != null) {
				result.add(treePath);
			}
		}
		return result.toArray(new TreePath[items.size()]);
	}

	private boolean isTreePathContentProvider() {
		return getContentProvider() instanceof ITreePathContentProvider;
	}

	/**
	 * Inserts the given element as a new child element of the given parent
	 * element at the given position. If this viewer has a sorter, the position
	 * is ignored and the element is inserted at the correct position in the
	 * sort order.
	 * <p>
	 * This method should be called (by the content provider) when elements have
	 * been added to the model, in order to cause the viewer to accurately
	 * reflect the model. This method only affects the viewer, not the model.
	 * </p>
	 *
	 * @param parentElementOrTreePath
	 *            the parent element, or the tree path to the parent
	 * @param element
	 *            the element
	 * @param position
	 *            a 0-based position relative to the model, or -1 to indicate
	 *            the last position
	 *
	 * @since 3.2
	 */
	public void insert(Object parentElementOrTreePath, Object element,
			int position) {
		Assert.isNotNull(parentElementOrTreePath);
		Assert.isNotNull(element);
		if (checkBusy())
			return;
		if (getComparator() != null || hasFilters()) {
			add(parentElementOrTreePath, new Object[] { element });
			return;
		}
		Widget[] items;
		if (internalIsInputOrEmptyPath(parentElementOrTreePath)) {
			items = new Widget[] { getControl() };
		} else {
			items = internalFindItems(parentElementOrTreePath);
		}

		for (Widget widget : items) {
			if (widget instanceof Item) {
				Item item = (Item) widget;

				Item[] childItems = getChildren(item);
				if (getExpanded(item)
						|| (childItems.length > 0 && childItems[0].getData() != null)) {
					// item has real children, go ahead and add
					int insertionPosition = position;
					if (insertionPosition == -1) {
						insertionPosition = getItemCount(item);
					}

					createTreeItem(item, element, insertionPosition);
				} else {
					Object parentElement = parentElementOrTreePath;
					if (element instanceof TreePath)
						parentElement = ((TreePath) parentElement).getLastSegment();
					updatePlus(item, parentElement);
				}
			} else {
				int insertionPosition = position;
				if (insertionPosition == -1) {
					insertionPosition = getItemCount((Control) widget);
				}

				createTreeItem(widget, element, insertionPosition);
			}
		}
	}

	@Override
	protected Widget getColumnViewerOwner(int columnIndex) {
		// Return null by default
		return null;
	}

	/**
	 * This implementation of {@link #getItemAt(Point)} returns null to ensure
	 * API backwards compatibility. Subclasses should override.
	 *
	 * @since 3.3
	 */
	@Override
	protected Item getItemAt(Point point) {
		return null;
	}

	/**
	 * This implementation of {@link #createViewerEditor()} returns null to ensure
	 * API backwards compatibility. Subclasses should override.
	 *
	 * @since 3.3
	 */
	@Override
	protected ColumnViewerEditor createViewerEditor() {
		return null;
	}

	/**
	 * Returns the number of columns of this viewer.
	 * <p><b>Subclasses should overwrite this method, which has a default
	 * implementation (returning 0) for API backwards compatility reasons</b></p>
	 *
	 * @return the number of columns
	 *
	 * @since 3.3
	 */
	@Override
	protected int doGetColumnCount() {
		return 0;
	}


	/**
	 * This implementation of buildLabel handles tree paths as well as elements.
	 *
	 * @param updateLabel
	 *            the ViewerLabel to collect the result in
	 * @param elementOrPath
	 *            the element or tree path for which a label should be built
	 *
	 * @see org.eclipse.jface.viewers.StructuredViewer#buildLabel(org.eclipse.jface.viewers.ViewerLabel,
	 *      java.lang.Object)
	 */
	@Override
	protected void buildLabel(ViewerLabel updateLabel, Object elementOrPath) {
		Object element;
		if (elementOrPath instanceof TreePath) {
			TreePath path = (TreePath) elementOrPath;
			IBaseLabelProvider provider = getLabelProvider();
			if (provider instanceof ITreePathLabelProvider) {
				ITreePathLabelProvider pprov = (ITreePathLabelProvider) provider;
				buildLabel(updateLabel, path, pprov);
				return;
			}
			element = path.getLastSegment();
		} else {
			element = elementOrPath;
		}
		super.buildLabel(updateLabel, element);
	}

	/**
	 * Returns true if the given object is either the input or an empty tree path.
	 *
	 * @param elementOrTreePath an element which could either be the viewer's input, or a tree path
	 *
	 * @return <code>true</code> if the given object is either the input or an empty tree path,
	 * <code>false</code> otherwise.
	 * @since 3.3
	 */
	final protected boolean internalIsInputOrEmptyPath(final Object elementOrTreePath) {
		if (elementOrTreePath.equals(getRoot()))
			return true;
		if (!(elementOrTreePath instanceof TreePath))
			return false;
		return ((TreePath) elementOrTreePath).getSegmentCount() == 0;
	}

	/*
	 * Subclasses should implement
	 */
	@Override
	protected ViewerRow getViewerRowFromItem(Widget item) {
		return null;
	}

	/**
	 * Instructs {@link #isExpandable(Object)} to consult filters to more accurately
	 * determine if an item can be expanded.
	 * <p>
	 * Setting this value to <code>true</code> will affect performance of the tree
	 * viewer.
	 * </p><p>
	 * To improve performance, by default the tree viewer does not consult filters when
	 * determining if a tree node could be expanded.
	 * </p>
	 * @param checkFilters <code>true</code> to instruct tree viewer to consult filters
	 * @see #isExpandable(Object)
	 * @since 3.8
	 */
	public void setExpandPreCheckFilters(boolean checkFilters) {
		if (checkFilters != isExpandableCheckFilters) {
			this.isExpandableCheckFilters = checkFilters;
			refresh();
		}
	}

}
