2017 June Release

Defining use casesPermanent link for this heading

Fabasoft Folio supports different types of actions that can be invoked on an object:

  • An Action (COOSYSTEM@1.1:Action) is considered to be the declaration of a private method that is implemented on one or more object classes. Actions can be marked as public.
  • A Use Case (COOSYSTEM@1.1:UseCase) is considered to be the declaration of a public method. It can provide different implementations on one or more object classes. Use cases can be marked as private.

For more information on public, private and obsolete see chapter “Public, private and obsolete”.

This section describes the definition of use cases using the app.ducx use case language of Fabasoft app.ducx.

Defining a new use casePermanent link for this heading

Syntax

usecase reference(parameter, ...) {
  accexec = accesstype;
  // Providing the implementation for one object class
  variant objectclass {
   ...
  }
  // Providing the same implementation for more object classes
  variant objectclass1, objectclass2 {
    ...
  }
}


The usecase keyword is used to declare a use case. It must be followed by the reference and by parentheses, holding the list of parameters or the prototype. Use cases define the public interface of the software component.

Note: An action is declared the same way, using the optional action keyword. Actions are ment to be private.

Defining the list of parametersPermanent link for this heading

Parameters must be separated by commas. For each parameter, the data type must be specified. For objects, use the object keyword or the reference of an object class when denoting the data type. For specifying an arbitrary data type, use the any keyword. Square brackets can be used to denote lists.

By default, parameters are treated as input parameters. Output parameters must be prefixed with the keyword out. For input/output parameters, the prefix ref must be used. The keywords retval out (out may be omitted) and retval ref denote parameters that are used as default return values. The keyword optional can be used to mark optional parameters. unique specifies unique lists in parameters.

can be used to mark an unspecified number of optional parameters at the end of the parameter list. The interface coometh.GetParameter() provides access to these arguments.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase CalcOrderPosValue(integer quantity, currency unitprice,
    out currency total, optional float rebate) {
    ...
  }

  usecase CalcOrderTotal(OrderPosition[] positions, boolean includetax,
    out currency total, out currency tax) {
    ...
  }

  usecase ValidateOrderPositions(ref unique OrderPosition[] positions) {
    ...
  }

  usecase CreateCollectiveInvoice(Order[] orders, retval Invoice invoice) {
    ...
  }

  usecase MyPrint(string format, ) {
    ...
  }

}

Note: Even if you mark a parameter with retval it is not allowed to use return with a value in a method implementation. The only way to provide a return value of a method is by assigning a value to the corresponding parameter.

Assigning prototypes instead of a parameter listsPermanent link for this heading

Prototypes are component objects containing predefined sets of parameters. Certain use cases – such as property triggers described in chapter “Assigning triggers to a property” – require predefined prototypes in order to function correctly.

For assigning a prototype to a use case instead of specifying a list of parameters you can use the parameters as keywords followed by the reference of the prototype.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  // Skeleton of a get value trigger action
  action GetOrderTotal(parameters as AttrGetPrototype) {
    ...
  }

  // Skeleton of a set value trigger action
  action SetOrderPositions(parameters as AttrSetPrototype) {
    ...
  }
}

Protecting a use case with an access typePermanent link for this heading

The accexec keyword is used to assign an access type to a use case.

If protected by an access type, a use case can only be invoked if the user trying to invoke it is granted the access type by the object’s ACL. However, it is not mandatory to protect a use case with an access type. Please refer to chapter “Defining an access type” for further information on how to define access types.

Providing the implementation for a use casePermanent link for this heading

In order to be able to invoke a use case, you have to provide an implementation for one or more object classes. You may also provide different implementations of the same use case for different object classes just as in an object-oriented programming language, Fabasoft app.ducx allows an object class to provide a more specific implementation of a use case that is already implemented by one of its base classes. In this case, the implementation in the subclass overrides the implementation in the base class.

The Fabasoft Folio Kernel returns an error message if a use case is invoked on an object where no implementation is found in the object class of the object or in one of its base classes.

The variant keyword is used to denote the object classes for which an implementation of a use case is provided. There are various types of implementations:

  • The application keyword specifies a virtual application that is called when the use case is invoked. A virtual application is required when your use case implementation must display user interface elements. Please refer to chapter “Defining a virtual application” for further information on implementing virtual applications.
  • The java keyword denotes a Java use case implementation.
  • Please refer to chapter “

  • If you want to provide the same implementation for multiple object classes, you can enumerate these object classes in a comma separated list after the variant keyword.

