2017 June Release

Common characteristics of DSLsPermanent link for this heading

Each DSL is an independent declarative modeling language having its own set of language constructs and keywords designed with a particular purpose in mind. However, all DSLs also share certain similarities. These common characteristics and language elements that are the same across all DSLs of Fabasoft app.ducx are presented in this section.

Keywords, expressions and blocksPermanent link for this heading

A DSL consists of a unique set of keywords for addressing a particular aspect of solution development. However, there are shared keywords that are common to all DSLs.

The Fabasoft app.ducx compiler is case-sensitive. All keywords must be in lower case.

Each expression must be terminated by a semicolon or be enclosed in a block. A block consists of one or more expressions enclosed in curly braces.

Operators and punctuatorsPermanent link for this heading

There are several kinds of operators and punctuators. Operators are used in expressions to describe operations involving one or more operands.

Examples for operators and punctuators are { } [ ] ( ) , . : ; + - * / % & | ^ ! ~ = < > ? ++ -- && || == != <= >= <=> += -= *= /= ->.

CommentsPermanent link for this heading

Two forms of comments are supported: single-line comments and delimited comments. Single-line comments start with the characters // and extend to the end of the source line. Delimited comments start with the characters /* and end with the characters */. Delimited comments may span multiple lines. Comments do not nest and are not processed within character and string literals.

Multilingual stringsPermanent link for this heading

Multilingual strings are not defined in the source code but in separate resource files in order to keep the source code free of any hard-coded strings. By default, the resource files holding multilingual strings are named mlnames.lang. For each language you want to support, a separate resource file must be created.

The main benefit of this approach is that all language-specific string resources are maintained in a single resource file for the particular language, which allows for a quick and hassle-free localization of your software application.

Resource files are automatically updated whenever you add a new element requiring a multilingual name (e.g. object classes, properties, or use cases) or another form of multilingual string, such as the label text for an input field on a form page or the text displayed for enumeration items in a drop-down list.

The language resource editor (see figure) is invoked when opening the mlnames.lang file. It allows you to enter a language-specific string for each multilingual string resource in your app.ducx project.

To edit the multilingual strings for all elements that are part of your software component open the mlnames.lang file in the Eclipse Project Explorer.

If a language string is not yet translated, the background color of this line is changed and after a successful build of this project, a warning is generated.

Beside mlnames.lang files, explanations.userdoc files (XML) are provided for defining explanation texts for properties. Simple XHTML tags like <b></b>, <i></i> or <br/> may be used to format the strings. These explanation texts can be displayed as context-sensitive help in the Fabasoft Folio Web Client. For detailed information on the help system, please refer to the white paper “Online Help in the Fabasoft Folio Web Client”.

Note: For your convenience it is recommended that you use an XML editor for editing explanation texts. To assign the userdoc file extension to your favorite XML editor open the “Window” menu and click “Preferences”. Navigate to “General” > “Editors” > “File Associations”. Add the userdoc file extension and associate the desired editor. The editor may be an internal Eclipse plug-in or an external XML editor.

Multilingual strings and explanation texts are not removed automatically when the corresponding reference is removed from the source code. Thus, you do not lose strings when temporarily commenting out some source code. To clean up multilingual names and explanation texts use the context menu command “Clean up Language Files”.

Using fully qualified references for referring to component objectsPermanent link for this heading

In all DSLs, component objects can be addressed by their fully qualified reference.

Each component object has a unique programming name, which is described by its fully qualified reference that indicates a logical hierarchy. For example, COOSYSTEM@1.1:objsubject is the fully qualified reference of a component object with the reference objsubject that is part of software component COOSYSTEM@1.1.

In Fabasoft app.ducx, a software component is somewhat similar to a namespace in an object-oriented programming language: all component objects belonging to a particular software component are nested in this namespace.

The following example shows part of an object model containing the definition of object class Product. This object class is derived from object class COOSYSTEM@1.1:BasicObject. Furthermore, the existing property COOSYSTEM@1.1:mlname is assigned to the object class. Please note that fully qualified references are used for referring to both of these component objects belonging to software component COOSYSTEM@1.1.

Example

objmodel APPDUCXSAMPLE@200.200
{
  class Product : COOSYSTEM@1.1:BasicObject {
    COOSYSTEM@1.1:mlname;
  }
}

Using the import statementPermanent link for this heading

Using the import statement, a software component can be made known to the compiler in order to avoid the need for using the fully qualified reference when referring to a component object that is part of the imported software component.

Once a software component has been imported using an import statement, you can refer to component objects belonging to this software component with their reference only, instead of having to use the fully qualified reference. This allows for the software component prefix to be left out when referring to its component objects once a software component has been imported.

A list of import statements is referred to as import declarations. All import declarations have to be placed inside objmodel, resources, userinterface, usecases, processes or orgmodel blocks. The different types of models are described in greater detail in the following chapters.

Note: Software components listed in the import declarations must be referenced in your Fabasoft app.ducx project’s list of software component references. For further information on software component references, refer to chapter “Adding a software component reference”.

Example

