blob: c9e49d55c8ab1f9b89f315db49f67fb8541163a6 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2018-2020 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.converters083.impl;
import java.io.File;
import java.util.ArrayList;
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.converters.common.utils.ModelVersion;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is responsible for converting the HW Model elements from 0.8.2 to 0.8.3 version format of AMALTHEA model
*
* @author zmeer
*
*/
@Component(
property = {
ServiceConstants.INPUT_MODEL_VERSION_PROPERTY + "=0.8.2",
ServiceConstants.OUTPUT_MODEL_VERSION_PROPERTY + "=0.8.3"},
service = IConverter.class)
public class SwConverter extends AbstractConverter {
private static final String AM = "am";
private static final String XSI = "xsi";
private static final String HREF = "href";
private static final String TYPE = "type";
private static final String VALUE = "value";
private static final String VALUES = "values";
private static final String VALUE_PROVIDER = "valueProvider";
private static final Logger LOGGER = LoggerFactory.getLogger(SwConverter.class);
@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.2 to 0.8.3 : Executing Software model converter for model file : {}",
targetFile.getName());
final Document root = filename2documentMap.get(targetFile);
if (root == null) {
return;
}
final Element rootElement = root.getRootElement();
migrateModeSwitchElements(rootElement);
migrateVariableRateActivationElements(rootElement);
update_CustomProps_InterfacePort_Refs(rootElement);
}
/**
* This method is used to migrate the contents of VariableRateActivation based on the changes introduced as per Bug 529831
*
*
* @param rootElement
* Amalthea root element
*/
private void migrateVariableRateActivationElements(Element rootElement) {
final StringBuilder xpathBuffer = new StringBuilder();
xpathBuffer.append("./swModel/activations[@xsi:type=\"am:VariableRateActivation\"]");
final List<Element> variableRateActivationElements = HelperUtil.getXpathResult(
rootElement,
xpathBuffer.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI),
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._083, AM));
for (Element element : variableRateActivationElements) {
element.removeChildren("activationDeviation");
}
}
/**
* This method is used to migrate the contents of ModeSwitch based on the changes introduced as per Bug 528934
*
*
* @param rootElement
* Amalthea root element
*/
private void migrateModeSwitchElements(Element rootElement) {
final StringBuilder xpathBuffer = new StringBuilder();
xpathBuffer.append("./swModel/isrs/callGraph/graphEntries[@xsi:type=\"am:ModeSwitch\"]");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/tasks/callGraph/graphEntries[@xsi:type=\"am:ModeSwitch\"]");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/isrs/callGraph/graphEntries//items[@xsi:type=\"am:ModeSwitch\"]");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/tasks/callGraph/graphEntries//items[@xsi:type=\"am:ModeSwitch\"]");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/runnables//runnableItems[@xsi:type=\"am:RunnableModeSwitch\"]");
xpathBuffer.append("|");
xpathBuffer.append("./swModel/runnables//items[@xsi:type=\"am:RunnableModeSwitch\"]");
final List<Element> modeSwitchElements = HelperUtil.getXpathResult(
rootElement,
xpathBuffer.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI),
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._083, AM));
updateModeSwitchElement(modeSwitchElements);
}
private void updateModeSwitchElement(final List<Element> modeSwitchElements) {
//Setting xsi:type value of Port
for (Element modeSwitchElement : modeSwitchElements) {
boolean isLocalModeLabelUsed = false;
String modeLabelValue = null;
Attribute valueProviderAttribute = modeSwitchElement.getAttribute(VALUE_PROVIDER);
Element valueProviderChild = modeSwitchElement.getChild(VALUE_PROVIDER);
if (valueProviderAttribute != null) {
isLocalModeLabelUsed = true;
modeLabelValue = valueProviderAttribute.getValue();
modeSwitchElement.removeAttribute(valueProviderAttribute);
} else if (valueProviderChild != null) {
modeLabelValue = valueProviderChild.getAttributeValue(HREF);
modeSwitchElement.removeContent(valueProviderChild);
}
//fetch ModeSwitchEntry<GraphEntryBase>[] entries objects and migrate them
List<Element> entriesElements = modeSwitchElement.getChildren("entries");
for (Element entriesElement : entriesElements) {
boolean isLocalLiteralsUsed=false;
Attribute valuesAttribute = entriesElement.getAttribute(VALUES);
List<Element> valuesElements = entriesElement.getChildren(VALUES);
List<String> literals = new ArrayList<>();
if (valuesAttribute != null) {
isLocalLiteralsUsed = true;
String value = valuesAttribute.getValue();
String[] split = value.split("\\s+");
for (String string : split) {
literals.add(string);
}
// removing this attribute, as it is not there in 0.8.3
entriesElement.removeAttribute(valuesAttribute);
} else if (valuesElements != null) {
for (Element valueElement : valuesElements) {
String attributeValue = valueElement.getAttributeValue(HREF);
if (attributeValue != null) {
literals.add(attributeValue);
}
}
// removing this attribute, as it is not there in 0.8.3
entriesElement.removeChildren(VALUES);
}
// creating Condition element and adding its children
Element conditionElement=new Element("condition");
for (String literal : literals) {
Element entriesElementInsideConditionElement=new Element("entries");
entriesElementInsideConditionElement.setAttribute(TYPE, "am:ModeValue", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
if (modeLabelValue != null) {
if (isLocalModeLabelUsed) {
entriesElementInsideConditionElement.setAttribute(VALUE_PROVIDER, modeLabelValue);
} else {
Element valueProviderElement = new Element(VALUE_PROVIDER);
entriesElementInsideConditionElement.addContent(valueProviderElement);
}
}
if (isLocalLiteralsUsed) {
entriesElementInsideConditionElement.setAttribute(VALUE, literal);
} else {
Element valueElement = new Element(VALUE);
valueElement.setAttribute(HREF, literal);
entriesElementInsideConditionElement.addContent(valueElement);
}
conditionElement.addContent(entriesElementInsideConditionElement);
}
entriesElement.addContent(conditionElement);
}
/*- now checking for recursive ModeSwitch elements and handling them
for (Element entriesElement : entriesElements) {
StringBuffer xpathForSubModeSwitchBuffer=new StringBuffer();
xpathForSubModeSwitchBuffer.append("./items[@xsi:type=\"am:ModeSwitch\"]");
xpathForSubModeSwitchBuffer.append("|");
xpathForSubModeSwitchBuffer.append("./defaultEntry/items[@xsi:type=\"am:ModeSwitch\"]");
final List<Element> submodeSwitchElements = this.helper.getXpathResult(entriesElement,xpathForSubModeSwitchBuffer.toString(),
Element.class, AmaltheaNamespaceRegistry.getGenericNamespace("xsi"),AmaltheaNamespaceRegistry.getNamespace(ModelVersion._083("am") );
updateModeSwitchElement(submodeSwitchElements);
}*/
}
}
private void update_CustomProps_InterfacePort_Refs(Element rootElement) {
final StringBuilder xpathBuffer = new StringBuilder();
xpathBuffer.append(".//customProperties/value[@xsi:type=\"am:FInterfacePort\"]");
xpathBuffer.append("|");
xpathBuffer.append(".//customProperties/value/value[@xsi:type=\"am:FInterfacePort\"]");
final List<Element> customPropsVals = HelperUtil.getXpathResult(
rootElement,
xpathBuffer.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI),
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._083, AM));
for (Element element : customPropsVals) {
Attribute val = element.getAttribute(TYPE, AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
val.setValue("am:InterfacePort");
//TBD :
// replaceFInterfacePortReference(element.getAttribute("value"));
replaceFInterfacePortReference(element.getAttribute(HREF));
}
}
private void replaceFInterfacePortReference(Attribute attr) {
if(attr != null) {
String value = attr.getValue();
value = value.replace("=FInterfacePort", "=InterfacePort");
attr.setValue(value);
}
}
}