/** | |
******************************************************************************** | |
* Copyright (c) 2019, 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.converters095.impl; | |
import java.io.File; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
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; | |
@Component( | |
property = { | |
ServiceConstants.INPUT_MODEL_VERSION_PROPERTY + "=0.9.4", | |
ServiceConstants.OUTPUT_MODEL_VERSION_PROPERTY + "=0.9.5" | |
}, | |
service = IConverter.class) | |
public class StimuliConverter extends AbstractConverter { | |
private static final Logger LOGGER = LoggerFactory.getLogger(StimuliConverter.class); | |
@Override | |
@Activate | |
protected void activate(Map<String, Object> properties) { | |
super.activate(properties); | |
} | |
@Override | |
public void convert(File targetFile, Map<File, Document> fileName_documentsMap, List<ICache> caches) { | |
LOGGER.info("Migration from 0.9.4 to 0.9.5 : Executing Stimuli converter for model file : {}", targetFile.getName()); | |
basicConvert(targetFile, fileName_documentsMap); | |
} | |
public void basicConvert(final File file, final Map<File, Document> map) { | |
final Document document = map.get(file); | |
if (document == null) { | |
return; | |
} | |
final Element rootElement = document.getRootElement(); | |
// migrate scenario | |
update_Scenario(rootElement); | |
// migrate clocks | |
update_ClocksMulitplierList(rootElement); | |
update_ClockSineFunction(rootElement); | |
update_ClockTriangleFunction(rootElement); | |
} | |
private void update_Scenario(Element rootElement) { | |
final String xpath = "./stimuliModel/stimuli[@xsi:type=\"am:VariableRateStimulus\"]/scenario"; | |
final List<Element> scenarios = HelperUtil.getXpathResult(rootElement, xpath, Element.class, | |
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._094, "am"), | |
AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
for (Element element : scenarios) { | |
Element recurrence = element.getChild("recurrence"); | |
if (recurrence != null) { | |
recurrence.detach(); | |
String value = recurrence.getAttributeValue("value"); | |
String unit = recurrence.getAttributeValue("unit"); | |
addCustomProperty(element, "old_definition_v0.9.4", "recurrence=" + value + unit); | |
} | |
String clockAttribute = element.getAttributeValue("clock"); | |
if (clockAttribute != null) { | |
Pattern p = Pattern.compile("(.+)\\?type=Clock(.+)"); | |
Matcher m = p.matcher(clockAttribute); | |
if (m.find()) { | |
String clockRef = m.group(1); | |
String clockType = getNewClockType(m.group(2)); | |
element.setAttribute("clock" , clockRef + "?type=Clock" + clockType); | |
} | |
} | |
Element clockElement = getSingleChild(element, "clock"); | |
if (clockElement != null) { | |
String hrefValue = clockElement.getAttributeValue("href"); | |
if (hrefValue != null) { | |
Pattern p = Pattern.compile("amlt:/#(.+)\\?type=Clock(.+)"); | |
Matcher m = p.matcher(hrefValue); | |
if (m.find()) { | |
String clockRef = m.group(1); | |
String clockType = getNewClockType(m.group(2)); | |
clockElement.setAttribute("type", "am:Clock" + clockType, AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
clockElement.setAttribute("href", "amlt:/#" + clockRef + "?type=Clock" + clockType); | |
} | |
} | |
} | |
} | |
} | |
private void update_ClockSineFunction(Element rootElement) { | |
final String xpath = "./stimuliModel/clocks[@xsi:type=\"am:ClockSinusFunction\"]"; | |
final List<Element> clocks = HelperUtil.getXpathResult(rootElement, xpath, Element.class, | |
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._094, "am"), | |
AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
StringBuilder customPropsValue = new StringBuilder(); | |
for (Element element : clocks) { | |
element.setAttribute("type", "am:ClockFunction", AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
element.setAttribute("curveType", "sine"); | |
Attribute amplitude = element.getAttribute("amplitude"); | |
amplitude.detach(); | |
customPropsValue.append(getStringValue(amplitude)); | |
customPropsValue.append(" "); | |
Attribute offset = element.getAttribute("yOffset"); | |
offset.detach(); | |
customPropsValue.append(getStringValue(offset)); | |
customPropsValue.append(" "); | |
customPropsValue.append(extractPeriodAndShift(element)); | |
addCustomProperty(element, "old_definition_v0.9.4", customPropsValue.toString().trim()); | |
} | |
} | |
private void update_ClockTriangleFunction(Element rootElement) { | |
final String xpath = "./stimuliModel/clocks[@xsi:type=\"am:ClockTriangleFunction\"]"; | |
final List<Element> clocks = HelperUtil.getXpathResult(rootElement, xpath, Element.class, | |
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._094, "am"), | |
AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
StringBuilder customPropsValue = new StringBuilder(); | |
for (Element element : clocks) { | |
element.setAttribute("type", "am:ClockFunction", AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
element.setAttribute("curveType", "triangle"); | |
Attribute max = element.getAttribute("max"); | |
max.detach(); | |
customPropsValue.append(getStringValue(max)); | |
customPropsValue.append(" "); | |
Attribute min = element.getAttribute("min"); | |
min.detach(); | |
customPropsValue.append(getStringValue(min)); | |
customPropsValue.append(" "); | |
customPropsValue.append(extractPeriodAndShift(element)); | |
addCustomProperty(element, "old_definition_v0.9.4", customPropsValue.toString().trim()); | |
} | |
} | |
private String extractPeriodAndShift(Element element) { | |
StringBuilder str = new StringBuilder(); | |
List<Element> children = element.getChildren(); | |
for (Element e : children) { | |
str.append(e.getName()); | |
str.append("="); | |
str.append(e.getAttributeValue("value")); | |
str.append(e.getAttributeValue("unit")); | |
str.append(" "); | |
} | |
element.removeChild("period"); | |
element.removeChild("shift"); | |
return str.toString(); | |
} | |
private String getStringValue(Attribute attr) { | |
return attr.getName() + "=" + attr.getValue(); | |
} | |
private void update_ClocksMulitplierList(final Element rootElement) { | |
final String xpath = "./stimuliModel/clocks[@xsi:type=\"am:ClockMultiplierList\"]"; | |
final List<Element> clocks = HelperUtil.getXpathResult(rootElement, xpath, Element.class, | |
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._094, "am"), | |
AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
for (Element element : clocks) { | |
element.setAttribute("type", "am:ClockStepList", AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
update_ClockEntries(element); | |
} | |
} | |
private void update_ClockEntries(Element clockElement) { | |
List<Element> entries = clockElement.getChildren("entries"); | |
for (Element entry : entries) { | |
Attribute multiplier = entry.getAttribute("multiplier"); | |
multiplier.detach(); | |
addCustomProperty(entry, "old_definition_v0.9.4", "multiplier=" + multiplier.getValue()); | |
} | |
} | |
private void addCustomProperty(Element element, String key, String value) { | |
Element customProps = new Element("customProperties"); | |
// set key | |
customProps.setAttribute("key", key); | |
// set value | |
Element valueElement = new Element("value"); | |
valueElement.setAttribute("type", "am:StringObject", AmaltheaNamespaceRegistry.getGenericNamespace("xsi")); | |
valueElement.setAttribute("value", value); | |
customProps.addContent(valueElement); | |
element.addContent(customProps); | |
} | |
private Element getSingleChild(final Element parent, String name) { | |
List<Element> list = parent.getChildren(name); | |
if (list.size() == 1) { | |
return list.get(0); | |
} else { | |
return null; | |
} | |
} | |
private String getNewClockType(final String oldClockType) { | |
switch (oldClockType) { | |
case "SinusFunction": case "TriangleFunction" : return "Function"; | |
case "MultiplierList" : return "StepList"; | |
} | |
return oldClockType; | |
} | |
} |