Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2020-04-10 05:57:02 +0000
committerEike Stepper2020-04-10 05:57:02 +0000
commitfed3b44a5bc48864cb40184128feb66559c7648c (patch)
tree53ce813a3ef53f3b96eb5c7ead5144d82f863284
parent92caf4e4d570e2a552d0508b19f0a52b1c4e9509 (diff)
downloadcdo-fed3b44a5bc48864cb40184128feb66559c7648c.tar.gz
cdo-fed3b44a5bc48864cb40184128feb66559c7648c.tar.xz
cdo-fed3b44a5bc48864cb40184128feb66559c7648c.zip
[561973] Make CDO Editor node expansion asynchronous and resilient to failures
https://bugs.eclipse.org/bugs/show_bug.cgi?id=561973
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/bundle/OM.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutContentProvider.java687
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutEditorInput.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutLabelProvider.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutState.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutStateManager.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/CDORepositoryItemProvider.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/wizards/MasterRepositoryController.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java670
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/RunnableViewerRefresh.java (renamed from plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutViewerRefresh.java)6
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/ViewerUtil.java (renamed from plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/ViewerUtil.java)8
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java109
12 files changed, 891 insertions, 608 deletions
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/bundle/OM.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/bundle/OM.java
index 0a2d70a253..f7a446a19b 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/bundle/OM.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/bundle/OM.java
@@ -52,7 +52,7 @@ public abstract class OM
PREFS.init("PREF_REPOSITORY_TIMEOUT_DISABLED", false); //$NON-NLS-1$
public static final OMPreference<Boolean> PREF_REMEMBER_OPEN_EDITORS = //
- PREFS.init("PREF_REMEMBER_OPEN_EDITORS", false); //$NON-NLS-1$
+ PREFS.init("PREF_REMEMBER_OPEN_EDITORS", true); //$NON-NLS-1$
public static final OMPreference<Integer> PREF_DASHBOARD_HEIGHT = //
PREFS.init("PREF_DASHBOARD_HEIGHT", 0); //$NON-NLS-1$
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutContentProvider.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutContentProvider.java
index 8503036f5a..c654b54b96 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutContentProvider.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutContentProvider.java
@@ -11,11 +11,6 @@
package org.eclipse.emf.cdo.explorer.ui.checkouts;
import org.eclipse.emf.cdo.CDOElement;
-import org.eclipse.emf.cdo.CDOObject;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.explorer.CDOExplorerManager;
@@ -24,33 +19,19 @@ import org.eclipse.emf.cdo.explorer.CDOExplorerUtil;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckoutManager;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckoutManager.CheckoutStateEvent;
-import org.eclipse.emf.cdo.explorer.ui.ViewerUtil;
import org.eclipse.emf.cdo.explorer.ui.bundle.OM;
import org.eclipse.emf.cdo.explorer.ui.checkouts.actions.OpenWithActionProvider;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
+import org.eclipse.emf.cdo.internal.ui.CDOContentProvider;
+import org.eclipse.emf.cdo.internal.ui.RunnableViewerRefresh;
+import org.eclipse.emf.cdo.internal.ui.ViewerUtil;
import org.eclipse.emf.cdo.ui.CDOItemProvider;
-import org.eclipse.emf.cdo.util.CDOUtil;
-import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.net4j.util.container.IContainerEvent;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
-import org.eclipse.net4j.util.lifecycle.LifecycleException;
-import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
-import org.eclipse.net4j.util.ui.UIUtil;
-import org.eclipse.net4j.util.ui.views.ItemProvider;
-import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.InternalEObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
-import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
-import org.eclipse.emf.edit.provider.ItemProviderAdapter;
-import org.eclipse.emf.spi.cdo.InternalCDOObject;
-import org.eclipse.emf.spi.cdo.InternalCDOView;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
@@ -60,7 +41,6 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -68,7 +48,6 @@ import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
@@ -78,7 +57,6 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
@@ -94,30 +72,23 @@ import org.eclipse.ui.views.properties.PropertySheet;
import org.eclipse.ui.views.properties.PropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
/**
* @author Eike Stepper
*/
-public class CDOCheckoutContentProvider implements ICommonContentProvider, IPropertySourceProvider, IOpenListener
+public class CDOCheckoutContentProvider extends CDOContentProvider<CDOCheckout> implements ICommonContentProvider, IPropertySourceProvider, IOpenListener
{
- private static final Map<String, CDOCheckoutContentProvider> INSTANCES = new HashMap<>();
-
- private static final Set<Object> LOADING_OBJECTS = new HashSet<>();
-
- private static final Method GET_CHILDREN_FEATURES_METHOD = getMethod(ItemProviderAdapter.class, "getChildrenFeatures", Object.class);
+ public static final String PROJECT_EXPLORER_ID = "org.eclipse.ui.navigator.ProjectExplorer";
- private static final Method FIND_ITEM_METHOD = getMethod(StructuredViewer.class, "findItem", Object.class);
+ private static final Map<String, CDOCheckoutContentProvider> INSTANCES = new HashMap<>();
private static final CDOCheckoutManager CHECKOUT_MANAGER = CDOExplorerUtil.getCheckoutManager();
@@ -126,7 +97,7 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
@Override
public void notifyEvent(IEvent event)
{
- CDOCheckoutViewerRefresh viewerRefresh = stateManager.getViewerRefresh();
+ RunnableViewerRefresh viewerRefresh = stateManager.getViewerRefresh();
if (event instanceof IContainerEvent)
{
@@ -141,23 +112,23 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
if (state == CDOCheckout.State.Opening)
{
// Trigger hasChildren().
- ViewerUtil.refresh(viewer, checkout);
+ ViewerUtil.refresh(getViewer(), checkout);
// Trigger getChildren().
- ViewerUtil.expand(viewer, checkout, true);
+ ViewerUtil.expand(getViewer(), checkout, true);
}
else
{
if (state == CDOCheckout.State.Closed)
{
- ViewerUtil.expand(viewer, checkout, false);
+ ViewerUtil.expand(getViewer(), checkout, false);
}
viewerRefresh.addNotification(checkout, true, true);
if (state == CDOCheckout.State.Open)
{
- ViewerUtil.expand(viewer, checkout, true);
+ ViewerUtil.expand(getViewer(), checkout, true);
}
updatePropertySheetPage(checkout);
@@ -203,10 +174,11 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
PropertySheet propertySheet = getPropertySheet(workbenchPage);
if (propertySheet != null)
{
- final IPage currentPage = propertySheet.getCurrentPage();
+ IPage currentPage = propertySheet.getCurrentPage();
if (currentPage instanceof PropertySheetPage || currentPage instanceof TabbedPropertySheetPage)
{
- final Control control = viewer.getControl();
+ TreeViewer viewer = getViewer();
+ Control control = viewer.getControl();
if (!control.isDisposed())
{
control.getDisplay().asyncExec(new Runnable()
@@ -269,16 +241,8 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
private final CDOCheckoutStateManager stateManager = new CDOCheckoutStateManager(this);
- private final Map<Object, Object[]> childrenCache = new ConcurrentHashMap<>();
-
private String viewerID;
- private TreeViewer viewer;
-
- private Object input;
-
- public static final String PROJECT_EXPLORER_ID = "org.eclipse.ui.navigator.ProjectExplorer";
-
public CDOCheckoutContentProvider()
{
}
@@ -327,497 +291,54 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
return stateManager;
}
- public final TreeViewer getViewer()
- {
- return viewer;
- }
-
@Override
public void inputChanged(Viewer newViewer, Object oldInput, Object newInput)
{
- TreeViewer newTreeViewer = null;
- if (newViewer instanceof TreeViewer)
- {
- newTreeViewer = (TreeViewer)newViewer;
- }
-
- if (newTreeViewer != viewer)
- {
- if (viewer != null)
- {
- viewer.removeOpenListener(this);
- }
-
- viewer = newTreeViewer;
-
- if (viewer != null)
- {
- viewer.addOpenListener(this);
- }
- }
-
- input = newInput;
- stateManager.inputChanged(newTreeViewer, oldInput, newInput);
- }
-
- public Object getInput()
- {
- return input;
- }
-
- @Override
- public Object[] getElements(Object object)
- {
- return getChildren(object);
+ super.inputChanged(newViewer, oldInput, newInput);
+ stateManager.inputChanged(getViewer(), oldInput, newInput);
}
@Override
public boolean hasChildren(Object object)
{
- try
- {
- if (object instanceof IResource)
- {
- if (object instanceof IWorkspaceRoot)
- {
- return !CHECKOUT_MANAGER.isEmpty();
- }
-
- return false;
- }
-
- if (object instanceof ViewerUtil.Pending)
- {
- return false;
- }
-
- if (object instanceof CDOCheckout)
- {
- CDOCheckout checkout = (CDOCheckout)object;
- switch (checkout.getState())
- {
- case Closing:
- case Closed:
- return false;
-
- case Opening:
- // This must be the ViewerUtil.Pending element.
- return true;
-
- case Open:
- object = checkout.getRootObject();
- break;
- }
- }
-
- if (object instanceof CDOElement)
- {
- CDOElement checkoutElement = (CDOElement)object;
- return checkoutElement.hasChildren();
- }
-
- if (GET_CHILDREN_FEATURES_METHOD != null && object instanceof EObject)
- {
- EObject eObject = (EObject)object;
-
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (cdoObject != null)
- {
- InternalCDORevision revision = cdoObject.cdoRevision(false);
- if (revision != null)
- {
- try
- {
- ITreeItemContentProvider provider = (ITreeItemContentProvider)stateManager.adapt(object, ITreeItemContentProvider.class);
- if (provider instanceof ItemProviderAdapter)
- {
- return hasChildren(cdoObject, revision, (ItemProviderAdapter)provider);
- }
- }
- catch (Exception ex)
- {
- //$FALL-THROUGH$
- }
- }
- }
- }
-
- ITreeContentProvider contentProvider = stateManager.getContentProvider(object);
- if (contentProvider != null)
- {
- return contentProvider.hasChildren(object);
- }
- }
- catch (LifecycleException ex)
+ if (object instanceof IResource)
{
- //$FALL-THROUGH$
- }
- catch (RuntimeException ex)
- {
- if (LifecycleUtil.isActive(object))
+ if (object instanceof IWorkspaceRoot)
{
- throw ex;
+ return !CHECKOUT_MANAGER.isEmpty();
}
- //$FALL-THROUGH$
+ return false;
}
- return false;
+ return super.hasChildren(object);
}
@Override
public Object[] getChildren(Object object)
{
- try
+ if (object instanceof IResource)
{
- if (object instanceof IResource)
- {
- if (object instanceof IWorkspaceRoot)
- {
- return CHECKOUT_MANAGER.getCheckouts();
- }
-
- return ViewerUtil.NO_CHILDREN;
- }
-
- if (object instanceof ViewerUtil.Pending)
+ if (object instanceof IWorkspaceRoot)
{
- return ViewerUtil.NO_CHILDREN;
+ return CHECKOUT_MANAGER.getCheckouts();
}
- if (object instanceof CDOElement)
- {
- CDOElement checkoutElement = (CDOElement)object;
- return checkoutElement.getChildren();
- }
-
- final Object originalObject = object;
- Object[] children = childrenCache.remove(originalObject);
- if (children != null)
- {
- return children;
- }
-
- CDOCheckout openingCheckout = null;
- CDOCheckout checkout = null;
-
- if (object instanceof CDOCheckout)
- {
- checkout = (CDOCheckout)object;
-
- switch (checkout.getState())
- {
- case Closing:
- case Closed:
- return ViewerUtil.NO_CHILDREN;
-
- case Opening:
- openingCheckout = checkout;
- break;
-
- case Open:
- object = checkout.getRootObject();
- break;
- }
- }
-
- final Object finalObject = object;
- final CDOCheckout finalOpeningCheckout = openingCheckout;
-
- final ITreeContentProvider contentProvider = stateManager.getContentProvider(finalObject);
- if (contentProvider == null)
- {
- return ItemProvider.NO_ELEMENTS;
- }
-
- final List<CDORevision> loadedRevisions = new ArrayList<>();
- final List<CDOID> missingIDs = new ArrayList<>();
-
- if (openingCheckout == null)
- {
- children = determineChildRevisions(object, loadedRevisions, missingIDs);
- if (children != null)
- {
- return CDOCheckoutContentModifier.Registry.INSTANCE.modifyChildren(object, children);
- }
- }
-
- boolean firstLoad;
- synchronized (LOADING_OBJECTS)
- {
- firstLoad = LOADING_OBJECTS.add(originalObject);
- }
-
- if (firstLoad || finalOpeningCheckout == null)
- {
- Job job = new Job("Load " + finalObject)
- {
- @Override
- protected IStatus run(IProgressMonitor monitor)
- {
- try
- {
- if (finalOpeningCheckout != null)
- {
- finalOpeningCheckout.open();
- determineChildRevisions(finalObject, loadedRevisions, missingIDs);
- }
-
- if (!missingIDs.isEmpty())
- {
- CDOObject cdoObject = getCDOObject((EObject)finalObject);
- CDOView view = cdoObject.cdoView();
- CDORevisionManager revisionManager = view.getSession().getRevisionManager();
-
- List<CDORevision> revisions = revisionManager.getRevisions(missingIDs, view, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
- loadedRevisions.addAll(revisions);
- }
-
- Object[] children = contentProvider.getChildren(finalObject);
-
- // Adjust possible legacy adapters.
- for (int i = 0; i < children.length; i++)
- {
- Object child = children[i];
- if (child instanceof InternalCDOObject)
- {
- InternalCDOObject cdoObject = (InternalCDOObject)child;
- InternalEObject instance = cdoObject.cdoInternalInstance();
- if (instance != cdoObject)
- {
- children[i] = instance;
- }
- }
- }
-
- children = CDOCheckoutContentModifier.Registry.INSTANCE.modifyChildren(finalObject, children);
- childrenCache.put(originalObject, children);
- }
- catch (final Exception ex)
- {
- childrenCache.remove(originalObject);
-
- if (finalOpeningCheckout != null)
- {
- finalOpeningCheckout.close();
- }
-
- OM.LOG.error(ex);
-
- final Control control = viewer.getControl();
- if (!control.isDisposed())
- {
- UIUtil.getDisplay().asyncExec(new Runnable()
- {
- @Override
- public void run()
- {
- try
- {
- if (!control.isDisposed())
- {
- Shell shell = control.getShell();
- String title = (finalOpeningCheckout != null ? "Open" : "Load") + " Error";
- MessageDialog.openError(shell, title, ex.getMessage());
- }
- }
- catch (Exception ex)
- {
- OM.LOG.error(ex);
- }
- }
- });
- }
- }
-
- CDOCheckoutViewerRefresh viewerRefresh = stateManager.getViewerRefresh();
- viewerRefresh.addNotification(originalObject, true, true, new Runnable()
- {
- @Override
- public void run()
- {
- synchronized (LOADING_OBJECTS)
- {
- LOADING_OBJECTS.remove(originalObject);
- }
- }
- });
-
- return Status.OK_STATUS;
- }
- };
-
- job.schedule();
- }
-
- if (FIND_ITEM_METHOD != null)
- {
- try
- {
- Object widget = FIND_ITEM_METHOD.invoke(viewer, originalObject);
- if (widget instanceof TreeItem)
- {
- TreeItem item = (TreeItem)widget;
- TreeItem[] childItems = item.getItems();
-
- int childCount = childItems.length;
- if (childCount != 0)
- {
- List<Object> result = new ArrayList<>();
- for (int i = 0; i < childCount; i++)
- {
- TreeItem childItem = childItems[i];
- Object child = childItem.getData();
- if (child != null)
- {
- result.add(child);
- }
- }
-
- int size = result.size();
- if (size != 0)
- {
- return result.toArray(new Object[size]);
- }
- }
- }
- }
- catch (Exception ex)
- {
- //$FALL-THROUGH$
- }
- }
-
- String text = "Loading...";
- if (finalOpeningCheckout != null)
- {
- text = "Opening...";
- }
-
- return new Object[] { new ViewerUtil.Pending(originalObject, text) };
+ return ViewerUtil.NO_CHILDREN;
}
- catch (LifecycleException ex)
- {
- //$FALL-THROUGH$
- }
- catch (RuntimeException ex)
- {
- if (LifecycleUtil.isActive(object))
- {
- throw ex;
- }
- //$FALL-THROUGH$
- }
-
- return ItemProvider.NO_ELEMENTS;
- }
-
- private Object[] determineChildRevisions(Object object, List<CDORevision> loadedRevisions, List<CDOID> missingIDs)
- {
- if (GET_CHILDREN_FEATURES_METHOD != null && object instanceof EObject)
- {
- EObject eObject = (EObject)object;
-
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (cdoObject != null)
- {
- InternalCDORevision revision = cdoObject.cdoRevision(false);
- if (revision != null)
- {
- try
- {
- ITreeItemContentProvider provider = (ITreeItemContentProvider)stateManager.adapt(object, ITreeItemContentProvider.class);
- if (provider instanceof ItemProviderAdapter)
- {
- determineChildRevisions(cdoObject, revision, (ItemProviderAdapter)provider, loadedRevisions, missingIDs);
-
- if (missingIDs.isEmpty())
- {
- // All revisions are cached. Just return the objects without server round-trips.
- ITreeContentProvider contentProvider = stateManager.getContentProvider(object);
- if (contentProvider != null)
- {
- return contentProvider.getChildren(object);
- }
- }
- }
- }
- catch (Exception ex)
- {
- //$FALL-THROUGH$
- }
- }
- }
- }
-
- return null;
+ return super.getChildren(object);
}
@Override
public Object getParent(Object object)
{
- try
- {
- if (object instanceof CDOCheckout)
- {
- return ResourcesPlugin.getWorkspace().getRoot();
- }
-
- if (object instanceof ViewerUtil.Pending)
- {
- return ((ViewerUtil.Pending)object).getParent();
- }
-
- if (object instanceof CDOElement)
- {
- CDOElement checkoutElement = (CDOElement)object;
- return checkoutElement.getParent();
- }
-
- if (object instanceof EObject)
- {
- EObject eObject = CDOUtil.getEObject((EObject)object);
-
- CDOElement element = CDOElement.getFor(eObject);
- if (element != null)
- {
- return element;
- }
-
- ITreeContentProvider contentProvider = stateManager.getContentProvider(object);
- if (contentProvider != null)
- {
- Object parent = contentProvider.getParent(object);
- if (parent instanceof EObject)
- {
- EObject eParent = (EObject)parent;
- Adapter adapter = EcoreUtil.getAdapter(eParent.eAdapters(), CDOCheckout.class);
- if (adapter != null)
- {
- return adapter;
- }
- }
-
- return parent;
- }
- }
- }
- catch (LifecycleException ex)
+ if (object instanceof CDOCheckout)
{
- //$FALL-THROUGH$
- }
- catch (RuntimeException ex)
- {
- if (LifecycleUtil.isActive(object))
- {
- throw ex;
- }
-
- //$FALL-THROUGH$
+ return ResourcesPlugin.getWorkspace().getRoot();
}
- return null;
+ return super.getParent(object);
}
@Override
@@ -834,7 +355,8 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
public void selectObjects(final Object... objects)
{
- final Control control = viewer.getControl();
+ TreeViewer viewer = getViewer();
+ Control control = viewer.getControl();
if (!control.isDisposed())
{
final long end = System.currentTimeMillis() + 5000L;
@@ -943,121 +465,96 @@ public class CDOCheckoutContentProvider implements ICommonContentProvider, IProp
}
}
- private IWorkbenchPage getWorkbenchPage()
+ @Override
+ protected void hookViewer(TreeViewer viewer)
{
- if (viewer instanceof CommonViewer)
- {
- CommonViewer commonViewer = (CommonViewer)viewer;
- return commonViewer.getCommonNavigator().getSite().getPage();
- }
+ viewer.addOpenListener(this);
+ }
- return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ @Override
+ protected void unhookViewer(TreeViewer viewer)
+ {
+ viewer.removeOpenListener(this);
}
- private static InternalCDOObject getCDOObject(EObject eObject)
+ @Override
+ protected Object adapt(Object target, Object type)
{
- return (InternalCDOObject)CDOUtil.getCDOObject(eObject, false);
+ return stateManager.adapt(target, type);
}
- private static boolean hasChildren(InternalCDOObject cdoObject, InternalCDORevision revision, ItemProviderAdapter provider) throws Exception
+ @Override
+ protected Object[] modifyChildren(Object parent, Object[] children)
{
- for (EStructuralFeature feature : getChildrenFeatures(cdoObject, provider))
- {
- if (feature.isMany())
- {
- if (!revision.isEmpty(feature))
- {
- return true;
- }
- }
- else if (revision.getValue(feature) != null)
- {
- return true;
- }
- }
+ return CDOCheckoutContentModifier.Registry.INSTANCE.modifyChildren(parent, children);
+ }
- return false;
+ @Override
+ protected ITreeContentProvider getContentProvider(Object object)
+ {
+ return stateManager.getContentProvider(object);
}
- private static void determineChildRevisions(InternalCDOObject cdoObject, InternalCDORevision revision, ItemProviderAdapter provider,
- List<CDORevision> loadedRevisions, List<CDOID> missingIDs) throws Exception
+ @Override
+ protected RunnableViewerRefresh getViewerRefresh()
{
- InternalCDOView view = cdoObject.cdoView();
- InternalCDORevisionCache revisionCache = view.getSession().getRevisionManager().getCache();
+ return stateManager.getViewerRefresh();
+ }
- for (EStructuralFeature feature : getChildrenFeatures(cdoObject, provider))
- {
- if (feature.isMany())
- {
- CDOList list = revision.getListOrNull(feature);
- if (list != null)
- {
- for (Object object : list)
- {
- determineChildRevision(loadedRevisions, missingIDs, view, revisionCache, object);
- }
- }
- }
- else
- {
- Object value = revision.getValue(feature);
- determineChildRevision(loadedRevisions, missingIDs, view, revisionCache, value);
- }
- }
+ @Override
+ protected boolean isContext(Object object)
+ {
+ return object instanceof CDOCheckout;
}
- private static void determineChildRevision(List<CDORevision> loadedRevisions, List<CDOID> missingIDs, InternalCDOView view, InternalCDORevisionCache cache,
- Object object)
+ @Override
+ protected ContextState getContextState(CDOCheckout checkout)
{
- if (object instanceof CDOID)
+ switch (checkout.getState())
{
- CDOID id = (CDOID)object;
- CDORevision childRevision = cache.getRevision(id, view);
- if (childRevision != null)
- {
- loadedRevisions.add(childRevision);
- }
- else
- {
- missingIDs.add(id);
- }
+ case Closing:
+ case Closed:
+ return ContextState.Closed;
+
+ case Opening:
+ return ContextState.Opening;
+
+ case Open:
+ return ContextState.Open;
+
+ default:
+ throw new IllegalStateException("Unexpected checkout state: " + checkout);
}
}
- @SuppressWarnings("unchecked")
- private static Collection<? extends EStructuralFeature> getChildrenFeatures(InternalCDOObject cdoObject, ItemProviderAdapter provider) throws Exception
+ @Override
+ protected void openContext(CDOCheckout checkout)
{
- return (Collection<? extends EStructuralFeature>)GET_CHILDREN_FEATURES_METHOD.invoke(provider, cdoObject);
+ checkout.open();
}
- private static Method getMethod(Class<?> c, String methodName, Class<?>... parameterTypes)
+ @Override
+ protected void closeContext(CDOCheckout checkout)
{
- try
- {
- Method method = c.getDeclaredMethod(methodName, parameterTypes);
- method.setAccessible(true);
- return method;
- }
- catch (Throwable ex)
- {
- return null;
- }
+ checkout.close();
}
- private static boolean isObjectLoading(Object... objects)
+ @Override
+ protected Object getRootObject(CDOCheckout checkout)
{
- synchronized (LOADING_OBJECTS)
- {
- for (Object object : objects)
- {
- if (LOADING_OBJECTS.contains(object))
- {
- return true;
- }
- }
+ return checkout.getRootObject();
+ }
- return false;
+ private IWorkbenchPage getWorkbenchPage()
+ {
+ TreeViewer viewer = getViewer();
+ if (viewer instanceof CommonViewer)
+ {
+ CommonViewer commonViewer = (CommonViewer)viewer;
+ return commonViewer.getCommonNavigator().getSite().getPage();
}
+
+ return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
}
public static TreeViewer createTreeViewer(Composite container)
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutEditorInput.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutEditorInput.java
index 1ed275bc07..c1574b4db7 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutEditorInput.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutEditorInput.java
@@ -24,6 +24,7 @@ import org.eclipse.emf.cdo.util.CDOURIUtil;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;
+import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.om.monitor.EclipseMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
@@ -58,6 +59,7 @@ public class CDOCheckoutEditorInput extends PlatformObject implements CDOEditorI
public CDOCheckoutEditorInput(URI uri)
{
+ CheckUtil.checkArg(uri, "uri is null");
this.uri = uri;
}
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutLabelProvider.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutLabelProvider.java
index 113545c88c..ea479db7b2 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutLabelProvider.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutLabelProvider.java
@@ -11,7 +11,7 @@
package org.eclipse.emf.cdo.explorer.ui.checkouts;
import org.eclipse.emf.cdo.explorer.CDOExplorerElement;
-import org.eclipse.emf.cdo.explorer.ui.ViewerUtil;
+import org.eclipse.emf.cdo.internal.ui.ViewerUtil;
import org.eclipse.emf.cdo.transfer.CDOTransferElement;
import org.eclipse.net4j.util.StringUtil;
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutState.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutState.java
index f4943d57f3..05f54b52c0 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutState.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutState.java
@@ -16,8 +16,8 @@ import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.explorer.CDOExplorerUtil;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckoutManager;
-import org.eclipse.emf.cdo.explorer.ui.ViewerUtil;
import org.eclipse.emf.cdo.explorer.ui.bundle.OM;
+import org.eclipse.emf.cdo.internal.ui.ViewerUtil;
import org.eclipse.emf.cdo.internal.ui.editor.CDOEditor;
import org.eclipse.emf.cdo.ui.CDOEditorUtil;
import org.eclipse.emf.cdo.ui.CDOLabelDecorator;
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutStateManager.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutStateManager.java
index 1ad21940fa..23a1cb650a 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutStateManager.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutStateManager.java
@@ -14,6 +14,7 @@ import org.eclipse.emf.cdo.explorer.CDOExplorerUtil;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout;
import org.eclipse.emf.cdo.explorer.ui.checkouts.CDOCheckoutState.ContentProvider;
import org.eclipse.emf.cdo.explorer.ui.checkouts.CDOCheckoutState.LabelProvider;
+import org.eclipse.emf.cdo.internal.ui.RunnableViewerRefresh;
import org.eclipse.net4j.util.lifecycle.LifecycleException;
@@ -38,7 +39,7 @@ public final class CDOCheckoutStateManager
private final CDOCheckoutContentProvider mainContentProvider;
- private CDOCheckoutViewerRefresh viewerRefresh;
+ private RunnableViewerRefresh viewerRefresh;
public CDOCheckoutStateManager(CDOCheckoutContentProvider mainContentProvider)
{
@@ -55,7 +56,7 @@ public final class CDOCheckoutStateManager
return resourceManager;
}
- public CDOCheckoutViewerRefresh getViewerRefresh()
+ public RunnableViewerRefresh getViewerRefresh()
{
return viewerRefresh;
}
@@ -98,7 +99,7 @@ public final class CDOCheckoutStateManager
public void inputChanged(TreeViewer newTreeViewer, Object oldInput, Object newInput)
{
- viewerRefresh = new CDOCheckoutViewerRefresh(newTreeViewer);
+ viewerRefresh = new RunnableViewerRefresh(newTreeViewer);
for (CDOCheckoutState state : getStates())
{
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/CDORepositoryItemProvider.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/CDORepositoryItemProvider.java
index ea95b72f15..17aecfa5cb 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/CDORepositoryItemProvider.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/CDORepositoryItemProvider.java
@@ -19,8 +19,8 @@ import org.eclipse.emf.cdo.explorer.repositories.CDORepository.IDGeneration;
import org.eclipse.emf.cdo.explorer.repositories.CDORepository.VersioningMode;
import org.eclipse.emf.cdo.explorer.repositories.CDORepositoryManager;
import org.eclipse.emf.cdo.explorer.repositories.CDORepositoryManager.RepositoryConnectionEvent;
-import org.eclipse.emf.cdo.explorer.ui.ViewerUtil;
import org.eclipse.emf.cdo.explorer.ui.bundle.OM;
+import org.eclipse.emf.cdo.internal.ui.ViewerUtil;
import org.eclipse.emf.cdo.ui.shared.SharedIcons;
import org.eclipse.net4j.util.container.IContainer;
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/wizards/MasterRepositoryController.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/wizards/MasterRepositoryController.java
index b771327e82..d9059cb155 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/wizards/MasterRepositoryController.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/repositories/wizards/MasterRepositoryController.java
@@ -16,8 +16,8 @@ import org.eclipse.emf.cdo.admin.CDOAdminClientRepository;
import org.eclipse.emf.cdo.admin.CDOAdminClientUtil;
import org.eclipse.emf.cdo.explorer.repositories.CDORepository.IDGeneration;
import org.eclipse.emf.cdo.explorer.repositories.CDORepository.VersioningMode;
-import org.eclipse.emf.cdo.explorer.ui.ViewerUtil;
import org.eclipse.emf.cdo.explorer.ui.bundle.OM;
+import org.eclipse.emf.cdo.internal.ui.ViewerUtil;
import org.eclipse.emf.cdo.net4j.CDONet4jSession;
import org.eclipse.emf.cdo.net4j.CDONet4jSessionConfiguration;
import org.eclipse.emf.cdo.net4j.CDONet4jUtil;
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java
new file mode 100644
index 0000000000..13311c66ac
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2015, 2016, 2018, 2019 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.ui;
+
+import org.eclipse.emf.cdo.CDOElement;
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.internal.ui.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
+import org.eclipse.emf.cdo.util.CDOUtil;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.net4j.util.lifecycle.LifecycleException;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.ui.UIUtil;
+import org.eclipse.net4j.util.ui.views.ItemProvider;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+import org.eclipse.emf.edit.provider.ItemProviderAdapter;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TreeItem;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDOContentProvider<CONTEXT> implements ITreeContentProvider
+{
+ private static final Set<Object> LOADING_OBJECTS = new HashSet<>();
+
+ private static final Method GET_CHILDREN_FEATURES_METHOD = getMethod(ItemProviderAdapter.class, "getChildrenFeatures", Object.class);
+
+ private static final Method FIND_ITEM_METHOD = getMethod(StructuredViewer.class, "findItem", Object.class);
+
+ private final Map<Object, Object[]> childrenCache = new ConcurrentHashMap<>();
+
+ private TreeViewer viewer;
+
+ private Object input;
+
+ public CDOContentProvider()
+ {
+ }
+
+ public final TreeViewer getViewer()
+ {
+ return viewer;
+ }
+
+ @Override
+ public void inputChanged(Viewer newViewer, Object oldInput, Object newInput)
+ {
+ TreeViewer newTreeViewer = null;
+ if (newViewer instanceof TreeViewer)
+ {
+ newTreeViewer = (TreeViewer)newViewer;
+ }
+
+ if (newTreeViewer != viewer)
+ {
+ if (viewer != null)
+ {
+ unhookViewer(viewer);
+ }
+
+ viewer = newTreeViewer;
+
+ if (viewer != null)
+ {
+ hookViewer(viewer);
+ }
+ }
+
+ input = newInput;
+ }
+
+ public Object getInput()
+ {
+ return input;
+ }
+
+ @Override
+ public Object[] getElements(Object object)
+ {
+ return getChildren(object);
+ }
+
+ @Override
+ public boolean hasChildren(Object object)
+ {
+ try
+ {
+ if (object instanceof ViewerUtil.Pending)
+ {
+ return false;
+ }
+
+ if (isContext(object))
+ {
+ @SuppressWarnings("unchecked")
+ CONTEXT context = (CONTEXT)object;
+
+ switch (getContextState(context))
+ {
+ case Closed:
+ return false;
+
+ case Opening:
+ // This must be the ViewerUtil.Pending element.
+ return true;
+
+ case Open:
+ object = getRootObject(context);
+ break;
+ }
+ }
+
+ if (object instanceof CDOElement)
+ {
+ CDOElement checkoutElement = (CDOElement)object;
+ return checkoutElement.hasChildren();
+ }
+
+ if (GET_CHILDREN_FEATURES_METHOD != null && object instanceof EObject)
+ {
+ EObject eObject = (EObject)object;
+
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (cdoObject != null)
+ {
+ InternalCDORevision revision = cdoObject.cdoRevision(false);
+ if (revision != null)
+ {
+ try
+ {
+ ITreeItemContentProvider provider = (ITreeItemContentProvider)adapt(object, ITreeItemContentProvider.class);
+ if (provider instanceof ItemProviderAdapter)
+ {
+ return hasChildren(cdoObject, revision, (ItemProviderAdapter)provider);
+ }
+ }
+ catch (Exception ex)
+ {
+ //$FALL-THROUGH$
+ }
+ }
+ }
+ }
+
+ ITreeContentProvider contentProvider = getContentProvider(object);
+ if (contentProvider != null)
+ {
+ return contentProvider.hasChildren(object);
+ }
+ }
+ catch (LifecycleException ex)
+ {
+ //$FALL-THROUGH$
+ }
+ catch (RuntimeException ex)
+ {
+ if (LifecycleUtil.isActive(object))
+ {
+ throw ex;
+ }
+
+ //$FALL-THROUGH$
+ }
+
+ return false;
+ }
+
+ @Override
+ public Object[] getChildren(Object object)
+ {
+ try
+ {
+ if (object instanceof ViewerUtil.Pending)
+ {
+ return ViewerUtil.NO_CHILDREN;
+ }
+
+ if (object instanceof CDOElement)
+ {
+ CDOElement checkoutElement = (CDOElement)object;
+ return checkoutElement.getChildren();
+ }
+
+ final Object originalObject = object;
+ Object[] children = childrenCache.remove(originalObject);
+ if (children != null)
+ {
+ return children;
+ }
+
+ CONTEXT openingCheckout = null;
+ if (isContext(object))
+ {
+ @SuppressWarnings("unchecked")
+ CONTEXT context = (CONTEXT)object;
+
+ switch (getContextState(context))
+ {
+ case Closed:
+ return ViewerUtil.NO_CHILDREN;
+
+ case Opening:
+ openingCheckout = context;
+ break;
+
+ case Open:
+ object = getRootObject(context);
+ break;
+ }
+ }
+
+ final Object finalObject = object;
+ final CONTEXT finalOpeningContext = openingCheckout;
+
+ final ITreeContentProvider contentProvider = getContentProvider(finalObject);
+ if (contentProvider == null)
+ {
+ return ItemProvider.NO_ELEMENTS;
+ }
+
+ final List<CDORevision> loadedRevisions = new ArrayList<>();
+ final List<CDOID> missingIDs = new ArrayList<>();
+
+ if (finalOpeningContext == null)
+ {
+ children = determineChildRevisions(object, loadedRevisions, missingIDs);
+ if (children != null)
+ {
+ return modifyChildren(object, children);
+ }
+ }
+
+ boolean firstLoad;
+ synchronized (LOADING_OBJECTS)
+ {
+ firstLoad = LOADING_OBJECTS.add(originalObject);
+ }
+
+ if (firstLoad || finalOpeningContext == null)
+ {
+ Job job = new Job("Load " + finalObject)
+ {
+ @Override
+ protected IStatus run(IProgressMonitor monitor)
+ {
+ try
+ {
+ if (finalOpeningContext != null)
+ {
+ openContext(finalOpeningContext);
+ determineChildRevisions(finalObject, loadedRevisions, missingIDs);
+ }
+
+ if (!missingIDs.isEmpty())
+ {
+ CDOObject cdoObject = getCDOObject((EObject)finalObject);
+ CDOView view = cdoObject.cdoView();
+ CDORevisionManager revisionManager = view.getSession().getRevisionManager();
+
+ List<CDORevision> revisions = revisionManager.getRevisions(missingIDs, view, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
+ loadedRevisions.addAll(revisions);
+ }
+
+ Object[] children = contentProvider.getChildren(finalObject);
+
+ // Adjust possible legacy adapters.
+ for (int i = 0; i < children.length; i++)
+ {
+ Object child = children[i];
+ if (child instanceof InternalCDOObject)
+ {
+ InternalCDOObject cdoObject = (InternalCDOObject)child;
+ InternalEObject instance = cdoObject.cdoInternalInstance();
+ if (instance != cdoObject)
+ {
+ children[i] = instance;
+ }
+ }
+ }
+
+ children = modifyChildren(finalObject, children);
+ childrenCache.put(originalObject, children);
+ }
+ catch (final Exception ex)
+ {
+ childrenCache.remove(originalObject);
+
+ if (finalOpeningContext != null)
+ {
+ closeContext(finalOpeningContext);
+ }
+
+ OM.LOG.error(ex);
+
+ final Control control = viewer.getControl();
+ if (!control.isDisposed())
+ {
+ UIUtil.getDisplay().asyncExec(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ if (!control.isDisposed())
+ {
+ Shell shell = control.getShell();
+ String title = (finalOpeningContext != null ? "Open" : "Load") + " Error";
+ MessageDialog.openError(shell, title, ex.getMessage());
+ }
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ }
+ }
+ });
+ }
+ }
+
+ RunnableViewerRefresh viewerRefresh = getViewerRefresh();
+ viewerRefresh.addNotification(originalObject, true, true, () -> {
+ synchronized (LOADING_OBJECTS)
+ {
+ LOADING_OBJECTS.remove(originalObject);
+ }
+ });
+
+ return Status.OK_STATUS;
+ }
+ };
+
+ job.schedule();
+ }
+
+ if (FIND_ITEM_METHOD != null)
+ {
+ try
+ {
+ Object widget = FIND_ITEM_METHOD.invoke(viewer, originalObject);
+ if (widget instanceof TreeItem)
+ {
+ TreeItem item = (TreeItem)widget;
+ TreeItem[] childItems = item.getItems();
+
+ int childCount = childItems.length;
+ if (childCount != 0)
+ {
+ List<Object> result = new ArrayList<>();
+ for (int i = 0; i < childCount; i++)
+ {
+ TreeItem childItem = childItems[i];
+ Object child = childItem.getData();
+ if (child != null)
+ {
+ result.add(child);
+ }
+ }
+
+ int size = result.size();
+ if (size != 0)
+ {
+ return result.toArray(new Object[size]);
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ //$FALL-THROUGH$
+ }
+ }
+
+ String text = "Loading...";
+ if (finalOpeningContext != null)
+ {
+ text = "Opening...";
+ }
+
+ return new Object[] { new ViewerUtil.Pending(originalObject, text) };
+ }
+ catch (LifecycleException ex)
+ {
+ //$FALL-THROUGH$
+ }
+ catch (RuntimeException ex)
+ {
+ if (LifecycleUtil.isActive(object))
+ {
+ throw ex;
+ }
+
+ //$FALL-THROUGH$
+ }
+
+ return ItemProvider.NO_ELEMENTS;
+ }
+
+ @Override
+ public Object getParent(Object object)
+ {
+ try
+ {
+ if (object instanceof ViewerUtil.Pending)
+ {
+ return ((ViewerUtil.Pending)object).getParent();
+ }
+
+ if (object instanceof CDOElement)
+ {
+ CDOElement checkoutElement = (CDOElement)object;
+ return checkoutElement.getParent();
+ }
+
+ if (object instanceof EObject)
+ {
+ EObject eObject = CDOUtil.getEObject((EObject)object);
+
+ CDOElement element = CDOElement.getFor(eObject);
+ if (element != null)
+ {
+ return element;
+ }
+
+ ITreeContentProvider contentProvider = getContentProvider(object);
+ if (contentProvider != null)
+ {
+ return contentProvider.getParent(object);
+ }
+ }
+ }
+ catch (LifecycleException ex)
+ {
+ //$FALL-THROUGH$
+ }
+ catch (RuntimeException ex)
+ {
+ if (LifecycleUtil.isActive(object))
+ {
+ throw ex;
+ }
+
+ //$FALL-THROUGH$
+ }
+
+ return null;
+ }
+
+ protected void hookViewer(TreeViewer viewer)
+ {
+ }
+
+ protected void unhookViewer(TreeViewer viewer)
+ {
+ }
+
+ protected abstract Object adapt(Object target, Object type);
+
+ protected abstract Object[] modifyChildren(Object parent, Object[] children);
+
+ protected abstract ITreeContentProvider getContentProvider(Object object);
+
+ protected abstract RunnableViewerRefresh getViewerRefresh();
+
+ protected abstract boolean isContext(Object object);
+
+ protected abstract ContextState getContextState(CONTEXT context);
+
+ protected abstract void openContext(CONTEXT context);
+
+ protected abstract void closeContext(CONTEXT context);
+
+ protected abstract Object getRootObject(CONTEXT context);
+
+ private Object[] determineChildRevisions(Object object, List<CDORevision> loadedRevisions, List<CDOID> missingIDs)
+ {
+ if (GET_CHILDREN_FEATURES_METHOD != null && object instanceof EObject)
+ {
+ EObject eObject = (EObject)object;
+
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (cdoObject != null)
+ {
+ InternalCDORevision revision = cdoObject.cdoRevision(false);
+ if (revision != null)
+ {
+ try
+ {
+ ITreeItemContentProvider provider = (ITreeItemContentProvider)adapt(object, ITreeItemContentProvider.class);
+ if (provider instanceof ItemProviderAdapter)
+ {
+ determineChildRevisions(cdoObject, revision, (ItemProviderAdapter)provider, loadedRevisions, missingIDs);
+
+ if (missingIDs.isEmpty())
+ {
+ // All revisions are cached. Just return the objects without server round-trips.
+ ITreeContentProvider contentProvider = getContentProvider(object);
+ if (contentProvider != null)
+ {
+ return contentProvider.getChildren(object);
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ //$FALL-THROUGH$
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ protected static boolean isObjectLoading(Object... objects)
+ {
+ synchronized (LOADING_OBJECTS)
+ {
+ for (Object object : objects)
+ {
+ if (LOADING_OBJECTS.contains(object))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ private static InternalCDOObject getCDOObject(EObject eObject)
+ {
+ return (InternalCDOObject)CDOUtil.getCDOObject(eObject, false);
+ }
+
+ private static boolean hasChildren(InternalCDOObject cdoObject, InternalCDORevision revision, ItemProviderAdapter provider) throws Exception
+ {
+ for (EStructuralFeature feature : getChildrenFeatures(cdoObject, provider))
+ {
+ if (feature.isMany())
+ {
+ if (!revision.isEmpty(feature))
+ {
+ return true;
+ }
+ }
+ else if (revision.getValue(feature) != null)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static void determineChildRevisions(InternalCDOObject cdoObject, InternalCDORevision revision, ItemProviderAdapter provider,
+ List<CDORevision> loadedRevisions, List<CDOID> missingIDs) throws Exception
+ {
+ InternalCDOView view = cdoObject.cdoView();
+ InternalCDORevisionCache revisionCache = view.getSession().getRevisionManager().getCache();
+
+ for (EStructuralFeature feature : getChildrenFeatures(cdoObject, provider))
+ {
+ if (feature.isMany())
+ {
+ CDOList list = revision.getListOrNull(feature);
+ if (list != null)
+ {
+ for (Object object : list)
+ {
+ determineChildRevision(loadedRevisions, missingIDs, view, revisionCache, object);
+ }
+ }
+ }
+ else
+ {
+ Object value = revision.getValue(feature);
+ determineChildRevision(loadedRevisions, missingIDs, view, revisionCache, value);
+ }
+ }
+ }
+
+ private static void determineChildRevision(List<CDORevision> loadedRevisions, List<CDOID> missingIDs, InternalCDOView view, InternalCDORevisionCache cache,
+ Object object)
+ {
+ if (object instanceof CDOID)
+ {
+ CDOID id = (CDOID)object;
+ CDORevision childRevision = cache.getRevision(id, view);
+ if (childRevision != null)
+ {
+ loadedRevisions.add(childRevision);
+ }
+ else
+ {
+ missingIDs.add(id);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Collection<? extends EStructuralFeature> getChildrenFeatures(InternalCDOObject cdoObject, ItemProviderAdapter provider) throws Exception
+ {
+ return (Collection<? extends EStructuralFeature>)GET_CHILDREN_FEATURES_METHOD.invoke(provider, cdoObject);
+ }
+
+ private static Method getMethod(Class<?> c, String methodName, Class<?>... parameterTypes)
+ {
+ try
+ {
+ Method method = c.getDeclaredMethod(methodName, parameterTypes);
+ method.setAccessible(true);
+ return method;
+ }
+ catch (Throwable ex)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static enum ContextState
+ {
+ Opening, Open, Closed
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutViewerRefresh.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/RunnableViewerRefresh.java
index 8b86b431f7..480598a18e 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOCheckoutViewerRefresh.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/RunnableViewerRefresh.java
@@ -8,7 +8,7 @@
* Contributors:
* Eike Stepper - initial API and implementation
*/
-package org.eclipse.emf.cdo.explorer.ui.checkouts;
+package org.eclipse.emf.cdo.internal.ui;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.edit.provider.IViewerNotification;
@@ -23,11 +23,11 @@ import java.util.List;
/**
* @author Eike Stepper
*/
-public final class CDOCheckoutViewerRefresh extends ViewerRefresh
+public final class RunnableViewerRefresh extends ViewerRefresh
{
private final Viewer viewer;
- public CDOCheckoutViewerRefresh(Viewer viewer)
+ public RunnableViewerRefresh(Viewer viewer)
{
super(viewer);
this.viewer = viewer;
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/ViewerUtil.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/ViewerUtil.java
index 3ed3d5492e..fa9831036b 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/ViewerUtil.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/ViewerUtil.java
@@ -8,7 +8,7 @@
* Contributors:
* Eike Stepper - initial API and implementation
*/
-package org.eclipse.emf.cdo.explorer.ui;
+package org.eclipse.emf.cdo.internal.ui;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredViewer;
@@ -195,5 +195,11 @@ public final class ViewerUtil
{
return text;
}
+
+ @Override
+ public String toString()
+ {
+ return text;
+ }
}
}
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
index 82364be6a6..2317f4e9cb 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
@@ -21,6 +21,9 @@ import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.model.EMFUtil;
import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.internal.ui.CDOContentProvider;
+import org.eclipse.emf.cdo.internal.ui.RunnableViewerRefresh;
+import org.eclipse.emf.cdo.internal.ui.ViewerUtil;
import org.eclipse.emf.cdo.internal.ui.actions.TransactionalBackgroundAction;
import org.eclipse.emf.cdo.internal.ui.bundle.OM;
import org.eclipse.emf.cdo.internal.ui.dialogs.BulkAddDialog;
@@ -50,6 +53,7 @@ import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.ui.actions.LongRunningAction;
import org.eclipse.net4j.util.ui.actions.SafeAction;
+import org.eclipse.net4j.util.ui.views.ContainerItemProvider;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
@@ -125,6 +129,7 @@ import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
@@ -1508,8 +1513,33 @@ public class CDOEditor extends MultiPageEditorPart implements IEditingDomainProv
*/
protected IContentProvider createContentProvider()
{
- return new AdapterFactoryContentProvider(adapterFactory)
+ class DelegateContentProvider extends AdapterFactoryContentProvider
{
+ public DelegateContentProvider(AdapterFactory adapterFactory)
+ {
+ super(adapterFactory);
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+ {
+ super.inputChanged(viewer, oldInput, newInput);
+
+ if (viewer != null)
+ {
+ viewerRefresh = new RunnableViewerRefresh(viewer);
+ }
+ else
+ {
+ viewerRefresh = null;
+ }
+ }
+
+ public RunnableViewerRefresh getViewerRefresh()
+ {
+ return (RunnableViewerRefresh)viewerRefresh;
+ }
+
@Override
public boolean hasChildren(Object object)
{
@@ -1527,6 +1557,72 @@ public class CDOEditor extends MultiPageEditorPart implements IEditingDomainProv
return false;
}
}
+ }
+
+ DelegateContentProvider delegate = new DelegateContentProvider(adapterFactory);
+
+ return new CDOContentProvider<CDOView>()
+ {
+ @Override
+ public void inputChanged(Viewer newViewer, Object oldInput, Object newInput)
+ {
+ super.inputChanged(newViewer, oldInput, newInput);
+ delegate.inputChanged(newViewer, oldInput, newInput);
+ }
+
+ @Override
+ protected Object adapt(Object target, Object type)
+ {
+ return adapterFactory.adapt(target, type);
+ }
+
+ @Override
+ protected Object[] modifyChildren(Object parent, Object[] children)
+ {
+ return children;
+ }
+
+ @Override
+ protected ITreeContentProvider getContentProvider(Object object)
+ {
+ return delegate;
+ }
+
+ @Override
+ protected RunnableViewerRefresh getViewerRefresh()
+ {
+ return delegate.getViewerRefresh();
+ }
+
+ @Override
+ protected boolean isContext(Object object)
+ {
+ return false;
+ }
+
+ @Override
+ protected ContextState getContextState(CDOView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void openContext(CDOView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void closeContext(CDOView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected Object getRootObject(CDOView view)
+ {
+ throw new UnsupportedOperationException();
+ }
};
}
@@ -1542,6 +1638,11 @@ public class CDOEditor extends MultiPageEditorPart implements IEditingDomainProv
{
try
{
+ if (element instanceof ViewerUtil.Pending)
+ {
+ return ContainerItemProvider.PENDING_IMAGE;
+ }
+
Image image = super.getImage(element);
if (image != null)
{
@@ -1564,6 +1665,12 @@ public class CDOEditor extends MultiPageEditorPart implements IEditingDomainProv
{
try
{
+ if (element instanceof ViewerUtil.Pending)
+ {
+ ViewerUtil.Pending pending = (ViewerUtil.Pending)element;
+ return pending.getText();
+ }
+
String text = super.getText(element);
if (!StringUtil.isEmpty(text))
{

Back to the top