Skip to content

Commit

Permalink
[SAFRAN-1134] Fix Database Import freezes when more than one represen…
Browse files Browse the repository at this point in the history
…tation has to be created
  • Loading branch information
vrichard12 committed Feb 28, 2024
1 parent 1d015f9 commit a1d7b46
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,24 @@ public static IStatus createErrorStatus(String message, Throwable e) {
}
}

public static void logError(String message) {
IStatus status = new Status(IStatus.ERROR, plugin.getBundle().getSymbolicName(), message);
plugin.getLog().log(status);
}

public static void logWarning(String message) {
IStatus status = new Status(IStatus.WARNING, plugin.getBundle().getSymbolicName(), message);
plugin.getLog().log(status);
}

public static void logInfo(String message) {
IStatus status = new Status(IStatus.INFO, plugin.getBundle().getSymbolicName(), message);
plugin.getLog().log(status);
}

public static void logError(String message, Throwable e) {
IStatus status = new Status(IStatus.INFO, plugin.getBundle().getSymbolicName(), message, e);
plugin.getLog().log(status);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package org.obeonetwork.database.ui.wizards.imports;

import static java.util.stream.Collectors.toList;
import static org.obeonetwork.database.ui.Activator.*;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
Expand All @@ -24,7 +25,9 @@
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.resource.Resource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
Expand All @@ -47,7 +50,6 @@
import org.obeonetwork.dsl.database.reverse.source.DataSourceException;
import org.obeonetwork.dsl.database.reverse.utils.JdbcUtils;
import org.obeonetwork.utils.common.ui.services.SiriusUIUtils;
import org.eclipse.jdt.core. IJavaProject;

public class DatabaseImportWizard extends Wizard implements IImportWizard {

Expand Down Expand Up @@ -81,7 +83,6 @@ public boolean performFinish() {
}
}


String filename = mainPage.getModelFilePath();
boolean result = DatabaseImportHelper.importDatabaseIntoModel(databaseInfos, filename, mainPage.getReferencedFiles());
if (result == true) {
Expand All @@ -107,22 +108,28 @@ protected void execute(IProgressMonitor monitor) throws CoreException, Invocatio
}
});
PlatformUI.getWorkbench().getProgressService().run(false, false, new WorkspaceModifyOperation(ResourcesPlugin.getWorkspace().getRoot()) {
@Override
@Override
protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
@SuppressWarnings("deprecation")
ModelingProject enclosingModelingProject = ModelingProject.asModelingProject(enclosingProject).get();
activateViewpoints(enclosingModelingProject, monitor);
}
});
PlatformUI.getWorkbench().getProgressService().run(false, false, new WorkspaceModifyOperation(ResourcesPlugin.getWorkspace().getRoot()) {
@Override
protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
@SuppressWarnings("deprecation")
ModelingProject enclosingModelingProject = ModelingProject.asModelingProject(enclosingProject).get();
Session session = enclosingModelingProject.getSession();
logInfo("Creating representations.");
List<DRepresentation> representations = createRepresentations(session, generatedFile, monitor);

logInfo(String.format("%d representations created.", representations.size()));
// Open representations
logInfo("Opening representations.");
for (DRepresentation representation : representations) {
DialectUIManager.INSTANCE.openEditor(session, representation, monitor);
}
logInfo("Done opening representations.");
}
});
} catch (InvocationTargetException e) {
Expand Down Expand Up @@ -156,24 +163,29 @@ private void activateViewpoints(ModelingProject enclosingModelingProject, IProgr
}

private List<DRepresentation> createRepresentations(Session session, IFile semanticResourceFile, IProgressMonitor monitor) {
List<DRepresentation> representations = new ArrayList<>();

URI semanticResourceURI = URI.createPlatformResourceURI(semanticResourceFile.getFullPath().toString(), true);
Resource semanticResource = session.getSemanticResources().stream().filter(r -> r.getURI() == semanticResourceURI).findAny().orElse(null);

List<EObject> contexts = new ArrayList<>();
List<String> representationDescriptionIds = new ArrayList<>();

List<DataBase> databases = semanticResource.getContents().stream()
.filter(DataBase.class::isInstance).map(DataBase.class::cast)
.collect(toList());
for(DataBase database : databases) {
representations.add(SiriusUIUtils.createRepresentation(session, database, IDatabaseViewpointConstants.DATABASE_DIAGRAM_ID, monitor));
contexts.add(database);
representationDescriptionIds.add(IDatabaseViewpointConstants.DATABASE_DIAGRAM_ID);
}

List<Schema> schemas = databases.stream().flatMap(db -> db.getSchemas().stream()).collect(toList());
List<Schema> schemas = databases.stream()
.flatMap(db -> db.getSchemas().stream())
.collect(toList());
for(Schema schema : schemas) {
representations.add(SiriusUIUtils.createRepresentation(session, schema, IDatabaseViewpointConstants.SCHEMA_DIAGRAM_ID, monitor));
contexts.add(schema);
representationDescriptionIds.add(IDatabaseViewpointConstants.SCHEMA_DIAGRAM_ID);
}

return representations;
return SiriusUIUtils.createRepresentations(session, contexts, representationDescriptionIds, monitor);
}

/* (non-Javadoc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
Expand All @@ -36,6 +37,7 @@
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.sirius.business.api.dialect.command.CreateRepresentationCommand;
import org.eclipse.sirius.business.api.modelingproject.ModelingProject;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.ui.business.api.dialect.DialectUIManager;
Expand Down Expand Up @@ -65,8 +67,6 @@ abstract public class AbstractISNewModelWizard extends Wizard implements INewWiz

private Resource createdResource;

private Collection<DRepresentation> createdRepresentations = new ArrayList<>();

public AbstractISNewModelWizard(String windowTitle, ImageDescriptor imageDescriptor) {
setWindowTitle(windowTitle);
this.imageDescriptor = imageDescriptor;
Expand Down Expand Up @@ -125,37 +125,35 @@ protected String extractNameFromTargetResourceName(String fileExtension) {

protected void initRepresentations(final Session session, Collection<EObject> initialObjects, IProgressMonitor monitor) {
if (session != null) {
CompoundCommand createRepresentationsCompoundCommand = new CompoundCommand();
Map<EClassifier, Collection<String>> mapDescIDs = getRepresentationDescriptionsIDToBeCreated();
if (!mapDescIDs.isEmpty()) {
for (EObject object : initialObjects) {
Collection<String> descIDs = mapDescIDs.get(object.eClass());
for (EObject context : initialObjects) {
Collection<String> descIDs = mapDescIDs.get(context.eClass());
for (String descID : descIDs) {
RepresentationDescription desc = SessionUtils.getRepresentationDescription(session, object, descID);
if (desc != null) {
RepresentationDescription representationDescription = SessionUtils.getRepresentationDescription(session, context, descID);
if (representationDescription != null) {
// Get name for the representation
String representationName = getRepresentationName(desc, object);
// and create representation
DRepresentation newRepresentation = SiriusUIUtils.createRepresentation(session, desc, representationName, object, monitor);
if (newRepresentation != null) {
createdRepresentations.add(newRepresentation);
}
}
}
// Open representations
for (DRepresentation createdRepresentation : createdRepresentations) {
if (shouldOpenRepresentation(createdRepresentation)) {
openRepresentation(session, createdRepresentation, monitor);
String representationName = getRepresentationName(representationDescription, context);
// Create representation
createRepresentationsCompoundCommand.append(new CreateRepresentationCommand(session, representationDescription, context, representationName, monitor));
}
}
}
}
if(!createRepresentationsCompoundCommand.getCommandList().isEmpty()) {
SiriusUIUtils.executeCreateRepresentationCommand(createRepresentationsCompoundCommand, session);
// Open created representations if needed
createRepresentationsCompoundCommand.getCommandList().stream()
.map(CreateRepresentationCommand.class::cast)
.map(CreateRepresentationCommand::getCreatedRepresentation)
.filter(newRepresentation -> newRepresentation != null)
.filter(newRepresentation -> shouldOpenRepresentation(newRepresentation))
.forEach(newRepresentation -> DialectUIManager.INSTANCE.openEditor(session, newRepresentation, monitor));
}
}
}

protected void openRepresentation(final Session session, DRepresentation representation, IProgressMonitor monitor) {
DialectUIManager.INSTANCE.openEditor(session, representation, monitor);
}

protected boolean isDataValid(ModelingProject targetModelingProject, Object targetContainer, String targetResourceName, IProgressMonitor monitor) {
if (targetContainer instanceof IProject) {
// We have to check the case of a resource creation at the root of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,55 @@
*******************************************************************************/
package org.obeonetwork.utils.common.ui;

import org.osgi.framework.BundleActivator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

private static BundleContext context;

static BundleContext getContext() {
return context;
}
public class Activator extends AbstractUIPlugin {

// The plug-in ID
public static final String PLUGIN_ID = "org.obeonetwork.utils.common.ui"; //$NON-NLS-1$

// The shared instance
private static Activator plugin;

/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
}

/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}