objmodel APPDUCXSAMPLE@200.200
{
  // Importing COOSYSTEM@1.1 permits the use of reference shorthands when
  // referring to component objects that belong to COOSYSTEM@1.1, instead

  // of requiring the use of fully qualified references

  import COOSYSTEM@1.1;

  class Product : BasicObject {
    mlname;
  }
}


It should be noted that even when a software component is imported using an import statement it is still valid to refer to component objects of the imported software component using the fully qualified reference.

Resolving of simple referencesPermanent link for this heading

A reference that is not fully qualified may be ambiguous, because component objects belonging to different software components might have the same reference. References of the own software component are favored over references of other software components. In all other cases the fully qualified reference must be used to refer to these component objects.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import FSCREC@1.1001;

  // "Record" is not sufficient for unique qualification, because it could
  // refer to either FSCFOLIO@1.1001:Record or FSCREC@1.1001:Record

  class DUCXRecord : FSCFOLIO@1.1001:Record {
    ...
  }

  class SpecialRecord : FSCREC@1.1001:Record {
    ...
  }

  class State : FSCFOLIO@1.1001:State {
    ...
  }

  // "State" refers to APPDUCXSAMPLE@200.200:State because the own
  // software component is favored

  class SpecialState : State {
    ...
  }
}

Resolving of qualifiers in app.ducx expressionsPermanent link for this heading

Beyond the resolving strategy of not fully qualified references some more rules apply to app.ducx expressions.

As a general rule of thumb, whenever you use qualifiers provide a type for the qualifiers to avoid ambiguities.

In following cases special resolving rules apply:

Compound properties

  1. Attempt to resolve the qualifier to a Fabasoft Folio Kernel Interface Method.
  2. Attempt to resolve the qualifier to a property of the compound property.
  3. No further resolving attempt is carried out and an error is generated.

In the following example GetTypeDefinition is resolved to a Fabasoft Folio Kernel Interface Method and isbn to a property of the compound property publication.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase ResolveCompoundProperty() {
    variant Order {
      impl = expression {
        Publication @publication = {};
        @publication.GetTypeDefinition();
        @publication.isbn;
      }
    }
  }
}


Objects

  1. Attempt to resolve the qualifier to a Fabasoft Folio Kernel Interface Method.
  2. Attempt to resolve the qualifier to a property of the object.
  3. Attempt to resolve the qualifier to an action or use case of the object.
  4. No further resolving attempt is carried out and an error is generated.

In the following example GetClass is resolved to a Fabasoft Folio Kernel Interface Method, orderpositions to a property of the object order and ResolveCompoundProperty to a use case of the object order.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase ResolveObject() {
    variant Object {
      impl = expression {
        Order @order = #Order.ObjectCreate()[2];
        @order.GetClass();
        @order.orderpositions;
        @order.ResolveCompoundProperty();
      }
    }
  }
}


Item Scope

  1. Attempt to resolve the qualifier according to the rules for the type of the list.
  2. Attempt to resolve the qualifier according to the rules of the local scope.
  3. No further resolving attempt is carried out and an error is generated.

In the following example objname is resolved to COOSYSTEM@1.1:objname and name to a key in the local scope.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase ResolveObjectList(string name) {
    variant Object {
      impl = expression {
        Object[] objects =
          coort.SearchObjects(cootx, "SELECT * FROM
                
COOSYSTEM@1.1:Object WHERE objname LIKE 'Test%'");
        objects[objname == "Test"];
        objects[objname == name];
      }
    }
  }
}


Dictionaries

  1. Attempt to resolve the qualifier to a Fabasoft Folio Kernel Interface Method.
  2. Attempt to resolve the qualifier to a dictionary key.
  3. No further resolving attempt is carried out and an error is generated.

In the following example key is resolved as dictionary key.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase ResolveDictionary() {
    variant Object {
      impl = expression {
        dictionary @dict = {};
        @dict.key = "Test";
        // alternative
        dictionary @dict = { key: "Test" };
        // alternative
        dictionary @dict;
        @dict = coort.CreateDictionary();
        @dict.key = "Test";
      }
    }
  }
}


Other data types

  1. Attempt to resolve the qualifier to a Fabasoft Folio Kernel Interface Method.
  2. No further resolving attempt is carried out and an error is generated.

Using generic assignment statementsPermanent link for this heading

Fabasoft app.ducx allows you to include so-called generic assignment statements in your source code in order to assign values to Fabasoft Folio properties. You may only reference properties that actually belong to the object class of the component object denoted by the Fabasoft app.ducx language element the assignment statement is nested in.

Initialization of properties with scalar valuesPermanent link for this heading

Syntax

property = value;


For initializing a property with a scalar value, the reference of the property must be denoted followed by the equality character, and the value. The assignment statement must be terminated by a semicolon.

In the following example, the COOSYSTEM@1.1:attrextension property of a content property should be initialized with the value “txt”. However, there is no language element provided by any of the Fabasoft app.ducx DSLs for defining the value for this property. Thus, a generic assignment statement must be used for defining the value of this property as illustrated by the following example.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;

  class OrderRecord : Record {
    content orderspecification {
      attrextension = "txt";
    }
  }
}