In a variant block, you may also define optional use case hints to describe the behavior of the use case implementation. To define use case hints use the hints keyword, followed by curly braces and a list of use case hints as described by the next table.

Hint

Description

MH_CHANGESOBJ

The use case implementation changes the current object.

MH_NEEDSSERVER

The use case implementation requires a connection to the server.

MH_NEEDSARCHIVE

The use case implementation requires an archive implementation.

MH_NEEDSLOCALGUI

The use case implementation requires interaction with the graphical user interface.

MH_CHANGESVIEW

The use case implementation changes the current view.

MH_CREATESOBJ

The use case implementation creates a new object in the currently selected object pointer or object list.

MH_NEEDSEXPLORER

The use case implementation requires explore mode.

MH_NEEDSTREE

The use case implementation requires the tree view

MH_NEEDSPLUGIN

The use case implementation requires the client plugin

MH_NEEDSSINGLESEL

The use case implementation requires a single selection

MH_NEEDSMULTISEL

The use case implementation requires a multiple selection

MH_NEEDSDESKTOPORTABLET

The use case implementation requires at least a Desktop or a Tablet.

MH_NEEDSCURRENTVERSION

The use case implementation requires the object in the current version, not a historic version.

Table 20: Use case hints

Implementing a use case in app.ducx expression languagePermanent link for this heading

The app.ducx expression language can be used for implementing a use case. When implementing a use case as expression, the current object – that is the object on which the use case has been invoked – can be accessed using the cooobj variable. Additionally, the coort interface object can be used to access the Fabasoft Folio Runtime, and the cootx variable contains an interface to the current transaction. Parameter names can be used to access the parameters declared in the use case signature.

Note: The app.ducx compiler verifies the syntax of expressions, but it cannot completely verify semantic correctness.

Implementing a use case as an inline expressionPermanent link for this heading

In the following example, the use case CreateInvoice is implemented in object class APPDUCXSAMPLE@200.200:Order as an expression. The expression creates a new instance of object class APPDUCXSAMPLE@200.200:Invoice, initializes some of its properties, passes back the invoice object in parameter invoice, and references the new invoice in the APPDUCXSAMPLE@200.200:invoice property of the order.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase CreateInvoice(out Invoice invoice) {
    variant Order {
      expression {
        Invoice invoice = #Invoice.ObjectCreate();
        invoice.invoiceorder = cooobj;
        invoice.invoicedate = coonow;
        invoice.COODESK@1.1:ShareObject(null, null,
            #APPDUCXSAMPLE@200.200:invoice, cooobj);
      }
      hints = {
        MH_NEEDSSERVER,
        MH_CHANGESOBJ
      }
    }
  }
}


If a use case overrides one of its superclass's use cases, you can invoke the overridden use case through the use of the keyword super. Calling super is only allowed when coometh (holds the so-called method context) is available. in or ref parameters that are changed before the call of super are passed in the changed state. out or ref parameters are written to the local scope after the call of super.

Example

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase CallSuper(integer inx, retval string name) {
    variant Object {
      expression {
        name = inx;
      }
    }
    variant CompoundObject {
      expression {
        inx++;
        super();
        %%TRACE("name = ", name);
      }
    }
  }
}

Deprecated: Implementing a use case in a separate app.ducx expression language filePermanent link for this heading

Fabasoft app.ducx allows you to store the actual expression code in a separate app.ducx expression language file.

Example

app.ducx Use Case Language

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  usecase CreateInvoice(out Invoice invoice) {
    variant Order {
      file("CreateInvoice.ducx-xp");
    }
  }
}

app.ducx Expression Language (CreateInvoice.ducx-xp)

#APPDUCXSAMPLE@200.200:Invoice.ObjectCreate(null, &invoice);
invoice.APPDUCXSAMPLE@200.200:invoiceorder = cooobj;
invoice.APPDUCXSAMPLE@200.200:invoicedate = coonow;

Note: Using this way to specify an expression implementation is discouraged since there is no context available to perform compiler features like type checking. Additionally all identifiers must be fully qualified.

Defining a new menu use casePermanent link for this heading

Syntax

menu usecase reference on selected {
  variant objectclass {
    ...
  }
}

menu usecase reference on selected or container {
  variant objectclass {
    ...
  }
}

menu usecase reference on container {
  variant objectclass {
    ..
  }
}

menu usecase reference dynamic {

  get = CalculateMenu;
  variant objectclass {
    ...
  }
}


