| /** |
| ******************************************************************************** |
| * Copyright (c) 2019, 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.common; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.Dictionary; |
| import java.util.Hashtable; |
| import java.util.Map; |
| |
| import org.eclipse.app4mc.amalthea.converters.common.base.ICache; |
| import org.eclipse.app4mc.amalthea.converters.common.base.IConverter; |
| import org.eclipse.app4mc.amalthea.converters.common.base.IPostProcessor; |
| import org.eclipse.app4mc.util.sessionlog.SessionLogger; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.jdom2.Document; |
| import org.osgi.service.component.ComponentFactory; |
| import org.osgi.service.component.ComponentInstance; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Reference; |
| |
| @Component(service = MigrationProcessor.class) |
| public class MigrationProcessor { |
| |
| private static final String NEWLINE = System.getProperty("line.separator"); |
| |
| @Reference(target = "(component.factory=" + ServiceConstants.MODEL_MIGRATION_FACTORY + ")") |
| ComponentFactory<ModelMigration> factory; |
| |
| @Reference(target = "(component.factory=" + "org.eclipse.app4mc.amalthea.sessionlog.factory" + ")") |
| ComponentFactory<SessionLogger> loggerFactory; |
| |
| /** |
| * Execute the migration for the provided {@link MigrationSettings}. |
| * |
| * @param settings The {@link MigrationSettings} containing the settings for the |
| * migration. |
| * @param monitor The progress monitor to give feedback to the caller. Can be |
| * <code>null</code>. |
| * @return A {@link MigrationStatusCode} indicating the status of the migration. |
| * @throws MigrationException In case saving the migrated files fails. |
| */ |
| public int execute(MigrationSettings settings, IProgressMonitor monitor) { |
| |
| ComponentInstance<SessionLogger> loggerInstance = loggerFactory.newInstance(null); |
| SessionLogger logger = loggerInstance.getInstance(); |
| |
| settings.getMigModelFiles().forEach(f -> f.setSessionLogger(logger)); |
| |
| try { |
| if (monitor != null) { |
| monitor.setTaskName("Collecting information for intermediate migration steps"); |
| } |
| |
| // check if a migration needs to be executed |
| Map<String, String> migStepEntries = MigrationHelper.generateMigrationSteps( |
| settings.getInputModelVersion(), |
| settings.getMigrationModelVersion()); |
| |
| if (migStepEntries.size() == 0) { |
| logger.error("Migration not supported for the selected model versions. \nInput Model version : \"{0}\" Output Model Version : \"{1}\"", |
| settings.getInputModelVersion(), |
| settings.getMigrationModelVersion()); |
| |
| return MigrationStatusCode.UNSUPPORTED_MODEL_VERSIONS; |
| } |
| |
| SubMonitor subMonitor = monitor != null ? SubMonitor.convert(monitor, migStepEntries.size() + 1) : null; |
| |
| Map<File, Document> fileDocumentMapping = settings.getMigModelFilesMap(); |
| |
| // info log |
| StringBuilder builder = new StringBuilder(); |
| builder.append(NEWLINE); |
| builder.append("*******************************************************************************************************************"); |
| builder.append(NEWLINE); |
| builder.append("\t\t Starting model migration for the following AMALTHEA models: "); |
| builder.append(NEWLINE); |
| for (final File modelFile : fileDocumentMapping.keySet()) { |
| builder.append("\t\t -- "); |
| builder.append(modelFile.getAbsolutePath()); |
| builder.append(NEWLINE); |
| } |
| builder.append(NEWLINE); |
| builder.append("*******************************************************************************************************************"); |
| builder.append(NEWLINE); |
| logger.info("{0}", builder); |
| |
| boolean conversionPerformed = false; |
| String currentModelVersion = settings.getInputModelVersion(); |
| while (!currentModelVersion.equals(settings.getMigrationModelVersion())) { |
| |
| if (subMonitor != null && subMonitor.isCanceled()) { |
| return MigrationStatusCode.CANCEL; |
| } |
| |
| // define the target filters and create the ModelMigration component instance |
| Dictionary<String, Object> properties = new Hashtable<>(); |
| String inputFilterExp = "(input_model_version=" + currentModelVersion + ")"; |
| String inputOuputFilterExpression = "(&(input_model_version=" + currentModelVersion + ")(output_model_version=" + migStepEntries.get(currentModelVersion) + "))"; |
| properties.put(ServiceConstants.INPUT_MODEL_VERSION_PROPERTY, currentModelVersion); |
| properties.put(ServiceConstants.OUTPUT_MODEL_VERSION_PROPERTY, migStepEntries.get(currentModelVersion)); |
| properties.put("caches.target", inputFilterExp); |
| properties.put("converter.target", inputOuputFilterExpression); |
| properties.put("postProcessor.target", inputOuputFilterExpression); |
| ComponentInstance<ModelMigration> newInstance = factory.newInstance(properties); |
| ModelMigration modelMigration = newInstance.getInstance(); |
| |
| String outputModelVersion = modelMigration.getOutputModelVersion(); |
| |
| // execute migration |
| if (subMonitor != null) { |
| subMonitor.setTaskName("Migrating AMALTHEA models from : " + currentModelVersion + " to " + outputModelVersion); |
| } |
| |
| logger.info("=========== START: Migrating AMALTHEA models from : {0} to {1} ========== ", currentModelVersion, outputModelVersion); |
| |
| // build caches |
| |
| // build up the cache for the current file set |
| for (ICache cache : modelMigration.getCaches()) { |
| // clear the cache to avoid any side effects if a previous migration failed with an exception |
| cache.clearCacheMap(); |
| |
| cache.buildCache(fileDocumentMapping); |
| } |
| |
| // execute conversion |
| for (IConverter converter : modelMigration.getConverter()) { |
| for (File file : fileDocumentMapping.keySet()) { |
| converter.convert(file, fileDocumentMapping, modelMigration.getCaches()); |
| conversionPerformed = true; |
| } |
| } |
| |
| for (IPostProcessor postProcessor : modelMigration.getPostProcessor()) { |
| postProcessor.process(fileDocumentMapping); |
| } |
| |
| logger.info("=========== END: Migrating AMALTHEA models from : {0} to {1} =========== \n\r", currentModelVersion, outputModelVersion); |
| |
| if (currentModelVersion.equals(outputModelVersion)) { |
| // if the output is already the current model version, |
| // we need to update the output model version to ensure |
| // that we exit the loop |
| outputModelVersion = migStepEntries.get(currentModelVersion); |
| |
| } |
| currentModelVersion = outputModelVersion; |
| |
| // clear the cache to ensure there are not leftovers on the next migration |
| for (ICache cache : modelMigration.getCaches()) { |
| cache.clearCacheMap(); |
| } |
| |
| if (subMonitor != null) { |
| subMonitor.worked(1); |
| } |
| |
| // destroy the created component instance |
| newInstance.dispose(); |
| } |
| |
| if (conversionPerformed) { |
| if (subMonitor != null) { |
| subMonitor.setTaskName("Saving migrated AMALTHEA model files "); |
| } |
| |
| try { |
| MigrationHelper.saveFiles(settings, logger); |
| } catch (IOException e) { |
| throw new MigrationException("Error on saving migrated files.", e); |
| } finally { |
| settings.close(); |
| } |
| } |
| |
| if (subMonitor != null) { |
| subMonitor.worked(1); |
| } |
| |
| return MigrationStatusCode.OK; |
| } finally { |
| logger.info("Migration session finished"); |
| |
| String dateToStr = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss").format(new Date()); |
| logger.flush(new File(settings.getOutputDirectoryLocation(), "ModelMigration__" + dateToStr + ".log")); |
| |
| loggerInstance.dispose(); |
| } |
| } |
| |
| } |