public static void logError(String message) {
IStatus status = new Status(IStatus.ERROR, plugin.getBundle().getSymbolicName(), message);
plugin.getLog().log(status);
}

public static void logWarning(String message) {
IStatus status = new Status(IStatus.WARNING, plugin.getBundle().getSymbolicName(), message);
plugin.getLog().log(status);
}

public static void logInfo(String message) {
IStatus status = new Status(IStatus.INFO, plugin.getBundle().getSymbolicName(), message);
plugin.getLog().log(status);
}

public static void logError(String message, Throwable e) {
IStatus status = new Status(IStatus.INFO, plugin.getBundle().getSymbolicName(), message, e);
plugin.getLog().log(status);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
*******************************************************************************/
package org.obeonetwork.utils.common.ui.services;

import static java.util.stream.Collectors.toList;
import static org.obeonetwork.utils.common.ui.Activator.logInfo;
import static org.obeonetwork.utils.common.ui.Activator.logWarning;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

import org.eclipse.core.runtime.IProgressMonitor;
Expand All @@ -23,6 +29,8 @@
import org.eclipse.eef.properties.ui.api.EEFTabContents;
import org.eclipse.eef.properties.ui.api.EEFTabbedPropertySheetPage;
import org.eclipse.eef.properties.ui.api.IEEFTabDescriptor;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.RecordingCommand;
Expand Down Expand Up @@ -87,23 +95,70 @@ protected void doExecute() {
}
}