A menu use case is a special type of use case that is usually invoked by a user selecting a menu item in the user interface.

There are a few optional options available, specified by using keywords after the reference:

  • on selected: The menu use case is invoked on each object selected by the user. This is the default behavior.
  • on selected or container: The menu use case is invoked on each object selected by the user. However, if no objects have been selected, the menu use case is invoked on the container object instead. For example, if you are invoking a menu use case from within a folder but no objects have been selected in the folder, it is invoked on the folder itself.
  • direct or on container: The menu use case is invoked on the container object only. It is NOT invoked on any objects selected by the user. However, it is possible to get the currently selected objects by using COODESK@1.1:GetSelected from within the implementation of the menu use case. If the use case is implemented as virtual application, the selected objects are also available in the sys_selobjects parameter.
  • dynamic: The displayed menu is calculated by an action specified by the alias get, which is a shortcut for menugetaction. This action has to use the prototype COODESK@1.1:MenuGetActionPrototype. The menu use case is invoked on the container object only. The parameter sys_dynkey contains the index of the selected menu item.

To enable this functionality, a number of elements are required. These are generated automatically by the app.ducx compiler:

  • the menu object that can be added to a menu or a context menu,
  • the outer use case that is invoked on the container object (when using the on selected or on selected or container clause),
  • the implementation of the outer use case using method definition COODESK@1.1:CallSelectedObjectsMethod in object class COOSYSTEM@1.1:Object (when using the on selected or on selected or container clause),
  • the application mapping of the outer use case to FSCVENV@1.1001:DoSelected (when using the on selected or on selected or container clause), and
  • the inner use case that is invoked on each of the selected objects.

The following example shows the definition of a menu use case for setting the state of an instance of object class APPDUCXSAMPLE@200.200:Order to OS_SHIPPED. This menu use case is invoked on each of the order objects selected by the user. For this menu use case, the Fabasoft app.ducx compiler also generates a menu object with the reference APPDUCXSAMPLE@200.200:MenuMarkOrderAsShipped. In the example, this menu object is added to context menu APPDUCXSAMPLE@200.200:MenuRootOrderContext to allow users to invoke the use case from the context menu of an order to change the state of the order to OS_SHIPPED.

Note: Objects must be locked before they may be changed. To lock an object, COOSYSTEM@1.1:ObjectLock must be invoked on the object.

Example

app.ducx Use Case Language

usecases APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  menu usecase MarkOrderAsShipped on selected {
    // Use defined symbol in ressources file
    symbol = SymbolMarkOrderAsShipped;
    variant Order {
      expression {
        cooobj.ObjectLock(true, true);
        cooobj.orderstate = OrderState(OS_SHIPPED);
      }
    }
  }
}

app.ducx User Interface Language

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  // Assign the use case to the context menu of APPDUCXSAMPLE@200.200:Order
  menus for Order {
    MenuContextExtension {

      MenuMarkOrderAsShipped;

    }

  }
}


Note: Menu use cases can also be implemented in Java or as a virtual application. If implemented as virtual application, a predefined prototype is assigned to the virtual application:

For menu use cases employing the on selected or on selected or container clause the FSCVENV@1.1001:MenuPrototype prototype is assigned to the virtual application, and the parameters described in the next table are passed to it.

Variable

Description

venv_object

The variable venv_object stores the object the use case was invoked on.

venv_parent

The variable venv_parent stores the container from which the use case was executed.

venv_index

The variable venv_index stores the index of the object in the property from which the use case was executed.

venv_view

The variable venv_view stores the property from which the use case was executed.

venv_action

The variable venv_action stores the use case that is executed.

Table 21: Parameters of FSCVENV@1.1001:MenuPrototype

  • For menu use cases employing the direct or on container clause the FSCVAPP@1.1001:MenuPrototype prototype is assigned to the virtual application, and the parameters described in the next table are passed to it.

Variable

Description

sys_object

The variable sys_object stores the object the use case was invoked on.

sys_action

The variable sys_action stores the use case that is executed.

sys_view

The variable sys_view stores the property from which the use case was executed.

sys_selobjects

The variable sys_selobjects stores the objects selected in the property stored in variable sys_view.

sys_selindices

The variable sys_selindices stores the index of each selected object in the property stored in variable sys_view.

sys_dynkey

The variable sys_dynkey stores the key of the dynamic menu and is only available when the use case was executed from a dynamic menu.

Table 22: Parameters of FSCVAPP@1.1001:MenuPrototype