blob: 6075e15ce1bedb98b1482bdc155d8294b6ed4b04 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 ALL4TEC & CEA LIST.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ALL4TEC & CEA LIST - initial API and implementation
******************************************************************************/
package org.polarsys.esf.core.importmodel.common.commands;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.ChangeCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.window.Window;
import org.eclipse.papyrus.infra.core.resource.ModelMultiException;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.ModelsReader;
import org.eclipse.papyrus.infra.core.sashwindows.di.util.DiResourceImpl;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.profile.ui.dialogs.ElementImportTreeSelectionDialog.ImportAction;
import org.eclipse.papyrus.uml.profile.ui.dialogs.ElementImportTreeSelectionDialog.ImportSpec;
import org.eclipse.papyrus.uml.tools.importsources.PackageImportSourceDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.internal.resource.UMLResourceImpl;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.polarsys.esf.core.importmodel.common.ImportModelCommonActivator;
import org.polarsys.esf.core.importmodel.common.dialogs.UMLImportModelDialog;
import org.polarsys.esf.core.profile.esfarchitectureconcepts.application.ApplyESFArchitectureConceptsAnnotation;
/**
* Specific {@link ChangeCommand} that imports models from file.
*
* @author $Author: ymunoz $
* @version $Revision: 168 $
*/
@SuppressWarnings("restriction")
public class UMLImportModelFromFileCommand
extends AbstractImportModelCommand {
/** Default title of the dialog for selecting models to import. */
private static final String SELECT_MODELS_TO_IMPORT_TITLE = ImportModelCommonActivator.getMessages().getString("UMLImportModelFromFileCommand.dialog.title"); //$NON-NLS-1$
/** Default label of the command Import Models to import. */
private static final String IMPORT_MODELS_LABLE = ImportModelCommonActivator.getMessages().getString("UMLImportModelFromFileCommand.command.label"); //$NON-NLS-1$
/** Default description of the command Import Models to import. */
private static final String IMPORT_MODELS_DESCRIPTION = ImportModelCommonActivator.getMessages().getString(
"UMLImportModelFromFileCommand.command.description"); //$NON-NLS-1$
/** UML extension key. */
private static final String UML_EXTENSION_KEY = "*.uml"; //$NON-NLS-1$
/** UML extension value. */
private static final String UML_EXTENSION_VALUE = "UML (*.uml)"; //$NON-NLS-1$
/** Underscore. */
private static final String UNDERSCORE = "_"; //$NON-NLS-1$
/**
* Default constructor.
*
* @param pEditingDomain
* The editing domain
* @param pSelectedElements
* The selected elements
* @param pSelection
* The selection
*/
public UMLImportModelFromFileCommand(
final TransactionalEditingDomain pEditingDomain,
final List<EObject> pSelectedElements,
final List<?> pSelection) {
super(
pEditingDomain,
pSelectedElements,
new UMLImportModelRunnable(pSelection, pSelectedElements),
IMPORT_MODELS_LABLE,
IMPORT_MODELS_DESCRIPTION);
}
/**
* The inner class which provides the dialog and operation for importing UML models.
*
* @author $Author: ymunoz $
* @version $Revision: 168 $
*/
private static class UMLImportModelRunnable
implements Runnable {
/** The selection of elements. */
private Collection<?> mSelection = null;
/** The model where the others models will be imported. */
private Model mModelTarget = null;
/**
* Default constructor.
*
* @param pSelection
* The selection
* @param pSelectedElements
* The selected Elements
*/
UMLImportModelRunnable(final List<?> pSelection, final List<EObject> pSelectedElements) {
mSelection = pSelection;
if (pSelectedElements.isEmpty()) {
throw new IllegalArgumentException("Selected element is empty");
} else if (!(pSelectedElements.get(0) instanceof Model)) {
throw new IllegalArgumentException("Selected element is not a Model object");
} else {
mModelTarget = (Model) pSelectedElements.get(0);
}
}
/**
* Open dialog for selecting the UML models. And in the end, they are duplicated and imported.
*/
@Override
public void run() {
Shell vShell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
Map<String, String> vExtensionFilters = new LinkedHashMap<String, String>();
vExtensionFilters.put(UML_EXTENSION_KEY, UML_EXTENSION_VALUE);
Collection<?> vSelection = mSelection;
Collection<Package> vModels = PackageImportSourceDialog.open(vShell, SELECT_MODELS_TO_IMPORT_TITLE, vSelection, vExtensionFilters);
// Remove self-import
vModels = removeSelfImport(vModels);
if ((vModels != null) && (!vModels.isEmpty())) {
if (!vModels.isEmpty()) {
UMLImportModelDialog vDialog = new UMLImportModelDialog(
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
vModels);
if (Window.OK == vDialog.open()) {
// Get the selected packages from UML model to import
Collection<ImportSpec<Package>> vResult = vDialog.getResult();
for (ImportSpec<Package> vResultElement : vResult) {
Package vSelectedPackage = vResultElement.getElement();
if (ImportAction.IMPORT == vResultElement.getAction()) {
Package vImportedPackage = importPackage(vSelectedPackage);
ApplyESFArchitectureConceptsAnnotation
.applyAnnotationOnUMLModel((Model) vImportedPackage);
}
}
}
}
}
}
/**
* Remove the model target where the others models will be imported.
*
* @param pModels
* The models to import
* @return The models without itself (model target)
*/
private Collection<Package> removeSelfImport(final Collection<Package> pModels) {
Collection<Package> vUpdatedModels = pModels;
if ((pModels != null) && (!pModels.isEmpty())) {
URI vModelTargetURI = EcoreUtil.getURI(mModelTarget);
Iterator<Package> vModels = pModels.iterator();
Boolean vRemoved = false;
while (!vRemoved && vModels.hasNext()) {
Package vModel = vModels.next();
if (EcoreUtil.getURI(vModel).equals(vModelTargetURI)) {
vUpdatedModels.remove(vModel);
vRemoved = true;
}
}
}
return vUpdatedModels;
}
/**
* Duplicate the file of each UML model.
*
* @param pModels
* The UML models
* @return The UML models of duplicate files
* @throws ModelMultiException
* This exception is thrown when an operation performed on several Models fails on
* one or more of these models.
*/
private Collection<Package> duplicateModels(final Collection<Package> pModels) throws ModelMultiException {
Collection<Package> vDuplicateModels = new ArrayList<Package>();
for (Package vModel : pModels) {
// Load the model to be duplicated
ModelSet vModelSet = new ModelSet();
ModelsReader vModelsReader = new ModelsReader();
vModelsReader.readModel(vModelSet);
vModelSet.loadModels(EcoreUtil.getURI(vModel).trimFragment());
EcoreUtil.resolveAll(vModelSet);
/*
* Retrieve di resources and get its file's path without
* extension for building a new path of the duplicate model
*/
Resource vDiResource = getSpecificResource(DiResourceImpl.class, vModelSet.getResources());
if (vDiResource != null) {
URI vDiURI = vDiResource.getURI();
String vDiExtension = vDiURI.fileExtension();
URI vURIWithoutExtension = vDiURI.trimFileExtension();
Timestamp vTimestamp = new Timestamp(GregorianCalendar.getInstance().getTime().getTime());
String vNewURIString = vURIWithoutExtension.toString() + UNDERSCORE + vTimestamp.getTime();
URI vNewURIWithoutExtension = URI.createURI(vNewURIString);
URI vNewDiURI = vNewURIWithoutExtension.appendFileExtension(vDiExtension);
try {
vModelSet.saveAs(vNewDiURI);
} catch (final IOException pException) {
ImportModelCommonActivator.logError(
"Error during the saving of the new models", pException); //$NON-NLS-1$
}
/*
* Retrieve the duplicate model to import
*/
UMLResource vUMLResource = (UMLResource) getSpecificResource(UMLResourceImpl.class, vModelSet.getResources());
if (vUMLResource != null) {
EObject vDuplicateModel = vUMLResource.getContents().get(0);
vDuplicateModels.add((Package) vDuplicateModel);
}
}
}
return vDuplicateModels;
}
/**
* Creates a PackageImport in the current package, which refers to the
* selected package.
*
* @param pPackage
* The selected package
* @return The imported package
*/
protected Package importPackage(final Package pPackage) {
Package vImportedPackage = null;
if (mModelTarget != null) {
PackageImport vPackageImport = UMLFactory.eINSTANCE.createPackageImport();
vImportedPackage = EMFHelper.reloadIntoContext(pPackage, mModelTarget);
((Package) mModelTarget).getPackageImports().add(vPackageImport);
vPackageImport.setImportedPackage(vImportedPackage);
}
return vImportedPackage;
}
/**
* Retrieve the resource specified from a resources' list.
*
* @param pResourceType
* The resource type
* @param pResources
* The list of resources
* @return The resource specified
*/
private Resource getSpecificResource(
final Class<? extends Resource> pResourceType,
final EList<Resource> pResources) {
Resource vSpecificResource = null;
for (Resource vResource : pResources) {
if (vResource.getClass() == pResourceType) {
vSpecificResource = vResource;
break;
}
}
return vSpecificResource;
}
}
}