Initialization of scalar compound propertiesPermanent link for this heading

Syntax

property = {
Assignment;

  …

}


When setting a scalar compound property, the commonly used syntax can be used.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;

  class OrderRecord : Record {
    classdocstateicons = {
      dsirecorded = true,

      dsidocstate = DS_EDIT,

      classmicon = MiniIconRecord_Edit

    }
  }
}

Initialization of array valuesPermanent link for this heading

Syntax

property = [value, value, value]


When setting array properties, the familiar expression syntax can be used, even with compound properties.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;

  class OrderRecord : Record {
    classdocstateicons = [

      {

        dsirecorded = true,

        dsidocstate = DS_EDIT,

        classmicon = MiniIconRecord_Edit

      },

      {

        dsirecorded = true,

        dsidocstate = DS_SUSPENDED,

        classmicon = MiniIconRecord_Suspended

      }

    ];

  }
}

Initialization of expression valuesPermanent link for this heading

Syntax

property = expression {

}


When setting expression properties, the keyword expression is used to describe an expression block.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;

  instance Expression MyExpression {

    exprtext = expression {

    }

  }
}

If the expression property does not specify parameters or a scope type, the keyword as and an expression property definition can be used to specifiy this information.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;

  instance FilterExpression MyFilterExpression {

    exprtext = expression as attrfilterexpr {

      return objowner == coouser

    }

  }
}

Initialization of compound properties, compact modePermanent link for this heading

Syntax

property<member, ...> = {
  { value, ... }
}


When assigning a list of values to a compound property, a special syntax can be used to create a very compact, table like initialization form. The reference of the compound property to be initialized must be followed by angle brackets. In the angle brackets, the references of the properties belonging to the compound property’s type that should be initialized with values must be specified. The initialization values provided must be enclosed in curly braces and separated by commas. Null values can be defined using the null keyword. Additionally, multiple lines must be separated by commas as well.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;

  class OrderRecord : Record {
    classdocstateicons<dsirecorded, dsidocstate, classmicon> = {
      { true, DS_EDIT, MiniIconRecord_Edit },
      { true, DS_SUSPENDED, MiniIconRecord_Suspended },
      { true, DS_CLOSED, MiniIconRecord_Closed },
      { true, DS_CANCELLED, MiniIconRecord_CancelledRec }
    }
  }
}


Compound properties can also be nested within other compound properties. The following example demonstrates the initialization of nested compound properties.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COOWF@1.1;
  import COODESK@1.1;

  extend class WorkList {
    dispviews<dispviewattr, dispviewcomp, dispcolumns<dispattribute>> = {
      { worklistitems, APPDUCXSAMPLE@200.200,
        {
          { objname },
          { actinstwork },
          { { actinstobject, bocontact } },
          { { actinstobject, boassignedto } },
          { actinstremark },
          { actinstreceivedat },
          { actinstenddeadline }
        }
      }
    }
  }
}

Public, private and obsoletePermanent link for this heading

Component objects may be marked as public, private or obsolete using the keywords public, private and obsolete.

Following rules apply:

  • Component objects are public by default except in following cases:
    • Actions are private by default but can be marked as public.
    • Activities that are defined within the scope of a process are private by default but can be marked as public.
  • Implicitly generated component objects not defined in the source code (like menus or applications for a use case) are public, private or obsolete depending on the definition of the component object itself that triggers the implicit generation of component objects.

Cloud profile note: All component objects are by default private. They must be explicitly marked as public when required.

PrivatePermanent link for this heading

Private component objects can only be used within the software component the component object is created in and in friend components (For further information on how to create a friend relation, please consult chapter “Defining a friend component”).

The type of the parameters of a public action or a public attribute must be also public. The private constraint is enforced by Fabasoft app.ducx the following way:

  • When using external private component objects of a non-friend component an error is generated.
  • External private component objects in non-friend components are excluded from IntelliSense.
  • Java: External private component objects in non friend components are not available.

ObsoletePermanent link for this heading

Obsolete component objects denote component objects that should not be used anymore and that are likely no longer available in prospective versions. To determine obsolete component objects Fabasoft app.ducx provides following support:

  • When using obsolete component objects a warning is generated.
  • Obsolete component objects are excluded from IntelliSense.
  • Java: Obsolete component objects are marked as deprecated.

Referencing resourcesPermanent link for this heading

The file keyword is used to reference a resource such as an image or another type of binary or text file. It must be followed by parentheses holding the relative path to the resource file enclosed in double quotes. The path must be specified relative to your Fabasoft app.ducx project.

The file keyword can also be used to reference app.ducx expressions that have been defined in separate app.ducx expression language files.

Example

// Referencing a symbol imported to the "resources/symbols" folder of the
//
app.ducx project
symbol SymbolApprove {
  images<symbolimageformat, content> = {
    {
      SF_PNG16,
      file("resources/symbols/Approve16.png")
    }
  }
}

// Referencing an expression in an app.ducx expression language file
impl = file("resources/expressions/GetOrders.ducx-xp");