/** | |
******************************************************************************** | |
* 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); | |
} | |
} | |
} |