Generic Model Manipulation Language (GMML)
GMML is a human readable representation of manipulations, i.e. instances of types from the Manipulation Model.
For a quick reference see GMML Full Example.
On this page
General
GMML is primarily used to feed CollaborativeSmoodAccesses such as cortex incrementally with data to make it an event-source database.
For more information on
CollaborativeSmoodAccess, see Smart Memory Object-oriented Database.
Following example shows GMML in action without requiring you to read the subsequent detailed explanation.
User = foo.bar.User
Group = foo.bar.Group
Status = foo.bar.Status
user1 = User()
.name = 'John'
.birthday = date(1967Y,1M,14D)
.status = Status::active
user2 = User()
.name = 'Johanna'
.birthday = date(1970Y,5M,23D)
.status = Status::active
user3 = User()
.name = 'Paul'
.birthday = date(1972Y,12M,22D)
.status = Status::active
user1.friends = (user2, user3)
user2.friends = (user1, user3)
user3.friends = (user1, user2)
group = Group('group:the-extra-ordinaries')
.members + (user1, user2, user3)
This example shows how three new Users are being created, equipped with simple values and wired to each other via the friends property. Finally, an existing Group entity is looked up by its globalId and the three users are added to as its members.
Supported Manipulations
Implementation of GMML can be found in the com.braintribe.gm:ManipulationModel#2.0 artifact. With GMML, you can have a short notation of the certain manipulations that can happen:
- lifecycle manipulations
- property manipulations
- ChangeValueManipulation
- collection manipulations
 
The format can be parsed into instances of the ManipulationModel for maintenance operations and later execution or can be directly executed without creating those instances. The format can be generated in the following ways:
- programmatically
- using the ManipulationStringifier on a Manipulation instance
- using the ManMarshaller on any value from any model which will result
 
- manually
Statements
GMML grammar supports the following statements:
Variable Assignment Statements
These statements do not directly represent a manipulation but help to store values for reuse. Values can be assigned to variables with the following form:
variable = 'value'
Examples:
someVariable = 'Hello World!'
anotherVar = 1
$0 = true
_my_var1 = (1,2,3,4)
MyType = foo.bar.MyType
Property Manipulation Statements
These statements represent instances of the PropertyManipulation
Property manipulations can come in the following 2 forms:
- variable.property operator 'value'
- .property operator value
The variable must contain a value of the type entity, for example:
user2.name = 'john'
.friends + user1
If the variable name is left out the last targeted variable is used as property owner.
Property Operators
| Operator | Description | Value | Represented Manipulation | 
|---|---|---|---|
| = | Assigns a value to the property | any value | ChangeValueManipulation | 
| + | Inserts one or more elements to a collection | A single value or a collection of values | AddManipulation | 
| - | Removes one or more elements to a collection | A single value or a collection of values | RemoveManipulation | 
| -- | Clears a collection | No operand | ClearCollectionManipulation | 
Delete Entity Statements
This statements represent the DeleteManipulation
Entities can be deleted with following form:
- value
The value must be of the type entity. Here a concrete example with a variable as value:
- user
Properties
Properties are defined by EntityTypes and have a name and a type.
Variables
GMML uses variables to assign all kinds of values for reuse in the manipulations as operands. Variables can hold the following values:
- sub types of CustomType
- instances from the type system
Variable names can use one the following characters:
- a-z
- A-Z
- $
- _
- 0-9except for the first character
Type System
- scalar types
- simple types
- numeric types
- integer types
- integer- signed 32bit
- long- signed 64bit
 
- floating point types
- float- 32bit
- double- 64bit
- decimal- unlimited
 
 
- integer types
- boolean
- string- unicode
- date
 
- numeric types
- enum
 
- simple types
- custom types
- entity
- enum
 
- complex types
- entity
- parameterized collection types
- list
- set
- map
 
 
Values
Values are instances from the types of the type system.
Simple Values
| Type | Example Literals | 
|---|---|
| Boolean | truefalse | 
| string | 'Hello World' | 
| integer | 16 | 
| long | 1235678987654321L | 
| float | 3.14F | 
| double | 2.81D | 
| decimal | 4.669201609102990671853203821578B | 
| date | date(2018Y,10M,10D,10H,54m,43S,853s,+0200Z) | 
String Literal Rules
String literals are opened and closed with the single quote '. The cannot span over more than one line currently and behave very much like JavaScript string literals. Escape characters can be used to insert certain non printable characters and exotic codepoints:
| Escape | Meaning | Codepoint | Character | 
|---|---|---|---|
| \\ | Escape for the escape character | 92 | \ | 
| \uxxxx | Unicode codepoint | generic | |
| \b | backspace | 8 | |
| \t | horizontal tab | 9 | |
| \n | line feed | 10 | |
| \f | form feed | 12 | |
| \r | carriage return | 13 | |
| \' | single quote | 39 | ' | 
Date Literal Rules
Date literals are given in the following form:
date(dateFragment, ...)
The number of given date fragments is free and missing fragments are assumed to have a base value. The fragments are added up to make up the whole date. The following dateFragment literals are supported:
| Date Fragment | Format | Example | 
|---|---|---|
| Year | integer with suffix Y | 1976Y | 
| Month | integer with suffix M | 1M | 
| Day | integer with suffix D | 14D | 
| Hour | integer with suffix H | 13H | 
| Minute | integer with suffix m | 42m | 
| Second | integer with suffix S | 30S | 
| Millisecond | integer with suffix s | 835s | 
| Time Zone | +or-hhmmZ | +0100Z | 
Examples
date(1992Y)
date(1992Y,10M,10D)
Enum Constants
Enum values come in the following form:
type::constant
Example with a prepared variable for the type:
Status = foo.bar.Status
user.status = Status::active
Example with variable assignment for the type:
user.status = (Status = foo.bar.Status)::active
Entity Values
Entity Instantiations
Such values represent an InstantiationManipulation. They are formed in the following way:
type()
Example with a prepared variable for the type:
User = foo.bar.User
user = User()
Example with variable assignment for the type:
user = (User = foo.bar.User)()
Entity Lookups
Such values do not represent any manipulation and only lookup existing entities to continue with incremental operations on them. Such values are formed in the following way:
type('globalId')
Example with a prepared variable for the type:
User = foo.bar.User
user = User('globalId')
Example with variable assignment for the type:
user = (User = foo.bar.User)('globalId')
Entity Acquires
Such values represent an AcquireManipulation and are formed in the following way:
type['globalId']
Example with prepared variable for the type:
User = foo.bar.User
user = User['globalId']
Example with variable assignment for the type value:
user = (User = foo.bar.User)['globalId']
Collection Values
Collections may only contain non collection values as elements which are of the following type:
- simple values
- entities
- enum constants
List Values
List values are formed in the following way:
[value1, value2, ....]
Examples:
[1,2,3]
['Hello','World']
[1,true,var,]
Set Values
Set values are formed in the following way:
(value1, value2, ....)
Examples:
(1,2,3)
('Hello','World')
(1,true,var,)
Map Values
Map values are formed in the following way:
{key1: value1, key2: value2, ....}
Examples:
{1: 'Hallo',2: 'World'}
{var1: 1L, var2: date(1976Y)}
Collection Delta Values
| Value Form | Valid for Collection Target Type | Description | 
|---|---|---|
| value | list, set | appends/inserts or removes a single value. | 
| (value1, value2, ...) | list, set | appends/inserts or removes a single value | 
| {pos1: value1, pos2: value2} | list, map | inserts/puts values |