| /******************************************************************************* |
| * |
| * Copyright (c) 2018, 2021 Robert Bosch GmbH. |
| * |
| * 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.transformation.registry; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import org.eclipse.app4mc.transformation.ServiceConstants; |
| import org.eclipse.app4mc.transformation.TransformationConstants; |
| import org.eclipse.app4mc.transformation.transformers.Model2ModelRootTransformer; |
| import org.eclipse.app4mc.transformation.transformers.Model2TextRootTransformer; |
| import org.eclipse.app4mc.util.sessionlog.SessionLogWriter; |
| import org.eclipse.app4mc.util.sessionlog.SessionLogger; |
| import org.osgi.service.component.annotations.Activate; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.ConfigurationPolicy; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.annotations.ReferenceCardinality; |
| import org.osgi.service.component.annotations.ReferencePolicy; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventAdmin; |
| import org.osgi.service.log.Logger; |
| import org.osgi.service.log.LoggerFactory; |
| |
| /** |
| * Configured OSGi service component to consume root transformer and start the |
| * transformation process once all configured dependencies are resolved. |
| * <p> |
| * Can also be used outside an OSGi context. For this case there is API provided |
| * that allows to register root transformer and configurations and start the |
| * transformation programmatically. |
| * </p> |
| */ |
| @Component( |
| configurationPid = ServiceConstants.SESSION_CONFIGURATION_PID, |
| configurationPolicy = ConfigurationPolicy.REQUIRE, |
| service=TransformerRegistry.class) |
| public class TransformerRegistry { |
| |
| private String logFilePath; |
| |
| private AtomicBoolean transformationStarted = new AtomicBoolean(false); |
| |
| LoggerFactory factory; |
| Logger osgiLogger; |
| |
| @Reference |
| EventAdmin eventAdmin; |
| |
| SessionLogger logger; |
| |
| String sessionName; |
| |
| private List<Model2ModelRootTransformer> m2mTransformers = new ArrayList<>(); |
| private List<Model2TextRootTransformer> m2tTransformers = new ArrayList<>(); |
| |
| @Activate |
| void activate(Map<String, ?> properties) { |
| this.logFilePath = (String) properties.get(TransformationConstants.LOG_FILE); |
| |
| this.sessionName = (String) properties.get(ServiceConstants.SESSION_ID); |
| } |
| |
| @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) |
| void setLogger(LoggerFactory factory) { |
| this.factory = factory; |
| this.osgiLogger = factory.getLogger(getClass()); |
| } |
| |
| void unsetLogger(LoggerFactory loggerFactory) { |
| if (this.factory == loggerFactory) { |
| this.factory = null; |
| this.osgiLogger = null; |
| } |
| } |
| |
| /** |
| * Set the {@link SessionLogger} that should be used to write the session log of |
| * the transformation. To write the log, the {@link SessionLogger} needs to have |
| * {@link SessionLogWriter} set. |
| * |
| * @param logger The {@link SessionLogger} that should be used to write the |
| * session log of the transformation. |
| */ |
| @Reference(name = "sessionLogger") |
| public void setSessionLogger(SessionLogger logger) { |
| this.logger = logger; |
| } |
| |
| // Model 2 Text |
| |
| @Reference(name = "m2mTransformers", cardinality = ReferenceCardinality.MULTIPLE) |
| public void registerM2mTransformer(Model2ModelRootTransformer transformer) { |
| this.m2mTransformers.add(transformer); |
| } |
| |
| // Model 2 Text |
| |
| @Reference(name = "m2tTransformers", cardinality = ReferenceCardinality.MULTIPLE) |
| public void registerM2tTransformer(Model2TextRootTransformer transformer) { |
| m2tTransformers.add(transformer); |
| } |
| |
| /** |
| * Start the transformation within an OSGi context. The call of this method |
| * assumes that the {@link TransformerRegistry} instance is configured via OSGi |
| * component configuration. |
| */ |
| public void startTransformation() { |
| if (this.transformationStarted.compareAndSet(false, true)) { |
| start(); |
| } |
| } |
| |
| void start() { |
| try { |
| logger.info("Starting Model transformation ..."); |
| |
| // Model to Model transformation |
| |
| for (Model2ModelRootTransformer model2ModelRootTransformer : m2mTransformers) { |
| logger.info("****************** Model to Model Transformation : {0} *******************************", model2ModelRootTransformer.getTransformationKey()); |
| |
| logger.info("** Executing M2M transformer : {0}", model2ModelRootTransformer.getClass().getTypeName()); |
| model2ModelRootTransformer.setSessionLogger(logger); |
| model2ModelRootTransformer.m2mTransformation(); |
| } |
| |
| // Model to Text transformation |
| |
| for (Model2TextRootTransformer model2TextRootTransformer : m2tTransformers) { |
| logger.info("****************** Model to Text Transformation : {0} ****************************", model2TextRootTransformer.getTransformationKey()); |
| |
| logger.info("** Executing M2T transformer : {0}", model2TextRootTransformer.getClass().getTypeName()); |
| model2TextRootTransformer.setSessionLogger(logger); |
| model2TextRootTransformer.m2tTransformation(); |
| } |
| |
| } finally { |
| logger.info("Transformation execution session \"{0}\" completed.", this.sessionName); |
| |
| stopSession(); |
| } |
| } |
| |
| /** |
| * Stop the current running session by deleting the configuration. Additionally |
| * the session logger is flushed and disposed. |
| */ |
| private void stopSession() { |
| // we need to flush the session log first, as deleting the configuration will |
| // trigger listeners that eventually kill the process, e.g. in headless mode |
| this.logger.flush(new File(this.logFilePath)); |
| |
| if (this.eventAdmin != null) { |
| HashMap<String, Object> properties = new HashMap<>(); |
| properties.put(ServiceConstants.SESSION_ID, this.sessionName); |
| this.eventAdmin.sendEvent(new Event("org/eclipse/app4mc/transformation/DONE", properties)); |
| } |
| } |
| |
| // Convenience API to perform transformations outside an OSGi runtime |
| |
| /** |
| * This method is intended to be used for triggering the transformation process |
| * outside the OSGi context. |
| * |
| * @param properties The properties needed to configure the transformation. |
| */ |
| public void startTransformation(Map<String, ?> properties) { |
| this.logFilePath = (String) properties.get(TransformationConstants.LOG_FILE); |
| |
| this.sessionName = "single"; |
| |
| if (this.logger == null) { |
| this.logger = new SessionLogger(); |
| } |
| start(); |
| } |
| |
| /** |
| * This method is intended to be used for triggering the transformation process |
| * outside the OSGi context. |
| * |
| * @param logFilePath the session log file location |
| */ |
| public void startTransformation(String logFilePath) { |
| this.logFilePath = logFilePath; |
| |
| this.sessionName = "single"; |
| |
| if (this.logger == null) { |
| this.logger = new SessionLogger(); |
| } |
| start(); |
| } |
| |
| } |