/******************************************************************************* * Copyright (c) 2007, 2014 Borland Software Corporation 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: * Borland Software Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.common.ui.views; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EModelElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.commands.ActionHandler; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.m2m.internal.qvt.oml.common.CommonPlugin; import org.eclipse.m2m.internal.qvt.oml.common.ui.CommonPluginImages; import org.eclipse.m2m.internal.qvt.oml.common.ui.dialogs.ComplexClassifierProvider; import org.eclipse.m2m.internal.qvt.oml.common.ui.dialogs.OpenClassifierDialog; import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfException; import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil; import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtilPlugin; import org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry.IMetamodelDesc; import org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry.MetamodelRegistry; import org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry.WorkspaceMetamodelProvider; import org.eclipse.m2m.internal.qvt.oml.emf.util.ui.DelegatingPropertySource; import org.eclipse.m2m.internal.qvt.oml.emf.util.ui.metamodel.MetamodelImageRegistry; import org.eclipse.m2m.internal.qvt.oml.emf.util.ui.provider.EMFProviderUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.custom.ViewForm; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.contexts.IContextActivation; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; import org.eclipse.ui.handlers.IHandlerActivation; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.part.DrillDownAdapter; import org.eclipse.ui.services.IServiceLocator; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.IPropertySourceProvider; import org.eclipse.ui.views.properties.PropertySheetPage; public class MetamodelBrowser implements IAdaptable { /* * Browser style constants */ public static final int SHOW_PACKAGE_ONLY = 0; public static final int SHOW_PACKAGE_CONTENTS = 1; public static final int SHOW_CLASSIFIER_CONTENTS = 2; public static final int CHECK_STYLE = 4; public static final int DEFAULT = SHOW_CLASSIFIER_CONTENTS | SHOW_PACKAGE_CONTENTS; private static final String FIND_CLASSIFIER_COMMAND_ID = "org.eclipse.m2m.qvt.oml.findClassifier"; //$NON-NLS-1$ private static final String CONTEXT_ID = "org.eclipse.m2m.qvt.oml.metamodelBrowser"; //$NON-NLS-1$ private static final String EXTENDED_CLASSES = " -> "; //$NON-NLS-1$ private static final String EXTENDED_CLASSES_SEPARATOR = ", "; //$NON-NLS-1$ private static final String INSTANCE_CLASS_NAME_START = " <"; //$NON-NLS-1$ private static final String INSTANCE_CLASS_NAME_END = ">"; //$NON-NLS-1$ private static final String NAME_AND_TYPE_SEPARATOR = " : "; //$NON-NLS-1$ private static final String PARAMETERS_START = "("; //$NON-NLS-1$ private static final String PARAMETERS_SEPARATOR = ", "; //$NON-NLS-1$ private static final String PARAMETERS_END = ")"; //$NON-NLS-1$ private IContextService contextService; private IContextActivation contextActivation; private IHandlerService handlerService; private IHandlerActivation handlerActivation; private TreeViewer myViewer; private DrillDownAdapter myDrillDownAdapter; private IAction myDoubleClickAction; private IAction myCollapseAllAction; private IAction myShowInheritedFeaturesAction; private IAction myShowFullQualifiedNamesAction; private IAction myOpenClassifierAction; private PropertySheetPage myPropertySheetPage; private boolean myShowInheritedFeatures = false; private boolean myShowFullQualifiedNames = false; private int browserStyle; private ViewForm control; private IToolBarManager toolBarManager; private BrowserNode workspaceModels; public MetamodelBrowser(Composite parent) { this(parent, DEFAULT); } public MetamodelBrowser(Composite parent, int browserStyle) { Composite container = parent; this.browserStyle = browserStyle; this.control = new ViewForm(container, SWT.NONE); GridData data = new GridData(GridData.FILL_BOTH); data.heightHint = 250; data.grabExcessHorizontalSpace = true; data.grabExcessVerticalSpace = true; this.control.setLayoutData(data); this.toolBarManager = getToolBarManager(); myViewer = createTreeViewer(control); control.setContent(myViewer.getControl()); setupFilters(); myViewer.setContentProvider(createTreeContentProvider()); myViewer.setLabelProvider(createLabelProvider()); myViewer.setSorter(createSorter()); myViewer.setInput(createInput()); myDrillDownAdapter = new DrillDownAdapter(myViewer); makeActions(); hookContextMenu(); hookDoubleClickAction(); contributeToActionBars(); myViewer.expandToLevel(((BrowserNode)myViewer.getInput()).getChildren(false).get(0), 1); myViewer.getTree().setFocus(); PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.m2m.qvt.oml.metamodel_browser"); //$NON-NLS-1$ control.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { dispose(); } }); } private void setupFilters() { List<ViewerFilter> filters = new ArrayList<ViewerFilter>(); if((browserStyle & SHOW_CLASSIFIER_CONTENTS) == 0) { filters.add(new ClassifierContentsFilter()); } if((browserStyle & SHOW_PACKAGE_CONTENTS) == 0) { filters.add(new PackageContentsFilter()); } myViewer.setFilters(filters.toArray(new ViewerFilter[filters.size()])); } public <T extends EModelElement> List<T> getModelElementSelection(Class<T> type) { List<T> result = new ArrayList<T>(); for (EModelElement element : getModelElementSelection()) { if(type.isInstance(element)) { result.add(type.cast(element)); } } return result; } public List<EModelElement> getModelElementSelection() { List<EModelElement> result = new ArrayList<EModelElement>(); if(!getViewer().getSelection().isEmpty()) { for (Iterator<?> it = ((IStructuredSelection)getViewer().getSelection()).iterator(); it.hasNext();) { BrowserNode selObj = (BrowserNode) it.next(); if(selObj.getEObject() instanceof EModelElement) { result.add((EModelElement)selObj.getEObject()); } } } if(getViewer() instanceof ContainerCheckedTreeViewer) { ContainerCheckedTreeViewer checkedViewer = (ContainerCheckedTreeViewer) getViewer(); Object[] elements = checkedViewer.getCheckedElements(); for (int i = 0; i < elements.length; i++) { Object nextObject = elements[i]; EModelElement modelElement = getElementAdapter(nextObject, EModelElement.class); if(modelElement instanceof EModelElement) { result.add((EModelElement)modelElement); } } } return result; } public <T> T getElementAdapter(Object element, Class<T> adapter) { if(!(element instanceof IAdaptable)) { return null; } IAdaptable adaptable = (IAdaptable)element; Object adapted = adaptable.getAdapter(adapter); if(adapted != null) { return (T)adapter.cast(adapted); } return null; } public Composite getControl() { return control; } protected IToolBarManager getToolBarManager() { if(toolBarManager != null) { return toolBarManager; } ToolBar tb = new ToolBar(control, SWT.FLAT); toolBarManager = new ToolBarManager(tb); control.setTopLeft(tb); return toolBarManager; } protected TreeViewer createTreeViewer(Composite parent) { int style = SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL; if((browserStyle & CHECK_STYLE) != 0) { return new ContainerCheckedTreeViewer(parent, style); } return new TreeViewer(parent, style); } private static MetamodelContainerNode createRootMetamodelContainer() { return new MetamodelContainerNode(MetamodelContainerNode.GLOBAL_REGISTRY_TYPE, null, null, null); } protected IServiceLocator getServiceLocator() { return org.eclipse.ui.PlatformUI.getWorkbench(); } public TreeViewer getViewer() { return myViewer; } protected ViewerSorter createSorter() { return new ViewerSorter() { @Override public int category(final Object element) { int category = super.category(element); if (((BrowserNode) element).getEObject() instanceof EPackage) { return category - 1; } return category; } @Override public int compare(Viewer viewer, Object e1, Object e2) { if(e1 instanceof MetamodelNode && e2 instanceof MetamodelNode) { MetamodelNode n1 = (MetamodelNode) e1; MetamodelNode n2 = (MetamodelNode) e2; String key1 = n1.getDescriptor().getId(); String key2 = n2.getDescriptor().getId(); if(n1.getPackage() != null && isOK(n1.getDescriptor())) { key1 = n1.getPackage().getName(); } if(n2.getPackage() != null && isOK(n2.getDescriptor())) { key2 = n2.getPackage().getName(); } return key1.compareTo(key2); } return super.compare(viewer, e1, e2); } }; } protected ITreeContentProvider createTreeContentProvider() { return new ITreeContentProvider() { public Object[] getChildren(final Object parentElement) { return ((BrowserNode) parentElement).getChildren(myShowInheritedFeatures).toArray(); } public Object getParent(final Object element) { return ((BrowserNode) element).getParent(); } public boolean hasChildren(final Object element) { BrowserNode node = (BrowserNode) element; if((browserStyle & SHOW_CLASSIFIER_CONTENTS) == 0 && node.getEObject() instanceof EClassifier) { return false; } else if((browserStyle & SHOW_PACKAGE_CONTENTS) == 0 && node.getEObject() instanceof EPackage) { EPackage ePackage = (EPackage)node.getEObject(); if(ePackage.getESubpackages().isEmpty()) { return false; } } return ((BrowserNode) element).hasChildren(myShowInheritedFeatures); } public Object[] getElements(Object inputElement) { if(!hasChildren(inputElement)) { return new Object[0]; } return getChildren(inputElement); } public void dispose() { } public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { } }; } protected ILabelProvider createLabelProvider() { final ILabelProvider provider = EMFProviderUtil.createLabelProvider(); return new ILabelProvider() { public void removeListener(final ILabelProviderListener listener) { provider.removeListener(listener); } public boolean isLabelProperty(final Object element, final String property) { return provider.isLabelProperty(((BrowserNode) element).getEObject(), property); } public void dispose() { provider.dispose(); } public void addListener(final ILabelProviderListener listener) { provider.addListener(listener); } public String getText(final Object element) { BrowserNode node = (BrowserNode) element; String availableText = node.getText(); if(availableText != null) { return availableText; } EObject eObject = ((BrowserNode) element).getEObject(); if (myShowFullQualifiedNames && eObject instanceof EClassifier) { EClassifier eClassifier = (EClassifier) eObject; StringBuilder text = new StringBuilder(); text.append(eClassifier.getName()); if (eClassifier instanceof EClass) { EClass eClass = (EClass) eClassifier; if (!eClass.getESuperTypes().isEmpty()) { text.append(EXTENDED_CLASSES); for (Iterator<EClass> iter = eClass.getESuperTypes().iterator(); iter.hasNext();) { EClass eSuperType = (EClass) iter.next(); text.append(EmfUtil.getFullName(eSuperType)); if (iter.hasNext()) { text.append(EXTENDED_CLASSES_SEPARATOR); } } } } if (eClassifier.getInstanceClassName() != null) { text.append(INSTANCE_CLASS_NAME_START); text.append(eClassifier.getInstanceClassName()); text.append(INSTANCE_CLASS_NAME_END); } return text.toString(); } if (myShowFullQualifiedNames && eObject instanceof ETypedElement) { ETypedElement eTypedElement = (ETypedElement) eObject; StringBuilder text = new StringBuilder(); text.append(eTypedElement.getName()); if (eTypedElement instanceof EOperation) { EOperation eOperation = (EOperation) eTypedElement; text.append(PARAMETERS_START); for (Iterator<EParameter> iter = eOperation.getEParameters().iterator(); iter.hasNext();) { EParameter eParameter = (EParameter) iter.next(); text.append(EmfUtil.getFullName(eParameter.getEType())); if (iter.hasNext()) { text.append(PARAMETERS_SEPARATOR); } } text.append(PARAMETERS_END); } if (eTypedElement.getEType() != null) { text.append(NAME_AND_TYPE_SEPARATOR); text.append(EmfUtil.getFullName(eTypedElement.getEType())); } return text.toString(); } String text = provider.getText(eObject); if (eObject instanceof EPackage && eObject.eContainer() == null) { String nsURI = ((EPackage) eObject).getNsURI(); if (nsURI != null && nsURI.length() > 0) { text += " (" + ((EPackage) eObject).getNsURI() + ")"; //$NON-NLS-1$//$NON-NLS-2$ } } return text; } public Image getImage(final Object element) { BrowserNode node = (BrowserNode) element; Image availableImage = node.getImage(); if(availableImage != null) { return availableImage; } EObject eObject = node.getEObject(); if (eObject instanceof EPackage) { Image image = MetamodelImageRegistry.INSTANCE.getImage((EPackage) eObject); if (image != null) { return image; } } return provider.getImage(eObject); } }; } protected Object createInput() { final Object[] input = new Object[1]; // initializing java generated registry is a long running task BusyIndicator.showWhile(null, new Runnable() { public void run() { input[0] = doCreateInput(); } }); assert input.length == 1; return input[0]; } protected Object doCreateInput() { BrowserNode rootContainer = createRootMetamodelContainer(); BrowserNode globalRegistryNode = new MetamodelContainerNode( MetamodelContainerNode.GLOBAL_REGISTRY_TYPE, Messages.MetamodelBrowserView_platformMetamodelsLabel, CommonPluginImages.getInstance().getImage(CommonPluginImages.METAMODELS), rootContainer); // TODO - add dedicated image to workspace metamodels workspaceModels = new MetamodelContainerNode( MetamodelContainerNode.WORKSPACE_MODELS_TYPE, Messages.MetamodelBrowserView_workspaceMetamodelsLabel, CommonPluginImages.getInstance().getImage(CommonPluginImages.METAMODELS), rootContainer); Map<EPackage, IMetamodelDesc> rootNodes = new HashMap<EPackage, IMetamodelDesc>(); String[] ids = MetamodelRegistry.getInstance().getMetamodelIds(); for (int i = 0; i < ids.length; i++) { try { IMetamodelDesc desc = MetamodelRegistry.getInstance().getMetamodelDesc(ids[i]); EPackage pack = desc.getModel(); if (pack != null) { if(pack.getESuperPackage() == null) { rootNodes.put(pack, desc); } else { // Note: // check for empty packages not registered in global EPackage.Registry // but created programmatically as containers, as EMF ignores packages with // empty content EPackage parent = EmfUtil.getRootPackage(pack); if(parent != pack && !rootNodes.containsKey(parent)) { rootNodes.put(parent, new DelegatingDesc(parent)); } } } } catch (EmfException ignore) { CommonPlugin.log(ignore); } } for (Map.Entry<EPackage, IMetamodelDesc> rootEntry : rootNodes.entrySet()) { globalRegistryNode.addChild(new MetamodelNode(rootEntry.getValue(), globalRegistryNode, false)); } WorkspaceMetamodelProvider ws = new WorkspaceMetamodelProvider(new ResourceSetImpl()); List<IResource> wsModels = collectWorkspaceMetamodels(); for (IResource res : wsModels) { URI resURI = URI.createPlatformResourceURI(res.getFullPath().toString(), false); IMetamodelDesc wsMModelDesc = ws.addMetamodel(resURI.toString(), resURI); workspaceModels.addChild(new ResourceModelNode(resURI, wsMModelDesc, workspaceModels)); } rootContainer.addChild(globalRegistryNode); rootContainer.addChild(workspaceModels); return rootContainer; } /** * Synchronizes the browser contents with the given the workspace changes about ecore files. * @param wsDelta an object grouping workspace changes related to ecore files. */ void update(WorkspaceMetamodelsDelta wsDelta) { if(!wsDelta.isEmpty()) { for (IPath addedPath : wsDelta.getAdditions()) { metamodelFileAdded(addedPath); } for (IPath modifiedPath : wsDelta.getModifications()) { metamodelFileModified(modifiedPath); } for (IPath deletedPath : wsDelta.getDeletions()) { metamodelDeletedFile(deletedPath); } for (Map.Entry<IPath, IPath> entry : wsDelta.getMoves().entrySet()) { metamodelDeletedFile(entry.getKey()); metamodelFileAdded(entry.getValue()); } myViewer.refresh(); } } protected void hookContextMenu() { MenuManager menuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$ menuManager.setRemoveAllWhenShown(true); menuManager.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { MetamodelBrowser.this.fillContextMenu(manager); } }); Menu menu = menuManager.createContextMenu(myViewer.getControl()); myViewer.getControl().setMenu(menu); } protected void contributeToActionBars() { fillLocalToolBar(toolBarManager); } protected void fillContextMenu(final IMenuManager manager) { myDrillDownAdapter.addNavigationActions(manager); manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } protected void fillLocalToolBar(IToolBarManager manager) { myDrillDownAdapter.addNavigationActions(manager); manager.add(new Separator()); manager.add(myCollapseAllAction); manager.add(new Separator()); manager.add(myShowInheritedFeaturesAction); manager.add(myShowFullQualifiedNamesAction); if(myOpenClassifierAction != null) { manager.add(new Separator()); manager.add(myOpenClassifierAction); } manager.update(true); } protected void makeActions() { myDoubleClickAction = new Action() { @Override public void run() { // ISelection selection = myViewer.getSelection(); // Object obj = ((IStructuredSelection) selection).getFirstElement(); } }; myCollapseAllAction = new Action() { @Override public void run() { myViewer.collapseAll(); } }; myCollapseAllAction.setToolTipText(Messages.MetamodelBrowserView_collapseAll); myCollapseAllAction.setImageDescriptor(CommonPluginImages.getInstance().getImageDescriptor(CommonPluginImages.COLLAPSE_ALL)); myShowInheritedFeaturesAction = new Action(null, IAction.AS_CHECK_BOX) { @Override public void run() { myShowInheritedFeatures = isChecked(); myViewer.refresh(); } }; myShowInheritedFeaturesAction.setToolTipText(Messages.MetamodelBrowserView_showInheritedFeatures); myShowInheritedFeaturesAction.setImageDescriptor(CommonPluginImages.getInstance().getImageDescriptor(CommonPluginImages.SHOW_INHERITED_FEATURES)); myShowFullQualifiedNamesAction = new Action(null, IAction.AS_CHECK_BOX) { @Override public void run() { myShowFullQualifiedNames = isChecked(); myViewer.refresh(); } }; myShowFullQualifiedNamesAction.setToolTipText(Messages.MetamodelBrowserView_showFullQualifiedNames); myShowFullQualifiedNamesAction.setImageDescriptor(CommonPluginImages.getInstance().getImageDescriptor(CommonPluginImages.SHOW_FULL_QUALIFIED_NAMES)); if((browserStyle & SHOW_PACKAGE_CONTENTS) != 0) { myOpenClassifierAction = createFindClassifierAction(myViewer); this.contextService = (IContextService)getServiceLocator().getService(IContextService.class); this.contextService.getShellType(control.getShell()); this.contextActivation = contextService.activateContext(CONTEXT_ID); this.handlerService = (IHandlerService)getServiceLocator().getService(IHandlerService.class); this.handlerActivation = handlerService.activateHandler("org.eclipse.m2m.qvt.oml.findClassifier", new ActionHandler(myOpenClassifierAction)); //$NON-NLS-1$ } } private Display getDisplay() { return getControl().getDisplay(); } private void dispose() { if(contextActivation != null) { contextService.deactivateContext(contextActivation); } if(handlerActivation != null) { handlerService.deactivateHandler(handlerActivation); } } private IAction createFindClassifierAction(final TreeViewer viewer) { Action action = new Action() { @Override public void run() { final List<EPackage> rootPackages = new ArrayList<EPackage>(); if(viewer != null) { BusyIndicator.showWhile(getDisplay(), new Runnable() { public void run() { List<BrowserNode> rootChildren = ((BrowserNode)viewer.getInput()).getChildren(false); for (int i = 0; i < rootChildren.size(); i++) { collectSearchScopePackages(rootChildren.get(i), rootPackages); } } } ); // end of show while } OpenClassifierDialog dialog = new OpenClassifierDialog(viewer.getControl().getShell(), new ComplexClassifierProvider(Collections.unmodifiableList(rootPackages))); if (dialog.open() == IDialogConstants.OK_ID) { ISelection selection = dialog.getSelection(); if (!selection.isEmpty() && selection instanceof IStructuredSelection) { navigate((EClassifier) ((IStructuredSelection) selection).getFirstElement()); } } } }; action.setToolTipText(Messages.MetamodelBrowserView_openClassifier); action.setImageDescriptor(CommonPluginImages.getInstance().getImageDescriptor(CommonPluginImages.OPEN_CLASSIFIER)); action.setActionDefinitionId(FIND_CLASSIFIER_COMMAND_ID); return action; } private static void collectSearchScopePackages(BrowserNode browserNode, List<EPackage> result) { if(browserNode instanceof MetamodelContainerNode) { List<BrowserNode> mmodelNodes = browserNode.getChildren(false); for (int i = 0; i < mmodelNodes.size(); i++) { BrowserNode mmNode = mmodelNodes.get(i); collectSearchScopePackages(mmNode, result); } } else { if(browserNode instanceof MetamodelNode) { EPackage ePackage = ((MetamodelNode)browserNode).getSearchScopePackage(); if(ePackage != null) result.add(ePackage); } else if(browserNode.getEObject() instanceof EClassifier) { EClassifier eClassifier = (EClassifier)browserNode.getEObject(); EPackage scope = eClassifier.getEPackage(); if(scope != null) result.add(scope); } else if(browserNode.getEObject() instanceof EPackage) { result.add((EPackage)browserNode.getEObject()); } } } public EObject navigate(final EModelElement eModelElement) { if (myViewer == null) { return null; } BrowserNode targetNode = null; Object root = myViewer.getInput(); if (root instanceof MetamodelContainerNode) { MetamodelContainerNode metamodelContainerNode = (MetamodelContainerNode) root; targetNode = metamodelContainerNode.resolve(eModelElement); } else if (root instanceof BrowserNode) { BrowserNode browserNode = (BrowserNode) root; targetNode = BrowserNode.findNodeForInstance(browserNode, eModelElement); } if(targetNode != null) { myViewer.setSelection(new StructuredSelection(targetNode), true); myViewer.expandToLevel(targetNode, 1); myViewer.getControl().setFocus(); return targetNode.getEObject(); } return null; } protected void hookDoubleClickAction() { myViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { myDoubleClickAction.run(); } }); } public boolean setFocus() { if(myViewer != null) { myViewer.getControl().setFocus(); } return false; } @SuppressWarnings({ "rawtypes", "unchecked" }) public Object getAdapter(Class key) { if (key.equals(IPropertySheetPage.class)) { return getPropertySheetPage(); } return null; } public IPropertySheetPage getPropertySheetPage() { if (myPropertySheetPage == null) { myPropertySheetPage = new PropertySheetPage(); final IPropertySourceProvider provider = EMFProviderUtil.createAdapterFactoryContentProvider(); myPropertySheetPage.setPropertySourceProvider(new IPropertySourceProvider() { public IPropertySource getPropertySource(Object object) { IPropertySource source = null; if (object instanceof BrowserNode) { source =provider.getPropertySource(((BrowserNode) object).getEObject()); } else { source = provider.getPropertySource(object); } if (source == null) { return null; } return new DelegatingPropertySource(source); } }); } return myPropertySheetPage; } private static List<IResource> collectWorkspaceMetamodels() { final List<IResource> result = new ArrayList<IResource>(); try { ResourcesPlugin.getWorkspace().getRoot().accept(new IResourceProxyVisitor() { public boolean visit(IResourceProxy proxy) throws CoreException { if(proxy.getType() == IResource.FILE && MetamodelRegistry.isMetamodelFileName(proxy.getName())) { result.add(proxy.requestResource()); } return true; } }, IResource.NONE); } catch (CoreException e) { CommonPlugin.log(e.getStatus()); } return result; } private static class DelegatingDesc implements IMetamodelDesc { final EPackage ePackage; DelegatingDesc(EPackage delegatedPackage) { assert delegatedPackage != null; this.ePackage = delegatedPackage; } public String getId() { return ePackage.getNsURI(); } public Diagnostic getLoadStatus() { return Diagnostic.OK_INSTANCE; } public EPackage getModel() { return ePackage; } public boolean isLoaded() { return true; } @Override public String toString() { return getId(); } } private void metamodelFileAdded(IPath ecoreFilePath) { if(this.workspaceModels == null) { return; } URI resURI = URI.createPlatformResourceURI(ecoreFilePath.toString(), false); WorkspaceMetamodelProvider ws = new WorkspaceMetamodelProvider(new ResourceSetImpl()); IMetamodelDesc modelFileDesc = ws.addMetamodel(resURI.toString(), resURI); this.workspaceModels.addChild(new ResourceModelNode(resURI, modelFileDesc, workspaceModels)); } private void metamodelDeletedFile(IPath ecoreFilePath) { ResourceModelNode resourceModelNode = findResourceMetamodelNode(ecoreFilePath); if(resourceModelNode != null) { resourceModelNode.getParent().removeChild(resourceModelNode); } } private void metamodelFileModified(IPath ecoreFilePath) { ResourceModelNode resourceModelNode = findResourceMetamodelNode(ecoreFilePath); if(resourceModelNode != null) { URI resourceURI = resourceModelNode.uri; WorkspaceMetamodelProvider ws = new WorkspaceMetamodelProvider(new ResourceSetImpl()); IMetamodelDesc modelFileDesc = ws.addMetamodel(resourceURI.toString(), resourceURI); ResourceModelNode newNode = new ResourceModelNode(resourceURI, modelFileDesc, workspaceModels); resourceModelNode.getParent().removeChild(resourceModelNode); resourceModelNode.getParent().addChild(newNode); myViewer.collapseToLevel(resourceModelNode, 2); } } private ResourceModelNode findResourceMetamodelNode(IPath ecoreFilePath) { if(this.workspaceModels == null) { return null; } URI resURI = URI.createPlatformResourceURI(ecoreFilePath.toString(), false); for (ListIterator<BrowserNode> it = workspaceModels.getChildren(false).listIterator(); it.hasNext();) { BrowserNode child = it.next(); if(child instanceof ResourceModelNode) { ResourceModelNode resourceModelNode = (ResourceModelNode) child; if(resURI.equals(resourceModelNode.uri)) { return resourceModelNode; } } } return null; } private static class ClassifierContentsFilter extends ViewerFilter { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { BrowserNode node = (BrowserNode) parentElement; return !(node.getEObject() instanceof EClass); } }; private static class PackageContentsFilter extends ViewerFilter { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { BrowserNode node = (BrowserNode) element; BrowserNode parentNode = (BrowserNode) parentElement; return !(parentNode.getEObject() instanceof EPackage) || node.getEObject() instanceof EPackage; } }; private static boolean isOK(IMetamodelDesc metamodelDesc) { return EmfUtilPlugin.isSuccess(metamodelDesc.getLoadStatus()); } }