/** | |
******************************************************************************** | |
* Copyright (c) 2015-2021 Robert Bosch GmbH and others. | |
* | |
* This program and the accompanying materials are made | |
* available under the terms of the Eclipse Public License 2.0 | |
* which is available at https://www.eclipse.org/legal/epl-2.0/ | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
* | |
* Contributors: | |
* Robert Bosch GmbH - initial API and implementation | |
******************************************************************************** | |
*/ | |
package org.eclipse.app4mc.amalthea.converters.ui.jobs; | |
import java.util.ArrayList; | |
import java.util.LinkedHashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.stream.Collectors; | |
import org.eclipse.app4mc.amalthea.converters.common.MigrationException; | |
import org.eclipse.app4mc.amalthea.converters.common.MigrationHelper; | |
import org.eclipse.app4mc.amalthea.converters.common.MigrationInputFile; | |
import org.eclipse.app4mc.amalthea.converters.common.MigrationProcessor; | |
import org.eclipse.app4mc.amalthea.converters.common.MigrationSettings; | |
import org.eclipse.app4mc.amalthea.converters.common.MigrationStatusCode; | |
import org.eclipse.app4mc.amalthea.converters.common.utils.ModelVersion; | |
import org.eclipse.app4mc.amalthea.converters.ui.dialog.MigrationResultDialog; | |
import org.eclipse.core.resources.IProject; | |
import org.eclipse.core.resources.IResource; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IProgressMonitor; | |
import org.eclipse.core.runtime.IStatus; | |
import org.eclipse.core.runtime.NullProgressMonitor; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.core.runtime.Status; | |
import org.eclipse.core.runtime.jobs.Job; | |
import org.eclipse.swt.widgets.Display; | |
public class ModelMigrationJob extends Job { | |
private final MigrationProcessor migrationProcessor; | |
private final ArrayList<MigrationSettings> migrationSettings = new ArrayList<>(); | |
private IProject project; | |
public ModelMigrationJob(String name, MigrationProcessor migrationProcessor, MigrationSettings migrationSettings, IProject project) { | |
super(name); | |
this.migrationProcessor = migrationProcessor; | |
this.project = project; | |
Map<String, Map<String, List<MigrationInputFile>>> collect = migrationSettings.getMigModelFiles().stream() | |
.collect(Collectors.groupingBy( | |
mig -> mig.getOriginalFile().getParent(), | |
Collectors.groupingBy(MigrationInputFile::getModelVersion))); | |
for (Map.Entry<String, Map<String, List<MigrationInputFile>>> folderMapping : collect.entrySet()) { | |
for (Map.Entry<String, List<MigrationInputFile>> versionMapping : folderMapping.getValue().entrySet()) { | |
MigrationSettings settings = new MigrationSettings(); | |
settings.setInputModelVersion(versionMapping.getKey()); | |
settings.setMigrationModelVersion(migrationSettings.getMigrationModelVersion()); | |
settings.setProject(migrationSettings.getProject()); | |
settings.setOutputDirectoryLocation(versionMapping.getValue().get(0).getOriginalFile().getParent()); | |
settings.setCreateBackupFile(migrationSettings.isCreateBackupFile()); | |
settings.getMigModelFiles().addAll(versionMapping.getValue()); | |
this.migrationSettings.add(settings); | |
} | |
} | |
} | |
@Override | |
protected IStatus run(final IProgressMonitor monitor) { | |
boolean cancelled = false; | |
LinkedHashMap<String, String> results = new LinkedHashMap<>(); | |
try { | |
for (MigrationSettings settings : this.migrationSettings) { | |
String ident = settings.getProject().toURI().relativize(settings.getMigModelFiles().get(0).getOriginalFile().getParentFile().toURI()).getPath(); | |
if (cancelled) { | |
results.put( | |
ident, | |
"Migration cancelled."); | |
continue; | |
} | |
boolean inputValid = true; | |
try { | |
inputValid = MigrationHelper.isInputModelVersionValid(settings); | |
} catch (MigrationException e) { | |
results.put( | |
ident, | |
"Error during migration: " + e.getLocalizedMessage()); | |
continue; | |
} | |
if (!inputValid) { | |
results.put( | |
ident, | |
"Model migration stopped as selected model files belong to different versions."); | |
continue; | |
} else { | |
if (settings.getInputModelVersion() != null | |
&& settings.getInputModelVersion().equals(settings.getMigrationModelVersion())) { | |
results.put( | |
ident, | |
"Selected models are compatible to latest AMALTHEA meta-model version (" | |
+ settings.getMigrationModelVersion() | |
+ "). It is not required to migrate these models !!"); | |
continue; | |
} else if (!ModelVersion.isValidVersion(settings.getMigrationModelVersion())) { | |
results.put( | |
ident, | |
"The AMALTHEA meta-model version (" | |
+ settings.getMigrationModelVersion() | |
+ ") is not supported by the migration component !!"); | |
continue; | |
} else if (settings.getInputModelVersion() != null | |
&& settings.getMigrationModelVersion() != null | |
&& ModelVersion.getModelVersion(settings.getInputModelVersion()).ordinal() | |
> ModelVersion.getModelVersion(settings.getMigrationModelVersion()).ordinal()) { | |
results.put( | |
ident, | |
"The target model version (" | |
+ settings.getMigrationModelVersion() | |
+ ") is older than the input model version (" | |
+ settings.getInputModelVersion() + "). " | |
+ "A backwards migration is not supported !!"); | |
continue; | |
} else { | |
// Rename or copy the original files to filename_currentversion.amxmi | |
boolean backupSucceeded = true; | |
if (settings.isCreateBackupFile()) { | |
for (MigrationInputFile input : settings.getMigModelFiles()) { | |
backupSucceeded = MigrationHelper.createBackupFile(input); | |
} | |
} | |
if (backupSucceeded) { | |
try { | |
int result = migrationProcessor.execute(settings, monitor); | |
switch (result) { | |
case MigrationStatusCode.UNSUPPORTED_MODEL_VERSIONS: | |
results.put( | |
ident, | |
"Migration not supported for the selected model versions. Input Model version : \"" | |
+ settings.getInputModelVersion() | |
+ "\" Output Model Version : \"" | |
+ settings.getMigrationModelVersion() + "\""); | |
continue; | |
case MigrationStatusCode.CANCEL: | |
results.put( | |
ident, | |
"Migration cancelled."); | |
cancelled = true; | |
continue; | |
case MigrationStatusCode.ERROR: | |
results.put( | |
ident, | |
"Error during migration !!"); | |
continue; | |
case MigrationStatusCode.OK: | |
results.put( | |
ident, | |
"Model Migration successful !!"); | |
continue; | |
} | |
} catch (MigrationException e) { | |
results.put( | |
ident, | |
"Error during migration: " + e.getLocalizedMessage()); | |
continue; | |
} | |
} else { | |
// do nothing as we could not backup source and this can data loss to user if he | |
// does not intend to loose his original model file | |
results.put( | |
ident, | |
"Migration Stopped : Source files could not be backed up before migration in " | |
+ settings.getMigModelFiles().get(0).getProjectRelativePath()); | |
continue; | |
} | |
} | |
} | |
} | |
} finally { | |
this.migrationSettings.forEach(MigrationSettings::close); | |
} | |
Display.getDefault().asyncExec(() -> { | |
MigrationResultDialog dialog = new MigrationResultDialog(Display.getDefault().getActiveShell(), results); | |
dialog.open(); | |
if (this.project != null) { | |
try { | |
this.project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); | |
} catch (final CoreException e) { | |
Platform.getLog(getClass()).error(e.getLocalizedMessage(), e); | |
} | |
} | |
}); | |
return Status.OK_STATUS; | |
} | |
@Override | |
public boolean belongsTo(final Object family) { | |
if (family != null && family.equals(IMigrationJobConstants.FAMILY)) { | |
return true; | |
} | |
return super.belongsTo(family); | |
} | |
} |