/*****************************************************************************
* Copyright (c) 2011 Atos Origin.
*
*
* 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:
* Vincent Hemery (Atos) vincent.hemery@atos.net - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.infra.services.resourceloading.util;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.util.EditPartUtilities;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.papyrus.infra.core.editor.CoreMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.notation.NotationModel;
import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel;
import org.eclipse.papyrus.infra.core.resource.uml.UmlModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.DiSashModelMngr;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.services.resourceloading.Activator;
import org.eclipse.papyrus.infra.services.resourceloading.Messages;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.Type;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.NotificationBuilder;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
/**
* This class provides utility methods for model loading
*
* @author vhemery
*/
public class LoadingUtils {
/**
* Load corresponding resources in model set for all its existing models.
*
* @param modelSet
* the model set
* @param uriWithoutFileExtension
* path of resources to load without file extension
*/
public static void loadResourcesInModelSet(ModelSet modelSet, URI uriWithoutFileExtension) {
// initiate progress dialog
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getCurrent().getActiveShell());
dialog.open();
IProgressMonitor monitor = dialog.getProgressMonitor();
IEditorPart editor = getEditor();
if(editor instanceof CoreMultiDiagramEditor) {
CoreMultiDiagramEditor core = (CoreMultiDiagramEditor)editor;
try {
DiSashModelMngr sashModelMngr = core.getServicesRegistry().getService(DiSashModelMngr.class);
IPageMngr pageMngr = sashModelMngr.getIPageMngr();
List<Object> allPages = pageMngr.allPages();
// mark progress
monitor.beginTask(Messages.LoadingUtils_RefreshPagesTask, allPages.size());
// the uri is added after getting all the pages. If it is done before, the eobjects are resolved
NotificationBuilder error = NotificationBuilder.createAsyncPopup(Messages.LoadingUtils_ErrorTitle, String.format(Messages.LoadingUtils_ErrorMessage, uriWithoutFileExtension.toString())).setType(Type.ERROR).setDelay(2000);
for(Object o : allPages) {
// refresh pages to display proxy diagrams
if(o instanceof EObject) {
EObject eobject = (EObject)o;
if(eobject.eIsProxy()) {
InternalEObject internal = (InternalEObject)eobject;
URI uriProxy = internal.eProxyURI();
URI trimFragment = uriProxy.trimFragment();
if(uriWithoutFileExtension.equals(trimFragment.trimFileExtension())) {
try {
Resource r = modelSet.getResource(trimFragment, true);
if(r != null) {
EObject newEObject = r.getEObject(uriProxy.fragment());
if(pageMngr.isOpen(newEObject)) {
pageMngr.closePage(newEObject);
pageMngr.openPage(newEObject);
}
} else {
error.run();
}
} catch (Exception e) {
error.run();
Activator.logError(e);
}
}
}
}
// mark progress
monitor.worked(1);
}
Set<String> extensions = getExtensions(modelSet);
// mark progress
monitor.beginTask(Messages.LoadingUtils_LoadModelsTask, extensions.size());
for(String s : extensions) {
try {
URI uriToLoad = uriWithoutFileExtension.appendFileExtension(s);
Resource r = modelSet.getResource(uriToLoad, true);
if(r == null) {
error.run();
}
} catch (Exception re) {
error.run();
Activator.logError(re);
}
// mark progress
monitor.worked(1);
}
} catch (ServiceException e) {
Activator.logError(e);
}
}
// mark progress
monitor.done();
dialog.close();
}
/**
* Unload corresponding resources from model set for all its existing models.
*
* @param modelSet
* the model set
* @param uriWithoutFileExtension
* path of resources to unload without file extension
*/
public static void unloadResourcesFromModelSet(ModelSet modelSet, URI uriWithoutFileExtension) {
unloadResourcesFromModelSet(modelSet, uriWithoutFileExtension, true);
}
/**
* Unload corresponding resources from model set for all its existing models.
*
* @param modelSet
* the model set
* @param uriWithoutFileExtension
* path of resources to unload without file extension
* @param refreshDiagramsWithProxies
* true if we must refresh necessary diagrams, false to skip it.
*/
public static void unloadResourcesFromModelSet(ModelSet modelSet, URI uriWithoutFileExtension, boolean refreshDiagramsWithProxies) {
// initiate progress dialog
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getCurrent().getActiveShell());
dialog.open();
IProgressMonitor monitor = dialog.getProgressMonitor();
IEditorPart editor = getEditor();
if(editor instanceof CoreMultiDiagramEditor) {
CoreMultiDiagramEditor core = (CoreMultiDiagramEditor)editor;
try {
DiSashModelMngr sashModelMngr = core.getServicesRegistry().getService(DiSashModelMngr.class);
IPageMngr pageMngr = sashModelMngr.getIPageMngr();
List<Object> allPages = pageMngr.allPages();
List<URI> pagesURIToOpen = new ArrayList<URI>(allPages.size());
List<URI> pagesURIToRefresh = new ArrayList<URI>(allPages.size());
if(refreshDiagramsWithProxies) {
// mark progress
monitor.beginTask(Messages.LoadingUtils_RefreshPagesTask, allPages.size());
for(Object o : allPages) {
// refresh pages to cancel display of proxified elements
if(o instanceof EObject) {
EObject eobject = (EObject)o;
if(!eobject.eIsProxy()) {
URI trimFragment = eobject.eResource().getURI();
String frag = eobject.eResource().getURIFragment(eobject);
if(uriWithoutFileExtension.equals(trimFragment.trimFileExtension())) {
// diagram was in unloaded resource. Refresh it.
if(pageMngr.isOpen(eobject)) {
pageMngr.closePage(eobject);
pagesURIToOpen.add(trimFragment.appendFragment(frag));
}
} else if(pageMngr.isOpen(eobject)) {
// diagram is still loaded but may display proxified elements
pagesURIToRefresh.add(trimFragment.appendFragment(frag));
}
}
}
// mark progress
monitor.worked(1);
}
}
// mark progress
monitor.beginTask(Messages.LoadingUtils_UnloadModelsTask, modelSet.getResources().size());
// Use the platform string of a normalized URI for comparison below, see bug 372326
// (registered libraries in the model set have different URIs - e.g. due to a pathmap -
// although they point to the same location).
// TODO: Use a single detection mechanism in ResourceUpdateService and here
String unloadPlatformString = uriWithoutFileExtension.toPlatformString(true);
URIConverter uriConverter = modelSet.getURIConverter();
// unload resource
for(Resource res : new ArrayList<Resource>(modelSet.getResources())) {
URI normalizedURI = uriConverter.normalize(res.getURI());
String platformString = normalizedURI.trimFileExtension().toPlatformString(true);
if((platformString != null) && platformString.equals(unloadPlatformString)) {
// unload this resource
modelSet.getResources().remove(res);
res.unload();
res.eAdapters().clear();
}
// mark progress
monitor.worked(1);
}
// // mark progress
// monitor.beginTask("Resolve", 1);
// EcoreUtil.resolveAll(modelSet);
// monitor.worked(1);
if(refreshDiagramsWithProxies) {
// mark progress
monitor.beginTask(Messages.LoadingUtils_RefreshPagesTask, allPages.size());
// reopen pages from proxies and refresh necessary pages
for(Object page : allPages) {
if(page instanceof EObject) {
EObject eobject = (EObject)page;
if(eobject.eIsProxy()) {
// reopen page from proxy if needed
InternalEObject internal = (InternalEObject)eobject;
URI uriProxy = internal.eProxyURI();
if(pagesURIToOpen.contains(uriProxy)) {
pageMngr.openPage(eobject);
}
} else if(eobject instanceof Diagram) {
// refresh page's diagram if needed
Diagram diag = ((Diagram)eobject);
if(pageMngr.isOpen(diag)) {
Object part = core.getDiagramGraphicalViewer().getEditPartRegistry().get(diag);
if(part instanceof GraphicalEditPart) {
// refresh nodes
for(Object child : EditPartUtilities.getAllChildren((GraphicalEditPart)part)) {
if(child instanceof EditPart) {
((EditPart)child).refresh();
}
}
// refresh edges
for(Object child : EditPartUtilities.getAllNestedConnectionEditParts((GraphicalEditPart)part)) {
if(child instanceof EditPart) {
((EditPart)child).refresh();
}
}
}
}
}
}
// mark progress
monitor.worked(1);
}
}
} catch (ServiceException e) {
Activator.logError(e);
}
}
// mark progress
monitor.done();
dialog.close();
}
/**
* Common extensions
* TODO get rid of listing all model's extensions and find a way to deduce them from model set. Then, delete this attribute.
*
* @see #getExtensions(ModelSet)
*/
private static final Set<String> COMMON_EXTENSIONS = new HashSet<String>();
static {
COMMON_EXTENSIONS.add(UmlModel.UML_FILE_EXTENSION);
COMMON_EXTENSIONS.add(NotationModel.NOTATION_FILE_EXTENSION);
COMMON_EXTENSIONS.add(DiModel.DI_FILE_EXTENSION);
}
/**
* Get list of file extensions existing for this model set
*
* @param modelSet
* model set to find common extensions for
* @return extensions list to explore
*/
private static Set<String> getExtensions(ModelSet modelSet) {
return COMMON_EXTENSIONS;
}
/**
* Get currently opened editor
*
* @return editor
*/
public static IEditorPart getEditor() {
IEditorPart editor = null;
IWorkbench workbench = PlatformUI.getWorkbench();
if(workbench != null) {
IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
if(activeWorkbenchWindow != null) {
IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();
if(activePage != null) {
editor = activePage.getActiveEditor();
}
}
}
return editor;
}
/**
* Get File from a URI
*
* @param uri
* the URI to transform
* @return the corresponding file
*/
public static IFile getFile(URI uri) {
IPath path = getPath(uri);
if(path != null) {
return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
}
return null;
}
/**
* Get Path from a URI
*
* @param uri
* the URI to transform
* @return the corresponding path
*/
public static IPath getPath(URI uri) {
String scheme = uri.scheme();
IPath path = null;
if("platform".equals(scheme)) { //$NON-NLS-1$
path = Path.fromPortableString(uri.toPlatformString(true));
} else if("file".equals(scheme)) { //$NON-NLS-1$
path = Path.fromPortableString(uri.toFileString());
}
return path;
}
}