diff options
Diffstat (limited to 'plugins/cdo/bundles/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/importer/ModelImporter.java')
-rwxr-xr-x | plugins/cdo/bundles/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/importer/ModelImporter.java | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/plugins/cdo/bundles/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/importer/ModelImporter.java b/plugins/cdo/bundles/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/importer/ModelImporter.java new file mode 100755 index 00000000..d66e8731 --- /dev/null +++ b/plugins/cdo/bundles/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/importer/ModelImporter.java @@ -0,0 +1,384 @@ +/***************************************************************************** + * Copyright (c) 2013, 2017 CEA LIST 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: + * CEA LIST - Initial API and implementation + * Christian W. Damus (CEA) - bug 429242 + * Christian W. Damus (CEA) - bug 422257 + * Eike Stepper (CEA) - bug 466520 + * + *****************************************************************************/ +package org.eclipse.papyrus.cdo.internal.core.importer; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.emf.cdo.explorer.CDOExplorerUtil; +import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.common.util.BasicDiagnostic; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.common.util.DiagnosticChain; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.cdo.core.importer.IModelImportMapping; +import org.eclipse.papyrus.cdo.core.importer.IModelImporter; +import org.eclipse.papyrus.cdo.core.importer.IModelTransferConfiguration; +import org.eclipse.papyrus.cdo.core.importer.IModelTransferNode; +import org.eclipse.papyrus.cdo.core.importer.IModelTransferOperation; +import org.eclipse.papyrus.cdo.internal.core.Activator; +import org.eclipse.papyrus.cdo.internal.core.CDOUtils; +import org.eclipse.papyrus.cdo.internal.core.controlmode.CDOControlModeParticipant; +import org.eclipse.papyrus.cdo.internal.core.l10n.Messages; +import org.eclipse.papyrus.cdo.internal.core.resource.CDOSashModelProvider; +import org.eclipse.papyrus.infra.core.sashwindows.di.DiPackage; +import org.eclipse.papyrus.infra.core.sashwindows.di.PageList; +import org.eclipse.papyrus.infra.core.sashwindows.di.SashModel; +import org.eclipse.papyrus.infra.core.sashwindows.di.SashWindowsMngr; +import org.eclipse.papyrus.infra.core.sashwindows.di.util.DiUtils; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; + +import com.google.common.collect.Sets; + +/** + * This is the ModelImporter type. Enjoy. + */ +public class ModelImporter implements IModelImporter { + + protected static final ContentType DI_CONTENT = new ContentType("DI"); //$NON-NLS-1$ + + protected static final ContentType UML_CONTENT = new ContentType("UML"); //$NON-NLS-1$ + + protected static final ContentType NOTATION_CONTENT = new ContentType("Notation"); //$NON-NLS-1$ + + protected static final ContentType UNKNOWN_CONTENT = new ContentType("unknown"); //$NON-NLS-1$ + + public ModelImporter() { + super(); + } + + @Override + public Diagnostic importModels(final IModelImportMapping mapping) { + BasicDiagnostic result = new BasicDiagnostic(); + + add(result, mapping.getConfiguration().validate()); + add(result, mapping.validate()); + + if (result.getSeverity() < Diagnostic.ERROR) { + add(result, mapping.getConfiguration().getOperationContext().run(new IModelTransferOperation() { + + @Override + public Diagnostic run(IProgressMonitor monitor) { + return doImport(mapping, monitor); + } + })); + } + + return result; + } + + protected Diagnostic doImport(IModelImportMapping mapping, IProgressMonitor monitor) { + BasicDiagnostic result = new BasicDiagnostic(); + IModelTransferConfiguration configuration = mapping.getConfiguration(); + + // by the time the configuration has analyzed every model to be + // imported, all proxies have been resolved that can be. So, + // there's no need for a further EcoreUtil.resolveAll() or such + + // 1/resource for import and 1/resource for sub-unit proxies + // 1 for each transaction commit, 1 for saving affected non-imported models, and 1 for clean-up + SubMonitor sub = SubMonitor.convert(monitor, Messages.ModelImporter_4, configuration.getModelsToTransfer().size() + 4); + + CDOCheckout checkout = mapping.getCheckout(); + CDOTransaction transaction = checkout.openTransaction(new ResourceSetImpl()); + ResourceSet destination = transaction.getResourceSet(); + + try { + for (IModelTransferNode model : configuration.getModelsToTransfer()) { + add(result, importModel(model, configuration.getResourceSet(), mapping.getMapping(model), transaction, sub.newChild(1))); + } + + try { + transaction.commit(sub.newChild(1)); + + // save sash resources (if any) + for (Resource next : destination.getResources()) { + // sash resource would have been saved by commit if it were a CDO URI + if (DependencyAdapter.isDIResource(next) && !CDOUtils.isCDOURI(next.getURI())) { + next.save(null); + } + } + } catch (Exception e) { + result.add(new BasicDiagnostic(IStatus.ERROR, Activator.PLUGIN_ID, 0, Messages.ModelImporter_5, new Object[] { e })); + } + + // can't create CDO-style proxies until the resources have been committed, because only then + // will the objects be persisted and have OIDs to reference + boolean hasSubUnits = false; + for (IModelTransferNode model : configuration.getModelsToTransfer()) { + if (createSubUnitProxies(model, mapping.getMapping(model), transaction, sub.newChild(1))) { + hasSubUnits = true; + } + } + if (hasSubUnits) { + try { + transaction.commit(sub.newChild(1)); + } catch (CommitException e) { + result.add(new BasicDiagnostic(IStatus.ERROR, Activator.PLUGIN_ID, 0, Messages.ModelImporter_5, new Object[] { e })); + } + } else { + sub.worked(1); // nothing to commit but still count progress + } + + try { + saveNonimportedModels(mapping, transaction, sub.newChild(1)); + } catch (Exception e) { + result.add(new BasicDiagnostic(IStatus.ERROR, Activator.PLUGIN_ID, 0, Messages.ModelImporter_6, new Object[] { e })); + } + } finally { + EMFHelper.unload(configuration.getResourceSet()); + CDOUtils.unload(transaction); + transaction.close(); + EMFHelper.unload(destination); + sub.worked(1); + } + + sub.done(); + + return result; + } + + protected Diagnostic importModel(IModelTransferNode model, ResourceSet rset, IPath toPath, CDOTransaction transaction, IProgressMonitor monitor) { + BasicDiagnostic result = new BasicDiagnostic(); + + IPath basePath = toPath.removeFileExtension(); + + SubMonitor sub = SubMonitor.convert(monitor, model.getName(), model.getResourceURIs().size()); + + for (URI next : model.getResourceURIs()) { + Resource destination = transaction.getOrCreateResource(basePath.addFileExtension(next.fileExtension()).toString()); + Resource source = rset.getResource(next, true); + + if (model.getConfiguration().isStripSashModelContent() && DependencyAdapter.isDIResource(source)) { + // import *.di content into the *.sash + CDOCheckout checkout = CDOExplorerUtil.getCheckout(transaction); + URI sashURI = new CDOSashModelProvider().initialize(checkout).getSashModelURI(destination.getURI()); + ResourceSet dset = destination.getResourceSet(); + Resource sashResource = dset.getURIConverter().exists(sashURI, null) ? dset.getResource(sashURI, true) : null; + if (sashResource == null) { + sashResource = dset.createResource(sashURI); + } + destination = sashResource; + } + + add(result, importResource(source, destination)); + sub.worked(1); + } + + sub.done(); + + return result; + } + + protected boolean createSubUnitProxies(IModelTransferNode model, IPath toPath, CDOTransaction transaction, IProgressMonitor monitor) { + boolean result; + + IPath basePath = toPath.removeFileExtension(); + URI uri = model.getPrimaryResourceURI(); + + SubMonitor sub = SubMonitor.convert(monitor, model.getName(), 1); + + Resource destination = transaction.getResource(basePath.addFileExtension(uri.fileExtension()).toString()); + CDOControlModeParticipant.IUpdate update = new CDOControlModeParticipant().getProxyCrossReferencesUpdate(destination); + result = !update.isEmpty(); + update.apply(); // no harm in applying an empty update + sub.worked(1); + + sub.done(); + + return result; + } + + protected Diagnostic importResource(Resource source, Resource destination) { + if (!destination.getContents().isEmpty()) { + ContentType contentType = getContentType(source); + if (contentType == DI_CONTENT) { + mergeDIContent(source, destination); + } else { + // just append the additional content + destination.getContents().addAll(source.getContents()); + } + } else { + destination.getContents().addAll(source.getContents()); + } + + return Diagnostic.OK_INSTANCE; + } + + /** + * Determines the content-type of a resource for the purpose of combining + * content. + * + * @param resource + * a resource to be combined with existing content + * + * @return the content type + */ + protected ContentType getContentType(Resource resource) { + ContentType result = UNKNOWN_CONTENT; + + for (EObject next : resource.getContents()) { + EPackage ePackage = next.eClass().getEPackage(); + if (ePackage == DiPackage.eINSTANCE) { + result = DI_CONTENT; + break; + } + if (ePackage.getName().equalsIgnoreCase("uml")) { //$NON-NLS-1$ + result = UML_CONTENT; + break; + } + if (ePackage.getName().equalsIgnoreCase("notation")) { //$NON-NLS-1$ + result = NOTATION_CONTENT; + break; + } + } + + return result; + } + + protected void mergeDIContent(Resource source, Resource destination) { + // snip out the source window manager and get its counterpart + SashWindowsMngr srcMngr = DiUtils.lookupSashWindowsMngr(source); + EcoreUtil.remove(srcMngr); + SashWindowsMngr dstMngr = DiUtils.lookupSashWindowsMngr(destination); + + // merge the window manager contents + if (dstMngr == null) { + destination.getContents().add(0, srcMngr); + } else { + SashModel dstModel = dstMngr.getSashModel(); + SashModel srcModel = srcMngr.getSashModel(); + + if (dstModel == null) { + dstMngr.setSashModel(srcModel); + } else { + dstModel.getWindows().addAll(srcModel.getWindows()); + if (dstModel.getCurrentSelection() == null) { + dstModel.setCurrentSelection(srcModel.getCurrentSelection()); + } + } + + PageList dstPages = dstMngr.getPageList(); + PageList srcPages = srcMngr.getPageList(); + + if (dstPages == null) { + dstMngr.setPageList(srcPages); + } else { + dstPages.getAvailablePage().addAll(srcPages.getAvailablePage()); + } + } + + // and add all of the tables and other content + destination.getContents().addAll(source.getContents()); + } + + protected Diagnostic saveNonimportedModels(IModelImportMapping mapping, CDOTransaction transaction, IProgressMonitor monitor) { + IModelTransferConfiguration configuration = mapping.getConfiguration(); + + BasicDiagnostic result = new BasicDiagnostic(); + + Collection<IModelTransferNode> imported = configuration.getModelsToTransfer(); + Set<IModelTransferNode> nonImported = Sets.newHashSet(); + + for (IModelTransferNode next : configuration.getModelsToTransfer()) { + for (IModelTransferNode dependent : next.getDependents()) { + if (!imported.contains(dependent)) { + nonImported.add(dependent); + } + } + } + + if (!nonImported.isEmpty()) { + SubMonitor sub = SubMonitor.convert(monitor, Messages.ModelImporter_9, nonImported.size()); + + ResourceSet rset = configuration.getResourceSet(); + + try { + for (IModelTransferNode next : nonImported) { + for (URI uri : next.getResourceURIs()) { + Resource resource = rset.getResource(uri, false); + + // if the resource is modified, then we imported it, so + // don't save + if ((resource != null) && !resource.isModified()) { + try { + resource.save(null); + } catch (Exception e) { + add(result, new BasicDiagnostic(IStatus.ERROR, Activator.PLUGIN_ID, 0, Messages.ModelImporter_10, new Object[] { e })); + } + } + } + + sub.worked(1); + } + } finally { + sub.done(); + } + } + + return result; + } + + private static void add(DiagnosticChain diagnostics, Diagnostic diagnostic) { + if (diagnostic.getSeverity() > Diagnostic.OK) { + diagnostics.merge(diagnostic); + } + } + + // + // Nested types + // + + protected static class ContentType { + + private final String name; + + protected ContentType(String name) { + this.name = name; + } + + public final String getName() { + return name; + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof ContentType) && ((ContentType) obj).getName().equals(getName()); + } + + @Override + public String toString() { + return getName() + " content"; //$NON-NLS-1$ + } + } +} |