Annotations
Annotations are meta data expressed in a Mosel source file (model or package) that are stored in the resulting BIM file after compilation. This additional information is either global or associated with public globally declared objects (including subroutines). Annotations do not have any direct impact on the model itself as they are treated like comments. Typical uses of annotations include model documentation or application configuration information.
Mosel annotations have the following format:
- a single-line annotation starts with '!@' and a name
!@doc.name This is my document title
- multi-line annotations are surrounded by '(!@' and '!)'
(!@mynote Some annotation text. Another line of text. !)
- '!@' is followed by the annotation name (identifier)
- no space between '!' and '@' characters
- space is allowed between '@' and the name
- value assignment operators are ' ' (space), ':', or '='
- no space between annotation name and operator
!@mynote contents for 'mynote' !@ another=contents of 'another' !@third: contents of 'third'
- association with symbols:
!@mynote This annotation is applied to all objects declared below public declarations val: integer !@doc.descr Explanation of 'val' !@doc.descr Text associated with 'msg' msg: string ! A standard comment !@mynote2 This annotation is ignored (no associated object) end-declarations
Annotations are organized in categories. A category groups a set of annotations and other categories (or sub-categories). For example
doc.namenamedocmcdoc'_'
We show some examples of the doc category in Section moseldoc: Generating model documentation below. The category mc is used to pass information to the compiler during the compilation, including the (optional) declaration of new annotations with the mc.def annotation or the definition of aliases, such as
!@mc.def descr alias doc.descr insight.descr
Accessing annotations
Annotations can be retrieved from the model itself during its execution or before/after execution from the calling program (using the Mosel libraries). The following example annottest.mos shows how to retrieve an annotation that is defined in the same model. The subroutine getannotations is defined by mmjobs, it takes an additional first argument of type Model if it is to be applied to a submodel and not the model itself.
model "Using annotations" uses "mmjobs" public declarations (!@. @value.first 5 @value.second 0 @descr A scalar value !) myint: integer AnnNames: set of string !@descr Set of annotation names Ann: array(string) of string !@descr Annotation values mytxt: text !@descr Default input data file end-declarations !@descr Annotations test !@furtherinfo Simply displays all defined global or specific annotations ! Get all global annotations defined in this model: getannotations("", "", AnnNames, Ann) writeln("Global annotations:") forall(a in AnnNames) writeln(" ", a, " = ", Ann(a)) ! Get all annotations for "myint": getannotations("myint", "", AnnNames, Ann) writeln("Annotations defined for 'myint':") forall(a in AnnNames) writeln(" ", a, " = ", Ann(a)) ! Retrieve all annotations starting with 'value.' and that are ! associated to 'myint' getannotations("myint", "value.", AnnNames, Ann) writeln("'value' annotations for 'myint':") forall(a in AnnNames) writeln(" ", a, " = ", Ann(a)) end-model
Running this model produces output like the following:
Global annotations: .descr = Annotations test .furtherinfo = Simply displays all defined global or specific annotations Annotations defined for 'myint': .descr = A scalar value value.first = 5 value.second = 0 'value' annotations for 'myint': value.first = 5 value.second = 0
And here is an example how to retrieve annotations into a C program (file annotdisplay.c):
#define MAXANN 100 int main() { XPRMmodel mod; void *ref; const char *symb; /* A model object name */ const char *ann[MAXANN*2]; /* List of annotations */ int i,n; if(XPRMinit()) return 1; /* Initialize Mosel */ if((mod=XPRMloadmod("annottest.bim",NULL))==NULL) /* Load a BIM file */ return 2; /* Retrieve and display global annotations */ n=XPRMgetannotations(mod,NULL,NULL,ann,MAXANN*2); printf("Global annotations (total: %d):\n", n/2); for(i=0;i<n && i<MAXANN;i+=2) printf(" %s:%s\n",ann[i],(ann[i+1]!=NULL)?ann[i+1]:""); /* Retrieve and display all annotations associated with model objects */ printf("Annotations associated with objects:\n"); ref=NULL; while((symb=XPRMgetnextanident(mod,&ref))!=NULL) { n=XPRMgetannotations(mod,symb,NULL,ann,MAXANN*2); printf(" %s->\n",symb); for(i=0;i<n && i<MAXANN;i+=2) printf(" %s:%s\n",ann[i],(ann[i+1]!=NULL)?ann[i+1]:""); } /* Retrieve and display annotations for model object 'myint' */ n=XPRMgetannotations(mod,"myint",NULL,ann,MAXANN*2); printf("Annotations defined for 'myint' (total: %d):\n", n/2); for(i=0;i<n && i<MAXANN;i+=2) printf(" %s:%s\n",ann[i],(ann[i+1]!=NULL)?ann[i+1]:""); return 0; }
The corresponding Java code looks as follows:
public class annotdisplay { public static void main(String[] args) throws Exception { XPRM mosel; XPRMModel mod; XPRMAnnotation ann[]; // List of annotations mosel = new XPRM(); // Initialize Mosel mod = mosel.loadModel("annottest.bim"); // Load a BIM file // Retrieve and display global annotations ann=mod.getAnnotations(""); System.out.println("Global annotations (total: "+ ann.length +"):"); for(int i=0;i<ann.length;i++) System.out.println(" "+ann[i]); // Retrieve and display all annotations associated with model objects System.out.println("Annotations associated with objects:"); for(XPRMIdentifiers ids=mod.annotatedIdentifiers(); ids.hasNext();) { XPRMIdentifier id=(XPRMIdentifier)ids.next(); ann=mod.getAnnotations(id,""); System.out.println(" "+id.getName()+"->"); for(int i=0;i<ann.length;i++) System.out.println(" "+ann[i]); } // Retrieve and display annotations for model object 'myint' ann=mod.getAnnotations("myint",""); System.out.println("Annotations defined for 'myint' (total: "+ ann.length +"):"); for(int i=0;i<ann.length;i++) System.out.println(" "+ann[i]); } }
Notice that the host application only needs to load the BIM file (and not necessarily run a model) in order to be able to retrieve the annotations.
moseldoc: Generating model documentation
The Mosel compiler reserves a special treatment to annotations belonging to the doc category. This annotation category will only be included into the BIM file if the source file is compiled with the option -D, such as
mosel comp -D mymodel.mos
The tool moseldoc can be applied to the resulting BIM file to generate an XML file that is then processed into a set of HTML pages:
moseldoc mymodel ! Generates HTML and XML moseldoc -html mymodel ! HTML output only moseldoc -o mydir -html mymodel ! Specify HTML output directory moseldoc -xml mymodel ! XML output only moseldoc -ixml mymodel ! XML file for inclusion (omitting header+root) moseldoc -f mymodel ! Force output overwrite
Here are some examples of how to use the documentation annotations:
- Document structure:
(!@doc. @title An example of model documentation @version 0.0.1 @date March 2015 @chapter Introduction @p This model needs to be compiled with the <tt>-D</tt> compiler option to include the documentation annotations into the BIM. The <tt>moseldoc</tt> program takes the resulting BIM file as input. !) !@doc.chapter The example !@doc.section Parameters
The resulting cover page and table of contents generated by moseldoc look as follows (the contents listing also refers to the entity and subroutine annotations shown in the following items):
- Documenting parameters:
parameters !@doc.descr Short parameter description !@doc.value v1 possible value !@doc.value v2 another possible value !@doc.info Some more explanation (longer text) MYPAR="some text" end-parameters
- Documenting entity declarations (type definitions, constants, variables):
!@doc.section Constants and variables public declarations (!@doc. @descr Short description of the constant set @info Some additional information !) S=1..10 !@doc.descr An error code constant MYERR=11 (!@doc. @descr A record type @recflddescr fld1 field description @recflddescr fld2 another field description @info Several @doc.info tags can be used for a given entity @info Entities can be referenced: <entRef>rectype</entRef> !) rectype=record fld1:integer fld2:string end-record end-declarations
This is the HTML page generated by moseldoc from these parameter and entity annotations:
- Documenting subroutines:
!@doc.section Subroutines (!@doc. @descr A short description @param i first parameter @paramval i value1 description of value1 @paramval i value2 description of value2 @param r second parameter @err MYERR reference to an error code constant @return The return value @example Some descriptive text for the example @example [SRC] the example code is here @info Some useful information for <tt>myfunct</tt> @related <fctRef>myotherfunct</fctRef> !) function myfunct(i:integer,r:real):boolean returned:=i>r end-function !@doc.group myfunct !@doc.info <tt>myotherfunc</tt> is an alternative to <fctRef>myfunct</fctRef> function myotherfunc(i:integer):boolean returned:=true end-function
The HTML subroutine documentation page generated by moseldoc from these annotations is shown here:
- Relocating documentation contents:
!@doc.section A section title !@doc.relocate newlocref ... ! All doc annotations defined here will be inserted at marker 'newlocref' !@doc.relocate ... ! All subsequently defined doc annotations remain where they are !@doc.section Destination location !@doc.location newlocref
- Excluding contents from generated documentation:
!@doc.autogen=false public declarations ... ! All doc annotations defined here will be ignored end-declarations !@doc.autogen=true ... ! All subsequently defined doc annotations will get processed