6 min. reading time

During the development of automotive functionalities, a large number of dedicated tools is being used – from requirements, through design, to implementation and testing. Data exchange between these tools is often not supported in an efficient manner. Transformation of data between different formats and meta-models is required.

The Eclipse ecosystem provides a rich infrastructure for these use cases. In this example, we are going to show how EMP (Eclipse Modeling Project) can be leveraged to support them.

We will demonstrate EMP usage based on the XML format of ADTF.

ADTF (Automotive Data and Time-Triggered Framework) is a tool that is being used in the development of automotive functions. It supports data exchange through an XML format. In our case, we wanted to transform the ADTF data from and to a SysML-based tool by using the powerful features of the Xtend language and the further features of EMP, e.g., EMF Compare, Graphiti, Sirius, etc. This blog posts lays out the required steps.

The XML format

Examples of the XML format can be easily found by searching for “adtf xml github”. For this blog-post, we will be using this example:

<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<adtf:ddl  xmlns:adtf="adtf" >
  <header>
    <language_version>3.00</language_version>
    <author>itemis AG</author>
    <date_creation>07.12.2018</date_creation>
    <date_change>07.12.2018</date_change>
    <description>ADTF Common Description File</description>
  </header>
  <units>
    <baseunit description="Fundamental unit for length" name="Metre" symbol="m" />
  </units>
  <datatypes>
    <datatype description="predefined ADTF tBool datatype" name="tUInt8" size="8" />
	</datatypes>
  <enums>
    <enum name="Fahrzeug_Zustand_Enum" type="tUInt8">
      <element name="Parken" value="0" />
      <element name="Wohnen" value="1" />
      <element name="Fahren" value="2" />
    </enum>
  </enums>
</adtf:dd>>

 

The EMF model

To be able to use the EMF/EMP features, we need an EMF meta-model, a so-called “ecore” definition, that describes the data. EMF supports the conversion of XML Schema (.xsd files) into an ecore. However, in our case, we chose to hand-craft the .ecore file with the ecore editor, since this gives us better control to create a well-designed meta-model (in terms of attribute types and inheritance). The initial model was quickly created after analyzing the XML:

Integrating Automotive Tools create EMF meta-model

 

A few specific settings are required in our .ecore file to match the XML. Note that we have the following line in the XML data:

<adtf:ddl  xmlns:adtf="adtf" >

 

The prefix is “adtf” and the namespace URI is “adtf”, too. So we are setting these as the properties of our root package:

Set prefix and namespace URI to adtf

 

Dealing with the XML structure

Please note that in our XML, sub-elements are grouped with their own tags (units) in this example:

<units>
  <baseunit description="Fundamental unit for length" name="Metre" symbol="m" />
</units>

 

This happens not only in ADTF, but also in AUTOSAR (Artop) and ReqIF. So we are reusing the org.eclipse.sphinx.emf.serialization.XMLPersistenceMappingResourceImpl implementation class from Eclipse Sphinx to create our specific EMF resource that supports exactly that.

For our EMF resource implementation, we extend the Sphinx base class:

public class Adtf2ResourceImpl extends XMLPersistenceMappingResourceImpl { … }

 

And we can then use the metadata mechanism to annotate our elements in the ecore with information that is being used to customize (de-)serialization of EMF to XML:

Annotate elements in ecore via meta data mechanism

 

Resolving references

The XML in our example has references between elements. The enumeration refers to a data type through the type=”…” attribute in XML, which points to the data type that is identified by name – type="tUInt8" in our example. This syntax is different from the default EMF mechanism, so we have to provide an implementation that can deal with this custom linking. We have to override getEObject() in our resource implementation:

@Override
public EObject getEObject(String uriFragment) {
  TreeIterator<EObject> allContents = getAllContents();

  while(allContents.hasNext()) {
    EObject next = allContents.next();
    if(next instanceof Named) {
      if(((Named)next).getName().equals(uriFragment)) {
        return next;
      }
    }
  }

  return null;
}

 

The getEObject method will be called with the value of the type=”…” attribute in the XML. We provide a simple implementation that will just traverse the entire model to find the element with the name being passed. A more sophisticated implementation might do some additional caching, but the performance is sufficient for our use cases.

XML namespaces

Finally, we work around a little problem in the XML:

<dtf:ddl  xmlns:adtf="adtf" >
  <header>

 

The XML code defines the namespace for the adtf prefix, but the following lines (<header>) do not have any prefixes, and namespaces are not inherited. This means that all the following lines are in the XML default namespace and thus not recognized in the model. So we need some code to tell our resource to treat everything without a prefix as belonging to the "adtf" namespace.

@Override
protected XMLHelper createXMLHelper() {
  XMLHelper result = super.createXMLHelper();
  result.getPrefixToNamespaceMap().put("", Adtf2Package.eNS_URI);
  return result;
}

 

Creating a standalone program

Now everything works fine within an Eclipse RCP (started with OSGi), because through the Eclipse plugin.xml mechanism, the file extensions are registered correctly. However, very often we want to have standalone programs that are not based on Eclipse RCPs. For a simple Java main(), we have some simple code for the loading:

def static Resource read(String filename) {
  val resourceSet = new ResourceSetImpl
  Adtf2Package.eINSTANCE.eClass
  resourceSet.resourceFactoryRegistry.extensionToFactoryMap.put("adtf2",
    new Adtf2ResourceFactoryImpl)
  resourceSet.resourceFactoryRegistry.extensionToFactoryMap.put("description",
    new Adtf2ResourceFactoryImpl)

  val resource = resourceSet.getResource(URI.createFileURI(filename), true)

  resource
}

 

And we can now process the model with standard means, such as Xtend code, e.g., dumping the contents of a file:

def static void main(String[] args) {
  val resource = read("xml/small.ddl.description");
  resource.allContents.forEach[println(it)]
}

 

Conclusion

With the steps outlined above, we have access to a full EMF model representing our XML, and we can now leverage the entire ecosystem of the Eclipse Modeling project. Our main use case is model-to-model transformation, but there is a rich set of features to support many integration use cases with other tools.

Comments