Bug 559976 - Missing handling of amlt://# reference

Change-Id: Ica225ff19b114e91f2bfcd31a2d9d9ae9ebb0e83
Signed-off-by: Dirk Fauth <dirk.fauth@de.bosch.com>
diff --git a/plugins/org.eclipse.app4mc.amalthea.converters.097/src/org/eclipse/app4mc/amalthea/converters097/utils/AmltModelReferencePostProcessor.java b/plugins/org.eclipse.app4mc.amalthea.converters.097/src/org/eclipse/app4mc/amalthea/converters097/utils/AmltModelReferencePostProcessor.java
index 35a7b91..7faef2e 100644
--- a/plugins/org.eclipse.app4mc.amalthea.converters.097/src/org/eclipse/app4mc/amalthea/converters097/utils/AmltModelReferencePostProcessor.java
+++ b/plugins/org.eclipse.app4mc.amalthea.converters.097/src/org/eclipse/app4mc/amalthea/converters097/utils/AmltModelReferencePostProcessor.java
@@ -71,6 +71,9 @@
 			//href="amlt:/#modelElement?type=EnumMode"
 			//"modelElement?type=EnumMode"
 			hrefValue = hrefValue.replaceFirst("amlt:/#", "");
+			//href="amlt://#GRAM?type=Memory"
+			//"GRAM?type=Memory"
+			hrefValue = hrefValue.replaceFirst("amlt://#", "");
 			
 			Attribute modelRefAttribute = new Attribute(element.getName(), hrefValue);
 			parentElement.getAttributes().add(modelRefAttribute);
