Skip to content

Users Guide

Preface

A model file is a normal text file with the ending “.gapp”. Model files have to be located in the workspace and can be edited by any text editor. The editor of the Virtual Developer Modeler (VDM) has some advantages, though.

  • syntax highlighting
  • markers for syntax errors
  • code-proposals and code-completion
  • outline-view
  • tool-tips for model elements (mouse over)

The domain spceific language (DSL) “gapp” allows for the definition of new DSLs. All DSLs share the same file structure. The VDM’s editor recognizes DSL definitions by reading “.gapp” files that are found in the “assets” directory or by scaning installed plug-ins that adhere to certain conventions. More information about the definition of new DSLs can be found in the developers guide.

File Structure

A model file basically has the following structure. Please note that the square and round brackets are not part of the syntax and it is not about templates. Square brackets stand for variable ids or names. Round brackets stand for optional parts of the syntax.

namespace [namespace];

import [import0];
import [import1];
...
import [importN];

/*
 * Documentation for module
 */
module [module-name] kind = [comma-separated list of module-types];

set [option-name] = [option-value(s)];
link [option-name] = [referenced element(s)];

/*
 * Documentation for element
 */
[element-type] [element-name] (extends [element-name]) {

    set [option-name] = [option-value(s)];
    link [option-name] = [referenced element(s)];

    /*
     * Documentation for member
     */
    [member-type] [member-name] : [element-name] {
        set [option-name] = [option-value(s)];
        link [option-name] = [referenced element(s)];
    }
}

...
more elements
...

Generic Concepts

Namespace

The namespace is a mandatory model element. It always denotes the start of a model file.

A namespace is used to be able to distinguish two model elements that have the same name but represent different model elements. Typically, a modeled namespace results in a namespace in generated code, e.g. packages in Java or Namespaces in .NET. Here is an example:

namespace com.gs.gapp;  // first line in model file

Module

Every model file represents a “Module”. The sole purpose of a module is to pool a set of model elements. Every module can be imported into another module that is present in the same Eclipse project. The name of a module has to be identical with the name of the model file.

A module can be modeled independently from any defined DSL. Only by using the keyword “kind”, the types of elements that are allowed to be used in a module are determined. In addition to that, “kind” determines which other module types can be imported in a module. Here is an example:

...
module MyModule kind = Persistence;
...

In the module “MyModule” only element types that are defined in the DSL “Persistence” may be used. The module type “Persistence” also sets the rule that only modules of type “Asset” or “Basic” may be imported.

When the keyword “kind” is not specified, as a consequence all available element types can be used for modeling.

Import

With import statements, elements that are defined in other modules are going to be re-used. Imports don’t work transitively. When module A imports module B and B imports module C, then module A does not automatically import module C.

The option to import other modules is limited by the definition of module types. A more detailed guidance can be found in the developers guide. Normally, you only need this information when you plan to develop your own DSLs.

In an import statement, the name of a module is prefixed with the module’s namespace. Here is an example for the module “ContactsPersistence”.

namespace my.name.space;

import com.gs.gapp.sample.contacts.entities.ContactsPersistence;
...

Comment

Similar to how it is done in Java, comments are written above of model element definitions. Comments are optional and can be added for mdoules, elements and members. They are not only for the modelers but fully-fledged model elements that can be processed by generators. Here is an example for a module comment:

/*
 * This module includes a simple
 * model element that serves as
 * an example for basic codegeneration
 * functionality.
 */
module hello-world;

Please note that comments written with /* and */ always belong to a model element. Such comments cannot float freely in the model. For free floating comments use the C/C++ like comment characters // instead. They can be placed everywhere.

Fundamental Syntax Rules

There are a few fundamental syntax rules that simplify the acquisition of DSLs: * Statements for element and member are terminated with a semicolon or alternatively with a block of curly braces. * Namespace-, import- and module-statements are terminated with a semicolon. * Options that are used to define values start with the keyword “set” and are terminated with a semicolon. * Options that are references to other model elements start with the keyword “link” and are terminated with a semicolon. * All model elements have a name.

DSL-specific Concepts

