The Mobo Manual
Premises
To learn mobo, it is mandatory to understand the basic concepts of JSON and JSON Schema first. I would also highly recommended to learn YAML and use it instead of JSON.
JSON Schema is a simple and concise standard which can be learned in a few hours. There is a great tutorial by the Space Telescope Science Institute. The time learning JSON Schema is a good investment anyhow. It is a versataile standard that can be used in many different situations.
Some understanding of MediaWiki, SemanticMediaWiki and SemanticForms is also highly recommended, since they are the target system. Their architecture has a huge impact on how models are developed.
If the default templates need to be changed, an understanding of the Handlebars.js template engine is of advantage.
Create a new project
To start with the model development, an empty project structure has to be created first:
mkdir newProject # Create new dir
cd newProject # Enter new dir
mobo --init # Create bootstrap project
Mobo comes with example projects, which may be a good starting point to learn mobo. Use mobo -h
to view the available options.
They can be copied to the current project directory with the --example
flag:
mobo --example hardware
How to write the mobo-model (JSON vs YAML)
It is possible to write the model in the JSON or the YAML notation. In either case, the data structure of Mobo Schema (JSON Schema) is the same and must be adhered to.
It is a matter of personal taste which notation format might be prefered. JSON is barebone, explicit and very strict, because it is a machine optimized data-serialization format by design. YAML is a bit more concise and more implicit (and therefore more forgiving). It supports comments and some comfort features like pipes. It is arguably easier to read and write by humans.
Mobo uses YAML by default. Here is a comparison:
YAML-Notation:
# Inline comments are possible. This is not true for JSON.
title: Location
description: Location where hardware is deployed
items:
- $extend: /field/streetAdress
- $extend: /field/streetNumber
- $extend: /field/town
- $extend: /field/country
required:
- streetAdress
- streetNumber
- town
smw_prefix:
header: 1
wikitext: Some prefix-description for the location
smw_postfix: |
Some postfix-description for the location
Supporting easy line breaks
JSON-Notation:
{
"title": "Location",
"description": "Location where hardware is deployed",
"type": "array"
"items": [
{ "$extend": "/field/streetAdress" },
{ "$extend": "/field/streetNumber" },
{ "$extend": "/field/town" },
{ "$extend": "/field/country" }
],
"required": [
"streetAdress",
"streetNumber",
"town"
],
"smw_prefix": {
"header": 1,
"wikitext": "Some prefix-description for the location"
},
"smw_postfix": {
"wikitext": "Some postfix-description for the location"
}
}
To batch-convert a project from JSON to YAML notation (or the other way around), I can recommend the yamljs CLI tool or the json2yaml.com WebApp. Conversion between both formats should be easy and fast, so the choice of notation format should have no lock in effect.
Since YAML is a superset of JSON, it is also possible to write/mix JSON into .yaml files.
Mobo Schema
Mobo uses JSON Schema as a basis for the model development. To fit the model development better, some additions and simplifications are introduced. The adjusted JSON Schema will be referred to as mobo Schema.
Additions
Inheritance: $extend
The $extend
keyword is used to inherit other models and implicitly defines how those relate to each other.
It takes a string (or an array of strings) that describe the path to another model file.
$extend
can be used with fields, models, forms and smw_templates. Circular dependencies are not allowed.
Parent - Child Inheritance
Use $extend
on the main level, to inherit a parent object and extend it:
# Inherit an abstract _Shape
$extend: /model/_Shape
# Overwrite title
title: Circle
# Add a new field (in addition to those that are inherited)
items:
- $extend: /field/radius
This goes hand in hand with the $abstract
keyword.
Inheritance to include and reference to other model parts
Use $extend
to include fields in models, models in forms, or templates in forms.
The inheritance works just the same as on the main level.
This is how the actual model structure and the relationships between forms, models and fields are defined.
TIPP: You can overwrite inherited properties by adding them on the same level as the extend.
title: Model with fields
items:
- $extend: /field/fieldOne
- $extend: /field/fieldTwo
title: Overwrite the title of fieldTwo
Inheritance Behaviour
Mobo will inherit all properties of the referenced parent object to the child object where this statement was made. If an array of multiple parent objects is given, the inheritance order will be the order of the array.
Properties of the child object will merge or overwrite inherited properties:
- Primitive Datatypes like Strings, Numbers and Booleans will be overwritten
- Objects will be merged. In the case that two properties share the same key, the merging algorithm is recursively executed.
- Arrays can behave in different ways. Multiple annotations can be used to define the merging behavior:
@overwrite
: The children overwrites the parent completely@prepend
: The children elements are prepended@append
: The children elements are appended@unique
: The resulting array removes all duplicate items@sorted
: The resulting array will be sorted alphabetically@unsorted
: The resulting array will not be sorted (undo @sorted)
The default array merging behaviour is defined in the settings and can be customized.
Important: In YAML the annotations have to be put in ''
or ""
, because @
is a reserved YAML Directive.
Example: This will result in an array of a, b, c
itemsOrder:
- '@unique'
- '@sorted'
- b
- c
- a
- b
JSON Schema has a similar keyword, called $ref
.
The official spec does not specify an inheritance behavior, though.
To avoid confusion, mobo supports only the custom $extend property.
$remove
$remove
is an array, that contains the IDs of all item
to remove.
Use this to remove any unwanted items that have been inherited from parents.
Use this with care! A good designed object oriented structure probably wont need this.
$remove:
- fieldThree
$abstract
Abstract objects will only be used for inheritance purposes.
They do not create any wiki related pages.
The $abstract
keyword is not inherited, so children of abstract objects don't have to explicitly set abstract: false.
$ignore
To (temporarily) remove objects from the model the ignore attribute can be set to true.
The $abstract
keyword is not inherited, so children of abstract objects don't have to explicitly set abstract: false.
itemsOrder
To change the order of the items array, the keyword itemsOrder
can be used.
This becomes necessary when the inherited items do not end up in the desired order.
The itemsOrder
keyword takes an array of the IDs of the items. (The ID is the filename of the referenced object.)
Any items that have not been mentioned will be appended at the bottom in their original order.
itemsOrder:
- ip
- macAdress
SMW / SF specific Additions
There are many platform and implementation specific additions to the schema.
They are prefixed with smw_
and sf_
and support the various settings
and possibilities of Semantic MediaWiki and Semantic Forms.
The platform specific options are often directly passed through to the end system. In those cases, the available options are documented by the end system.
Example: SemanticForms field tag (see official documentation)
sf_form:
input type: combobox
values from namespace: Manufacturer
max values: 1,
existing values only: true
Removals
The following JSON Schema properties are not supported:
$ref
additionalItems
additionalProperties
allOf
anyOf
definitions
dependencies
exclusiveMaximum
exclusiveMinimum
multipleOf
not
patternProperties
uniqueItems
The $ref
and definition
property are substituted with mobos own $extend
property.
The reason the other (primarily validation oriented) properties are not supported is because the target system (SMW + Semantic Forms) has not much validation capabilities. Advanced validation properties can be used for internal validation, though (e.g. programmatic imports).
Continue Learning
Now that you've learned the basics of mobo, you may continue with:
- The tutorial gives a fast overview how it's like to work with mobo
- An overview about the project structure
- The project structure also contains a complete and up to date documentation of all available properties.