AMIL Language and Interpreter
Author: Basil Krikeles, BAE Systems - Technology Solutions
Version 1.0
March 5, 2011
Introduction
The
purpose of AMIL is to serve as the ARRoW Model Interconnection
Language. AMIL is a meta-model for modeling interconnections between
heterogeneous models while making minimal assumptions about the nature
of these models. For example, AMIL makes no assumption about shared
meta-models as is the case in many modeling tool chains such as Eclipse
Modeling Framework. The strategy in AMIL is to to only assume that
external models and modeling tools provide some sort of access
interface and that they are capable of exporting unique identifiers for
modeling elements that are relevant across multiple models. AMIL
creates proxies for these elements as nodes in an attributed graph.
These nodes can be associated with related nodes (proxie of other model
elements) with attributed edges. The approach is fundamentally lazy, i.e.
represent only the proxies that are required and only introduce the
interconnections that are useful. The underlying attributed graph
semantics provides a general and extremely flexible foundation in
support of the model interconnection semantics. Both nodes and edges of
the interconnection network contain lists of key-value pairs that can
be extended without arbitrary limit. New relationship types can be
introduced on demand without compromising performance.
Retrieval
of information from the graph has additional semantics that enables the
dynamic extraction of information from the authoritative source model
(see getNodes). With the added semantics, AMIL
is arbitrarily extensible (always in a lazy fashion) to accomodate
heterogeneity in the external models.
AMIL Interpreter Interface
AMIL Interpreter exposes one interface with the following signature:
String execute(String amilStmt)
where amilStmt
is a valid AMIL statement formatted as a JSON string, and the return
value is also a JSON formatted string containing the results of the
execution of the amilStmt. This document lists the supported AMIL statements and provides examples of their syntax in terms of JSON.
The
AMIL interpreter interface with its JSON binding can be easily exposed
as a Web Service. Java applications can embed the AMIL interpreter. A command line client is also included.
Execution of AMIL statements has transactional semantics. The statement is executed within a transaction, and either all of its parts succeed or all fail.
The AmilInterpreter constructor has the following signature:
AmilInterpreter (String dbDir)
where
dbDir is a directory where the database files are stored. This
directory can be passed to the front-end web service, can be read
from a properties file, or it can be hard coded.
AMIL Command Line tool
It is implemented in the class: com.ait.meta.lang.Amil.java
java -Damil_server=dbDir -classpath=... com.ait.meta.lang.Amil amilFile [amilFile]
where each amilFile contains a single AMIL statement.AMIL Statement Syntax in JSON format
AMILStatement =>
[Action, SequenceOfNodeOrEdge]
Action =>
{
action : actionName,
preConditions : {predicateList},
postConditions : {predicateList}
}
actionName =>
"createNodes"
| "createLinks" | "getNodesRaw" | "getNodes" | "getLinks" |
"deleteNodes" | "deleteLinks" | "updateNodes" | "clearDatabase"
PredicateList => PredicateCall | PredicateCall, PredicateList
PradicateCall => predicateName : [parameterList]
ParameterList=> String | String, ParameterList
SequenceOfNodeOrEdge=>
NodeOrEdge,
NodeOrEdge, SequenceOfNodeOrEdge
NodeOrEdge=>
{
type : nodeOrEdgeType,
uniqueId : {nameValueList}
}
NameValueList=> name : value | name : value, NameValueList
NodeOrEdgeType=> node | edge
AMIL Statements
- createNodes
- createLinks
- getNodesRaw
- getNodes
- getLinks
- deleteNodes
- deleteLinks
- updateNodes
- clearDatabase
- getClosure
Statement Description
createNodes
Example
[
{
"action" : "createNodes",
"preConditions" : {},
"postConditions" : {}
},
{
"type" : "node",
"massOfFrame1" :
{
"modelType" : "Behavior",
"toolName" : "OpenModelica",
"elementId" : "A1979_z",
"projectId" : "//server/meta/modelica/proj.mod"
}
},
{
"type" : "node",
"massOfFrame2" :
{
"modelType" : "SysML",
"toolName" : "MagicDraw",
"elementId" : "123",
"projectId" : "//server/meta/sysml/proj.mzip"
}
}
]
createLinks
Example:
[
{
"action" : "createLinks",
"preConditions" : {},
"postConditions" : {}
},
{
"type" : "edge",
"reference1" :
{
"type" : "REFERENCE",
"from" : "massOfFrame1",
"to" : "massOfFrame2"
}
}
]
getNodesRaw
Synopsis:
Unconditionally retrieve the nodes listed according to their unique
identifier. It does not take any actions based on the semantics of the
node, e.g. an valueType property that might be present in a node.
Example:
[
{
"action" : "getNodesRaw",
"preConditions" : {},
"postConditions" : {}
},
{
"massOfFrame1" : {}
},
{
"massOfFrame2" : {}
}
]
getNodes
Synopsis:
Retrieve the nodes listed according to their unique identifier but
subject to configurable semantic interpretation based on the optional valueType property. If valueType is not present the result is immediate and equivalent to the action of getNodesRaw on that node. This is the default action. If the property valueType is present and its value is externalCall, then the property className should also be present. Instead of returning the node, getNodes returns the result of invoking the class with name className with the node, serialize in JSON format, as a parameter. The target class must implement the External interface
This is one mechanism that enables the introduction of levels of
indirection in accessing the proxies in the graph. The external call
can invoke an external tool in order to dynamically retrieve
information from its counterpart.
Example:
[
{
"action" : "getNodes",
"preConditions" : {},
"postConditions" : {}
},
{
"massOfFrame" : {}
}
]
Where massOfFrame was created as follows:
[
{
"action" : "createNodes",
"preConditions" : {},
"postConditions" : {}
},
{
"type" : "node",
"massOfFrame" :
{
"modelType" : "SysML",
"toolName" : "MagicDraw",
"elementId" : "123",
"projectId" : "//server/meta/sysml/proj.mzip",
"valueType" : "external",
"className" :
"com.ait.meta.lang.ExternSample"
}
}
]
getLinks
Example
[
{
"action" : "getLinks",
"preConditions" : {},
"postConditions" : {},
"depth" : "2"
},
{
"type" : "edge",
"dummy" :
{
"type" : "REFERENCE",
"from" : "a",
"to" : {}
}
}
]
deleteNodes
Example
[
{
"action" : "deleteNodes",
"preConditions" : {},
"postConditions" : {}
},
{
"a" : {}
},
{
"d" : {}
},
{
"foo" : {}
}
]
deleteLinks
Example
[
{
"action" : "deleteLinks",
"preConditions" : {},
"postConditions" : {},
},
{
"type" : "edge",
"dummy" :
{
"type" : "REFERENCE",
"from" : "a",
"to" : "b"
}
},
{
"type" : "edge",
"dummy" :
{
"type" : "REFERENCE",
"from" : "d",
"to" : "e"
}
}
]
updateNodes
Example
[
{
"action" : "updateNodes",
"preConditions" : {},
"postConditions" : {}
},
{
"type" : "node",
"a" :
{
"modelType" : "b_x",
"toolName" : "b_y",
"elementId" : "b_z",
"projectId" : "b_proj"
}
},
{
"type" : "node",
"e" :
{
"modelType" : "f_x",
"toolName" : "f_y",
"elementId" : "f_z",
"projectId" : "f_proj"
}
}
]
clearDatabase
Note: After a clearDatabase statement it appears that in the current implementation all indices are removed. Since getNodes and getNodesRaw
rely on the index, the underlying Lucene implementation will generate a
runtime error if an attempt is made to call them after the clearDatabase call.
Example
[
{
"action" : "clearDatabase",
"preConditions" : {},
"postConditions" : {}
}
]
getClosure
Example
[
{
"action" : "getClosure",
"entryPoints" : ["a", "anotherNode"],
"relationships" : ["r1", "r2", "rel"],
"doRelationshipClosure" : "",
"preConditions" : {},
"postConditions" : {}
}
]
Semantics
The
getClosure action starts by retrieving the nodes referenced in the
"entryPoints" property. Starting with these nodes it retrieves all
nodes that can be reached by following relationships referenced in the
"relationships" property. If the "doRelationshipClosure" property is
not present, the getClosure action will return the reachable nodes
(including the entry point nodes) and the relationships (links) that
are referenced in the "relationships" property. If the
"doRelationshipClosure" property is present then the result of
the action are the nodes reached plus all the relationships (links)
between these nodes whether they are referenced in the "relationships"
property or not. The value of the "doRelationshipClosure" property does
not matter, it is its presence or absence that is used.
Appendix A - Interfaces
External
public interface External {
/**
*
* @param params are the input parameters of
* the external call as key-value pairs,
* same as the properties (key-val pairs) stored in the AMIL node
* @return the results as key-value pairs
*
* When implementing this use whatever means necessary to
* make the external call using parameters extracted from params
* params has everything that was in the AMIL node
* The result should have everything produced by the computation.
*/
Map<String, String> invoke(Map<String, String> params);
}