Element types, member types and options are specific to a DSL. The “gapp” DSL itself does not define such things. Instead, the “gapp” DSL offers a syntax to define element types, member types and options. That syntax is only of interest for somebody who intends to develop own DSLs. More details related to this can be found in the developers guide.

Module-Type

Module types are there to group a set of element types. An element type logically belongs to one or more module types. Module types are applied during modeling when using the keyword “kind”. A DSL designed for the usage in the VDM can contain one or more module types. A module type itself can rule, which other module types can be imported when that module type is applied.

Element

Elements are modeled with the help of element types that themselves are defined in DSLs. Modeled elements also serve as types for members and can also be referenced by means of options (keyword “link”). Here is an example from the DSL “Persistence”, where the element type “entity” is used.

entity BaseEntity {

    set Storable = false;

    field pk : PrimaryKey {
        set Id = true;
    }
}

Member

Members are modeled by using member types that are defined in DSLs. They are modeled within an element’s code block that is delimited with curly brackets. Also members can be referenced by options (keyword “link”). Here is the same example from the DSL “Persistence” that has been used further above. The member type “field” is used here.

entity BaseEntity {

    set Storable = false;

    field pk : PrimaryKey {
        set Id = true;
    }
}

Option

Options can be modeled for modules, elements and members. An option can have one or more values (number, text, boolean, enumeration). Such options are modeled with the keyword “set”. A special type of option can be used to set references to other modules, elements and members. This special type of option is used with the keyword “link”. Options can have default values. Those default values are not defined by a DSL but by a generator that uses the model files as input.

Again, here is the same example from the DSL “Persistence” that has been used further above. The options “Storable” and “Id” are used here.

Built-In Module-Types and Options

The Virtual Developer Modeler comes with a few predefined module types and options. They help to organize the definition of new DSLs and allow for a more flexible type system. Here are the predefined module types:

Module-Types

Module-Type Description
Asset A module, that has this module type set as “kind” attribute, contains a DSL definition. This module type is only being used when defining a new DSL
Aliasing A module, that has this module type set as “kind” attribute, contains the definition of type aliases. A module with this type can be provided by developers of new DSLs. But its also possible that every user of a DSL defines her own type aliases, in order to end up with more expressive models. Generators then resolve the aliases before executing the main part of the code generation.

Options

Module-Type Option Option-Type Description
Aliasing Type Reference, single valued References a model element, that is of the same type as the model element for which the option is set. This option can be used for modules, elements and members.
ALL TypeFilterGroups Text, multi valued Is set on the module level. Allows the definition of names that can be used to activate type aliases. The names defined with this option are going to be used with the option “TypeFilters”.
ALL TypeFilters Text, multi valued Is set on the module level. By specifying one or more of the names that were defined with “TypeFilterGroups”, the related type aliases are activated and used for the parsing of the model as well as the code-completion mechanism.
ALL Abstract Boolean Can be set for modules, elements or members. For elements this option typically is set to true in order to tell a generator that the element is only used in an inheritance structure and does not play any other role during generation.

Keyword Reference (Generic Syntax)

Here all keywords and syntax rules are listed that can be used for modeling. Those keywords and syntax rules that are used to define new DSLs are explained in the developers guide. A description of the supplied built-in DSLs can be found in the DSL sections.

Keyword Syntax-Rule Comment
namespace namespace [name]; The name can include alpha-numeric characters and dots. It must not begin with a number or dot. It is mandatory to model a namespace and there is only one namespace per module/file.
import import [module-namespace].[module-name]; There can be as many import statements as you want.
module module [name] (kind = [module-type] (,[module-type])*); The setting of “kind” is optional. Typically, you do use it, though. This way you have cleaner models where the code-proposal lists are much shorter.
set set [option-name] = [value] (, [value])*; The keyword “set” is used the same way for all DSLs. An option name, option value-type and the number of allowd values is DSL-specific.
link link [option-name] = [ref] (, [ref])*; The keyword “link” is used the same way for all DSLs. The allowed type for the referenced model element is DSL-specific. [ref] denotes the name of the referenced model element.
extends extends [element-name] An optional, single inheritance relation between model elements of the same type.