diff --git a/tests/org.eclipse.app4mc.amalthea.converters.097.tests/TestModels/input/modelreference/model.amxmi b/tests/org.eclipse.app4mc.amalthea.converters.097.tests/TestModels/input/modelreference/model.amxmi
new file mode 100644
index 0000000..d6dfdda
--- /dev/null
+++ b/tests/org.eclipse.app4mc.amalthea.converters.097.tests/TestModels/input/modelreference/model.amxmi
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<am:Amalthea xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:am="http://app4mc.eclipse.org/amalthea/0.9.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <hwModel>
+    <definitions xsi:type="am:MemoryDefinition" name="GenericRAM">
+      <size value="262144" />
+    </definitions>
+    <definitions xsi:type="am:MemoryDefinition" name="GenericLocalRAM">
+      <size value="131072" />
+    </definitions>
+    <definitions xsi:type="am:ProcessingUnitDefinition" name="Generic Core" puType="CPU">
+      <features href="amlt:/#Instructions/IPC_1?type=HwFeature" />
+    </definitions>
+    <featureCategories name="Instructions" featureType="performance">
+      <features name="IPC_1" value="1" />
+    </featureCategories>
+    <definitions xsi:type="am:ConnectionHandlerDefinition" name="GenericCrossbarSwitch" />
+    <definitions xsi:type="am:ConnectionHandlerDefinition" name="GenericLocalBus" />
+    <structures name="System" structureType="System">
+      <structures name="ECU" structureType="ECU">
+        <structures name="Microcrontroller" structureType="Microcontroller">
+          <modules name="GRAM" xsi:type="am:Memory">
+            <definition href="amlt:/#GenericRAM?type=MemoryDefinition" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" />
+          </modules>
+          <modules name="LRAM0" xsi:type="am:Memory">
+            <definition href="amlt:/#GenericLocalRAM?type=MemoryDefinition" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" />
+            <ports name="Port_CORE0_to_LRAM0_Bus" bitWidth="32" />
+          </modules>
+          <modules name="LRAM1" xsi:type="am:Memory">
+            <definition href="amlt:/#GenericLocalRAM?type=MemoryDefinition" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" />
+            <ports name="Port_CORE1_to_LRAM1_Bus" bitWidth="32" />
+          </modules>
+          <modules name="LRAM2" xsi:type="am:Memory">
+            <definition href="amlt:/#GenericLocalRAM?type=MemoryDefinition" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" />
+            <ports name="Port_CORE2_to_LRAM2_Bus" bitWidth="32" />
+          </modules>
+          <modules name="LRAM3" xsi:type="am:Memory">
+            <definition href="amlt:/#GenericLocalRAM?type=MemoryDefinition" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" />
+            <ports name="Port_CORE3_to_LRAM3_Bus" bitWidth="32" />
+          </modules>
+          <modules name="GenericCrossbarNet" xsi:type="am:ConnectionHandler">
+            <definition href="amlt:/#GenericCrossbarSwitch?type=ConnectionHandlerDefinition" />
+            <frequencyDomain href="amlt:/#GenericPLL?type=FrequencyDomain" />
+          </modules>
+          <modules xsi:type="am:ProcessingUnit" name="CORE0">
+            <definition href="amlt:/#Generic+Core?type=ProcessingUnitDefinition" />
+            <frequencyDomain href="amlt:/#GenericPLL?type=FrequencyDomain" />
+            <ports name="Port_CORE0_to_LRAM0_Bus" bitWidth="32" portType="initiator" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" portType="initiator" />
+            <accessElements name="CORE0_to_LRAM0">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM0?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="1" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="1" />
+            </accessElements>
+            <accessElements name="CORE0_to_LRAM1">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM1?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE0_to_LRAM2">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM2?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE0_to_LRAM3">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM3?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE0_to_GRAM">
+              <destination xsi:type="am:Memory" href="amlt://#GRAM?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+          </modules>
+          <modules name="CORE0_to_LRAM0_Bus" xsi:type="am:ConnectionHandler">
+            <definition href="amlt:/#GenericLocalBus?type=ConnectionHandlerDefinition" />
+          </modules>
+          <modules xsi:type="am:ProcessingUnit" name="CORE1">
+            <definition href="amlt:/#Generic+Core?type=ProcessingUnitDefinition" />
+            <frequencyDomain href="amlt:/#GenericPLL?type=FrequencyDomain" />
+            <ports name="Port_CORE1_to_LRAM1_Bus" bitWidth="32" portType="initiator" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" portType="initiator" />
+            <accessElements name="CORE1_to_LRAM0">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM0?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE1_to_LRAM1">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM1?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="1" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="1" />
+            </accessElements>
+            <accessElements name="CORE1_to_LRAM2">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM2?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE1_to_LRAM3">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM3?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE1_to_GRAM">
+              <destination xsi:type="am:Memory" href="amlt://#GRAM?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+          </modules>
+          <modules name="CORE1_to_LRAM1_Bus" xsi:type="am:ConnectionHandler">
+            <definition href="amlt:/#GenericLocalBus?type=ConnectionHandlerDefinition" />
+          </modules>
+          <modules xsi:type="am:ProcessingUnit" name="CORE2">
+            <definition href="amlt:/#Generic+Core?type=ProcessingUnitDefinition" />
+            <frequencyDomain href="amlt:/#GenericPLL?type=FrequencyDomain" />
+            <ports name="Port_CORE2_to_LRAM2_Bus" bitWidth="32" portType="initiator" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" portType="initiator" />
+            <accessElements name="CORE2_to_LRAM0">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM0?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE2_to_LRAM1">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM1?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE2_to_LRAM2">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM2?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="1" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="1" />
+            </accessElements>
+            <accessElements name="CORE2_to_LRAM3">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM3?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE2_to_GRAM">
+              <destination xsi:type="am:Memory" href="amlt://#GRAM?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+          </modules>
+          <modules name="CORE2_to_LRAM2_Bus" xsi:type="am:ConnectionHandler">
+            <definition href="amlt:/#GenericLocalBus?type=ConnectionHandlerDefinition" />
+          </modules>
+          <modules xsi:type="am:ProcessingUnit" name="CORE3">
+            <definition href="amlt:/#Generic+Core?type=ProcessingUnitDefinition" />
+            <frequencyDomain href="amlt:/#GenericPLL?type=FrequencyDomain" />
+            <ports name="Port_CORE3_to_LRAM3_Bus" bitWidth="32" portType="initiator" />
+            <ports name="Port_GenericCrossbarNet" bitWidth="32" portType="initiator" />
+            <accessElements name="CORE3_to_LRAM0">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM0?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE3_to_LRAM1">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM1?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE3_to_LRAM2">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM2?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+            <accessElements name="CORE3_to_LRAM3">
+              <destination xsi:type="am:Memory" href="amlt://#LRAM3?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="1" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="1" />
+            </accessElements>
+            <accessElements name="CORE3_to_GRAM">
+              <destination xsi:type="am:Memory" href="amlt://#GRAM?type=Memory" />
+              <readLatency xsi:type="am:DiscreteValueConstant" value="9" />
+              <writeLatency xsi:type="am:DiscreteValueConstant" value="9" />
+            </accessElements>
+          </modules>
+          <modules name="CORE3_to_LRAM3_Bus" xsi:type="am:ConnectionHandler">
+            <definition href="amlt:/#GenericLocalBus?type=ConnectionHandlerDefinition" />
+          </modules>
+        </structures>
+      </structures>
+    </structures>
+    <domains xsi:type="am:FrequencyDomain" name="GenericPLL">
+      <defaultValue value="2.0E8" />
+    </domains>
+  </hwModel>
+</am:Amalthea>
diff --git a/tests/org.eclipse.app4mc.amalthea.converters.097.tests/src/org/eclipse/app4mc/amalthea/converters097/tests/AmltModelReferencePostProcessorTest.java b/tests/org.eclipse.app4mc.amalthea.converters.097.tests/src/org/eclipse/app4mc/amalthea/converters097/tests/AmltModelReferencePostProcessorTest.java
new file mode 100644
index 0000000..2ca3e43
--- /dev/null
+++ b/tests/org.eclipse.app4mc.amalthea.converters.097.tests/src/org/eclipse/app4mc/amalthea/converters097/tests/AmltModelReferencePostProcessorTest.java
@@ -0,0 +1,153 @@
+/*********************************************************************************
+ * Copyright (c) 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.converters097.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+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.base.IPostProcessor;
+import org.eclipse.app4mc.amalthea.converters.common.converter.NamespaceConverter;
+import org.eclipse.app4mc.amalthea.converters.common.tests.AbstractConverterTest;
+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.eclipse.app4mc.amalthea.converters097.impl.ComponentsModelConverter;
+import org.eclipse.app4mc.amalthea.converters097.utils.AmltModelReferencePostProcessor;
+import org.eclipse.app4mc.amalthea.converters097.utils.ComponentPortInterfaceCacheBuilder;
+import org.jdom2.Attribute;
+import org.jdom2.Document;
+import org.jdom2.Element;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)
+public class AmltModelReferencePostProcessorTest extends AbstractConverterTest {
+
+	@Parameterized.Parameters(name = "{index}: Test file: {0}")
+	public static Collection<Object[]> getTestData() {
+
+		return Arrays.asList(new Object[][] { { "/modelreference/model.amxmi", true } });
+	}
+
+	public AmltModelReferencePostProcessorTest(final String xmlFileRelativeLocation, final boolean canExecuteTestCase) {
+		super(canExecuteTestCase, xmlFileRelativeLocation);
+	}
+
+	@Override
+	public ModelVersion getInputModelVersion() {
+		return ModelVersion._096;
+	}
+
+	@Override
+	public ModelVersion getOutputModelVersion() {
+		return ModelVersion._097;
+	}
+
+	@Test
+	public void testConversion() {
+		super.testConversion(NamespaceConverter.class, ComponentsModelConverter.class);
+	}
+
+	@Override
+	@Test
+	public void verification() {
+		super.verification();
+	}
+
+	@Override
+	protected void modelFileVerificationHook(Document document) {
+		super.modelFileVerificationHook(document);
+		
+		// verify that the interfaces are created in democar-common
+		List<Element> modules = HelperUtil.getXpathResult(
+				document.getRootElement(),
+				"./hwModel/structures/structures/structures/modules",
+				Element.class,
+				AmaltheaNamespaceRegistry.getNamespace(ModelVersion._097, "am"), 
+				AmaltheaNamespaceRegistry.getGenericNamespace("xsi"));
+
+		assertEquals(14, modules.size());
+		
+		// definition of every modules is an attribute instead of a child
+		for (Element element : modules) {
+			Attribute definition = element.getAttribute("definition");
+			assertNotNull(definition);
+			assertFalse("definition attribute contains amlt reference", definition.getValue().startsWith("amlt"));
+		}
+		
+		modules = HelperUtil.getXpathResult(
+				document.getRootElement(),
+				"./hwModel/structures/structures/structures/modules/accessElements",
+				Element.class,
+				AmaltheaNamespaceRegistry.getNamespace(ModelVersion._097, "am"), 
+				AmaltheaNamespaceRegistry.getGenericNamespace("xsi"));
+		
+		// destination of every accessElements is an attribute instead of a child
+		for (Element element : modules) {
+			Attribute destination = element.getAttribute("destination");
+			assertNotNull(destination);
+			assertFalse("destination attribute contains amlt reference", destination.getValue().startsWith("amlt"));
+		}
+	}
+
+	@Override
+	protected List<ICache> buildCaches() {
+		List<ICache> caches = super.buildCaches();
+
+		ComponentPortInterfaceCacheBuilder cacheBuilder = new ComponentPortInterfaceCacheBuilder();
+		cacheBuilder.buildCache(this.fileDocumentMapping);
+		caches.add(cacheBuilder);
+		
+		return caches;
+	}
+
+	// accessibility updates in test cases are ok here, at runtime the reference is set by the SCR
+	@SuppressWarnings("squid:S3011")
+	@Override
+	protected void setCache(IConverter converter, List<ICache> caches)
+			throws IllegalAccessException, NoSuchFieldException {
+
+		if (converter instanceof ComponentsModelConverter) {
+			for (ICache iCache : caches) {
+				if (iCache instanceof ComponentPortInterfaceCacheBuilder) {
+					Field declaredField = ((ComponentsModelConverter) converter).getClass().getDeclaredField("cache");
+					declaredField.setAccessible(true);
+					declaredField.set(converter, iCache);
+					return;
+				}
+			}
+		}
+	}
+	
+	@Override
+	protected List<IPostProcessor> buildPostProcessors() {
+		List<IPostProcessor> postProcessors = new ArrayList<IPostProcessor>();		
+		postProcessors.add(new AmltModelReferencePostProcessor());		
+		return postProcessors;
+	}
+}