blob: 57f5cca78de48d57db253395383fa6f7abb2fcfd [file] [log] [blame]
/**
********************************************************************************
* 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.converters081.impl;
import java.io.File;
import java.util.List;
import java.util.Map;
import org.eclipse.app4mc.amalthea.converters.common.ServiceConstants;
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.converter.AbstractConverter;
import org.eclipse.app4mc.amalthea.converters.common.utils.AmaltheaNamespaceRegistry;
import org.eclipse.app4mc.amalthea.converters.common.utils.HelperUtil;
import org.eclipse.app4mc.amalthea.converters081.utils.HelperUtils_080_081;
import org.eclipse.app4mc.util.sessionlog.SessionLogger;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* This class is responsible for converting the SW Model elements from 0.8.0 to 0.8.1 version format of AMALTHEA model
*
* @author mez2rng
*
*/
@Component(
property = {
ServiceConstants.INPUT_MODEL_VERSION_PROPERTY + "=0.8.0",
ServiceConstants.OUTPUT_MODEL_VERSION_PROPERTY + "=0.8.1"},
service = IConverter.class)
public class SwConverter extends AbstractConverter {
private static final String XSI = "xsi";
private static final String TYPE = "type";
private static final String NAME = "name";
private static final String VALUE = "value";
@Reference
SessionLogger logger;
@Override
@Activate
protected void activate(Map<String, Object> properties) {
super.activate(properties);
}
@Override
public void convert(File targetFile, Map<File, Document> filename2documentMap, List<ICache> caches) {
logger.info("Migration from 0.8.0 to 0.8.1 : Executing Software converter for model file : {0}",
targetFile.getName());
final Document root = filename2documentMap.get(targetFile);
if (root == null) {
return;
}
final Element rootElement = root.getRootElement();
updateRunnable(rootElement);
updateActivations(rootElement);
updateAllAbstractProcessElements(rootElement);
}
/**
* This method is used to remove priority from sub-classes of AbstractProcess (For further
* details, check : Bug 511284, 518070 )
*
*
* @param rootElement
* Amalthea root element
*/
private void updateAllAbstractProcessElements(Element rootElement) {
final StringBuilder xpathBuffer = new StringBuilder();
xpathBuffer.append("./swModel/tasks");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/isrs");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/processPrototypes");
final List<Element> abstractProcessElements = HelperUtil.getXpathResult(
rootElement,
xpathBuffer.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
for (Element abstractProcessElement : abstractProcessElements) {
Attribute priorityAttribute = abstractProcessElement.getAttribute("priority");
if(priorityAttribute !=null){
String value = priorityAttribute.getValue();
/*-- removing attribute based on the metamodel changes introduced in 0.8.1 --*/
abstractProcessElement.removeAttribute(priorityAttribute);
if(!value.equals("0")){
Element customPropertiesElement=new Element("customProperties");
customPropertiesElement.setAttribute("key", "priority");
Element valueElement=new Element(VALUE);
valueElement.setAttribute(TYPE, "am:StringObject", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
valueElement.setAttribute(VALUE, value);
customPropertiesElement.addContent(valueElement);
abstractProcessElement.addContent(customPropertiesElement);
logger.info("Priority is removed from : {0} element ({1}) and added as a CustomProperty with key as Priority",
abstractProcessElement.getName(),
abstractProcessElement.getAttributeValue(NAME));
}
}
/*-- removing osekTaskGroup attribute inside Task element: based on the metamodel changes introduced in 0.8.1 --*/
if(abstractProcessElement.getName().equals("tasks")){
Attribute osekTaskGroupAttribute = abstractProcessElement.getAttribute("osekTaskGroup");
if(osekTaskGroupAttribute !=null){
String osekTaskGroupValue = osekTaskGroupAttribute.getValue();
abstractProcessElement.removeAttribute(osekTaskGroupAttribute);
if(!osekTaskGroupValue.equals("0")){
HelperUtils_080_081.addCustomProperty(abstractProcessElement, "osekTaskGroup", osekTaskGroupValue);
logger.info("osekTaskGroup attribute is removed from Task ({0}) and added as a CustomProperty with key as osekTaskGroup",
abstractProcessElement.getAttributeValue(NAME));
}
}
}
}
}
/**
* This method is used to migrate the Runnable data to support multiple Activations (For further
* details, check : Bug 519357 )
*
*
* @param rootElement
* Amalthea root element
*/
private void updateRunnable(Element rootElement) {
final StringBuilder xpathBuffer = new StringBuilder();
xpathBuffer.append("./swModel/runnables");
final List<Element> runnableElements = HelperUtil.getXpathResult(
rootElement,
xpathBuffer.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
for (Element runnableElement : runnableElements) {
Attribute activationAttribute = runnableElement.getAttribute("activation");
Element activationElement = runnableElement.getChild("activation");
if(activationAttribute !=null){
activationAttribute.setName("activations");
}else if(activationElement !=null){
activationElement.setName("activations");
}
}
}
/**
* This method is used to migrate both PeriodicAtivation (removal of deadline ) and EventActivation (change of trigger tag to triggeringEvents)
*
* @param rootElement
* Amalthea root element
*/
private void updateActivations(Element rootElement) {
final StringBuilder xpathBuffer = new StringBuilder();
xpathBuffer.append("./swModel/activations");
final List<Element> activationElements = HelperUtil.getXpathResult(
rootElement,
xpathBuffer.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
boolean removedDeadLine=false;
for (Element activationElement : activationElements) {
if(activationElement.getAttributeValue(TYPE, AmaltheaNamespaceRegistry.getGenericNamespace(XSI)).contains("am:PeriodicActivation")){
Element deadlineElement = activationElement.getChild("deadline");
if(deadlineElement !=null){
deadlineElement.detach();
Element customPropertiesElement=new Element("customProperties");
customPropertiesElement.setAttribute("key", "deadline");
deadlineElement.setName(VALUE);
deadlineElement.setAttribute(TYPE, "am:TimeObject", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
//adding as a value to CustomProperty
customPropertiesElement.addContent(deadlineElement);
//adding customProperty to Activation Element
activationElement.addContent(customPropertiesElement);
removedDeadLine=true;
}
}else if(activationElement.getAttributeValue(TYPE, AmaltheaNamespaceRegistry.getGenericNamespace(XSI)).contains("am:EventActivation")){
List<Element> triggerElements = activationElement.getChildren("trigger");
if(triggerElements !=null){
for (Element element : triggerElements) {
element.setName("triggeringEvents");
}
}
Attribute triggerAttribute = activationElement.getAttribute("trigger");
if(triggerAttribute!=null){
triggerAttribute.setName("triggeringEvents");
}
}
}
if(removedDeadLine){
logger.warn("-- Deadline inside PeriodicActivation elements is removed, as there is no equivalent element for it in AMALTHEA 0.8.1");
}
}
}