Configuring the .mff File

www.altova.com Print this Topic Previous Page Up One Level Next page

Home >  Functions > Referencing Java, C# and C++ Libraries Manually >

Configuring the .mff File

The MapForce Function File (.mff) is a configuration file in XML format that makes it possible to adapt functions from custom Java, C#, or C++ libraries into MapForce, so that they appear in the Libraries window. An .mff file essentially mediates between your custom libraries and MapForce, and it must be configured to specify a) the interfaces to the custom functions and b) where the implementation can be found in generated code. This topic provides instructions on how to do this.

 

Note:The *.mff library files must be valid against the mff.xsd schema file found in the Altova\MapForce2019\MapForceExamples folder, relative to your (My) Documents folder. The mff.xsd schema defines the custom library configuration and is for internal use only. Altova GmbH retains the right to change this file format with new releases.

 

The following code listing illustrates a sample .mff file for C#:

 

<?xml version="1.0" encoding="UTF-8"?>
<mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="mff.xsd" version="8" library="helloworld">
  <implementations>
    <implementation language="cs">
        <setting name="namespace" value="HelloWorldLibrary"/>
        <setting name="class" value="Greetings"/>
        <setting name="reference" value="C:\HelloWorldLibrary\HelloWorldLibrary.dll"/>
    </implementation>
  </implementations>
  <group name="string functions">
    <component name="hello">
        <sources>
          <datapoint name="greeting_type" type="xs:boolean"/>
        </sources>
        <targets>
          <datapoint name="result" type="xs:string"/>
        </targets>
        <implementations>
          <implementation language="cs">
              <function name="HelloFunction"/>
          </implementation>
        </implementations>
        <description>
          <short>result = hello(greeting_type)</short>
          <long>Returns a greeting sentence according to the given greeting_type.</long>
        </description>
    </component>
  </group>
</mapping>

 

The image below shows a custom .mff file may look after import into MapForce. Notice that the custom library "helloworld" appears as a library entry (sorted alphabetically), containing the "hello" string function.

mip1

The steps needed to adapt the mff file to suit your needs are described below.

 

Configuring the library name

The library name is found in the .mff file line shown below. By convention, the library name is written in lowercase letters.

 

<mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="mff.xsd" version="8" library="helloworld">

 

In the sample above, the entry that will appear in the Libraries window will be called "helloworld".

 

Configuring the language implementations

The <implementations> element is mandatory element which specifies which languages your library should support, and it must be added as child of <mapping>, for example:

 

...
<mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="mff.xsd" version="8" library="helloworld">
  <implementations>
    <implementation language="cs">
        <setting name="namespace" value="HelloWorldLibrary"/>
        <setting name="class" value="Greetings"/>
        <setting name="reference" value="C:\HelloWorldLibrary\HelloWorldLibrary.dll"/>
    </implementation>
  </implementations>
...

 

The settings within each <implementation> allow the generated code to call the specific functions defined in Java, C++ or C#.

 

An .mff file can be written so that it targets more than one programming language. In this case, every additional language must contain an additional <implementation> element. The specific settings for each programming language are discussed below.

 

Java

...
<implementation language="java">
  <setting name="package" value="com.hello.functions"/>
  <setting name="class" value="Hello"/>
</implementation>
...

 

It is important for the generated code to be able to find your Hello.class file. Therefore, make sure that your class is in the Java classpath. The default Java classpath is found in the system environment variables.

 

Note that it is only possible to have one class per *.mff file when working with custom Java libraries.

 

C#

...
  <implementation language="cs">
    <setting name="namespace" value="HelloWorldLibrary"/>
    <setting name="class" value="Hello"/>
    <setting name="reference" value=" C:\HelloWorldLibrary\HelloWorldLibrary.dll"/>
  </implementation>
...

 

For C#, it is important that the namespace in the code corresponds to the namespace defined in the .mff file (in the code listing above, the namespace is HelloWorldLIbrary). The same is true for the class name (in the code listing above, the class name is Hello). The third setting, reference, provides the path of the dll that is to be linked to the generated code.

 

C++

...
  <implementation language="cpp">
        <setting name="namespace" value="helloworld"/>
        <setting name="class" value="Greetings"/>
        <setting name="path" value="C:\HelloWorldLibrary"/>
        <setting name="include" value="Greetings.h"/>
        <setting name="source" value="Greetings.cpp"/>
  </implementation>
...

 

For the C++ sample listing above, note the following:

 

namespace is the namespace in which your Greetings class will be defined. It must be equal to the library name.
path is the path in which the include and the source files are to be found.
When code for a mapping is generated, the include and source files will be copied to the directory targetdir/libraryname (defined when selecting the menu option File | Generate xxx code, and selecting the directory) and included in the project file.

 

All the include files you supply will be included in the generated algorithm.

 

Adding a component

In the Libraries window of the MapForce graphics user interface, each function appears nested under a function group, for example "string functions". In the .mff file, a function corresponds to a <component> element. Conversely, each <component> must be nested under a <group> element, for example:

 

...
<group name="string functions">
  <component name="hello">
     …
  </component>
</group>
...

 

The code shown below defines a sample function (component) called hello.

 

...
<component name="hello">
  <sources>
    <datapoint name="greeting_type" type="xs:boolean"/>
  </sources>
  <targets>
    <datapoint name="result" type="xs:string"/>
  </targets>
  <implementations>
  …
  </implementations>
  <description>
    <short>result = hello(greeting_type)</short>
    <long>Returns a greeting sentence according to the given greeting_type.</long>
  </description>
</component>
...

 

Here is how the component above would look in MapForce:

mip2

In the code listing above, a <datapoint> can be loosely defined as the input or output parameter of a function (also known as input or output connector). The type argument of the <datapoint> specifies the data type of the parameter (or the data type of the return value).

 

Only one target datapoint is allowed for each function. There is no limitation as to how many source datapoints you can define.

 

The data type of each datapoint must be one of the XML Schema types (for example, xs:string, xs:integer, etc.) These data types have to correspond to the data types of the function's parameters you defined in your Java, C++ or C# library. For the mapping of XML Schema datatypes to language types, see Data Type Mapping.

 

Functions are accompanied by short and long descriptions in the library window. The short description is always shown to the right of the function name, while the long description is displayed as a ToolTip when you place the mouse cursor over the short description.

 

Short description:

mip3

Long description:

mip4

 

 

Defining language implementations

We are now at the point where we need to make a connection between the function in the Libraries window, and the function in the custom Java, C# or C++ classes. This is achieved through the <implementation> element.

 

As previously stated, one function may have multiple implementation elements – one for each supported programming language. A function may be called "helloFunction" in Java, or "HelloFunctionResponse" in C++. This is why you need to specify a separate function name for each programming language. A function for each of the three programming languages might look like the following:

 

...
<component name="hello">
...
  <implementations>
    <implementation language="cs">
        <function name="HelloFunction"/>
    </implementation>
    <implementation language="java">
        <function name="helloFunction"/>
    </implementation>
    <implementation language="cpp">
        <function name="HelloFunctionResponse"/>
    </implementation>
  </implementations>
...
</component>
...

 

The value you supply as function name must exactly match the name of the method in the Java, C# or C++ class.


© 2019 Altova GmbH