public static DRepresentation createRepresentation(Session session, RepresentationDescription description, String name, EObject context, IProgressMonitor monitor) {
// Ensure that there is no save in progress.
// Otherwise when the representation is added to the resource CreateRepresentationCommand can be problematic.
// Indeed, during the save the eSetDeliver is disabled at some point (ResourceSaveDiagnose.hasDifferentSerialization),
// preventing any adapter to be added to the new representation.
/**
* Executes the given {@link CreateRepresentationCommand} or compound of {@link CreateRepresentationCommand}s.<br>
* <p>
* Joins on the save session job family to make sure that no session save is in progress.<br>
* Otherwise, when the representation is added to the resource,
* CreateRepresentationCommand can be problematic.
* At some point during the save, the eSetDeliver is disabled
* (ResourceSaveDiagnose.hasDifferentSerialization), preventing any adapter from
* being added to the new representation.
* </p>
* <p>
* Warning: This induce the following risk. If no dialect editors are open,
* SaveSessionWhenNoDialectEditorsListener saves the session each time a command
* is executed on the stack. Creating multiple representations with multiple
* commands executed separately and at once may therefore cause a deadlock situation
* (SAFRAN-1134). This is why this method accepts a compound of {@link CreateRepresentationCommand}s.
* </p>
* @param command
* @param session
*/
public static void executeCreateRepresentationCommand(AbstractCommand command, Session session) {
logInfo("Joining on Sirius save session job family.");
try {
Job.getJobManager().join(SaveSessionJob.FAMILY, new NullProgressMonitor());
} catch (OperationCanceledException | InterruptedException e) {
// Ignore. The join is just here to avoid to have a save in progress.
logWarning(String.format("Join Sirius save session jobs aborted for '%s'.", command.getLabel()));
}

CreateRepresentationCommand cmd = new CreateRepresentationCommand(session, description, context, name, monitor);
session.getTransactionalEditingDomain().getCommandStack().execute(cmd);
return cmd.getCreatedRepresentation();
logInfo("Joining on Sirius save session job family passed.");
logInfo(String.format("Executing command '%s'.", command.getLabel()));
session.getTransactionalEditingDomain().getCommandStack().execute(command);
logInfo(String.format("Command '%s' executed.", command.getLabel()));
}

public static DRepresentation createRepresentation(Session session, EObject context, RepresentationDescription representationDescription, String title, IProgressMonitor monitor) {
CreateRepresentationCommand command = new CreateRepresentationCommand(session, representationDescription, context, title, monitor);
executeCreateRepresentationCommand(command, session);
return command.getCreatedRepresentation();
}

public static DRepresentation createRepresentation(Session session, EObject context, String representationDescriptionId, IProgressMonitor monitor) {
CreateRepresentationCommand command = createRepresentationCommand(session, context, representationDescriptionId, monitor);
executeCreateRepresentationCommand(command, session);
return command.getCreatedRepresentation();
}

public static List<DRepresentation> createRepresentations(Session session, List<EObject> contexts, List<String> representationDescriptionIds, IProgressMonitor monitor) {
CompoundCommand compoundCommand = new CompoundCommand();

Iterator<EObject> contextIterator = contexts.iterator();
Iterator<String> representationDescriptionIdIterator = representationDescriptionIds.iterator();
while(contextIterator.hasNext() && representationDescriptionIdIterator.hasNext()) {
compoundCommand.append(createRepresentationCommand(session, contextIterator.next(), representationDescriptionIdIterator.next(), monitor));
}

executeCreateRepresentationCommand(compoundCommand, session);

return compoundCommand.getCommandList().stream()
.map(CreateRepresentationCommand.class::cast)
.map(CreateRepresentationCommand::getCreatedRepresentation)
.collect(toList());
}

private static CreateRepresentationCommand createRepresentationCommand(Session session, EObject context, String representationDescriptionId, IProgressMonitor monitor) {

RepresentationDescription representationDescription = SessionUtils.getRepresentationDescription(session, context, representationDescriptionId);
String title = null;
Expand All @@ -119,7 +174,7 @@ public static DRepresentation createRepresentation(Session session, EObject cont
title = representationDescription.getLabel();
}

return createRepresentation(session, representationDescription, title, context, monitor);
return new CreateRepresentationCommand(session, representationDescription, context, title, monitor);
}

/**
Expand Down
Loading

0 comments on commit a1d7b46

Please sign in to comment.