2017 June Release

Adding properties to an object classPermanent link for this heading

Each object class can have several properties defined in which to store various data.

Reusing existing propertiesPermanent link for this heading

Existing properties can be reused and referenced within an object class or within a compound type. When an existing property is referenced, this property must be available in the Fabasoft app.ducx cache.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class FileCategory : BasicObject {
    // Reusing object pointer property FSCFOLIO@1.1001:dcstate
    FSCFOLIO@1.1001:dcstate;
  }
}


When reusing properties, keep in mind that changes to the original property might affect your solution. For instance, the definition of the selectable object classes in the FSCFOLIO@1.1001:dcstate property in the example might be changed in a future version. As a result, reusing properties might result in unpredictable side-effects in some cases.

Defining new propertiesPermanent link for this heading

Syntax

datatype reference modifiers;


New properties can only be defined directly within an object class or within a compound type. For each property defined using Fabasoft app.ducx, a corresponding property component object is created as part of the project’s software component.

A property must be defined based on a valid Fabasoft Folio data type. Each property can either store a scalar value or a list of values of the specified data type. Add square brackets after the data type for defining a property for storing a list of items.

There are two ways of defining a new property: the simple shorthand notation and the extended notation for including triggers and constraints in a property definition.

A shorthand property definition consists of

  • a data type
  • square brackets as an optional list marker
  • a reference
  • a semicolon

Additional features concerning property definitions are covered in chapter “Extended property definitions”.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Project : CompoundObject {
    // Creates a new property of data type COOSYSTEM@1.1:STRINGLIST
    // with the reference
APPDUCXSAMPLE@200.200:projectdescription
    string[] projectdescription;
  }
}

Data typesPermanent link for this heading

In Fabasoft Folio, every property must have a data type. Fabasoft Folio supports simple data types, enumeration types, and compound types.

Simple data typesPermanent link for this heading

Simple data types are provided by software component COOSYSTEM@1.1. The next table shows a list of simple data types supported by Fabasoft Folio.

Simple data type

Keyword

Maximum Size

COOSYSTEM@1.1:STRING

string

4000 characters

COOSYSTEM@1.1:BOOLEAN

boolean

COOSYSTEM@1.1:INTEGER

integer, time, timespan

20 digits

COOSYSTEM@1.1:FLOAT

float

16 digits

COOSYSTEM@1.1:DATETIME

date, datetime

COOSYSTEM@1.1:Currency

currency

COOSYSTEM@1.1:CONTENT

content

COOSYSTEM@1.1:DICTIONARY

dictionary

COOSYSTEM@1.1:OBJECT

object

Table 2: Simple data types

For most simple data types, a corresponding list data type is provided for storing lists of items of this type. The supported list data types are depicted in the next table.

Simple data type

Keyword

COOSYSTEM@1.1:STRINGLIST

string[]

COOSYSTEM@1.1:BOOLEANLIST

boolean[]

COOSYSTEM@1.1:INTEGERLIST

integer[], time[], timespan[]

COOSYSTEM@1.1:FLOATLIST

float[]

COOSYSTEM@1.1:DATETIMELIST

date[], datetime[]

COOSYSTEM@1.1:CONTENTLIST

content[]

COOSYSTEM@1.1:DICTIONARYLIST

dictionary[]

COOSYSTEM@1.1:OBJECTLIST

object[]

Table 3: List data types

Enumeration typesPermanent link for this heading

For information concerning the definition and extension of enumeration types, please consult chapter “Defining enumeration types”.

Compound typesPermanent link for this heading

For information concerning the definition and extension of compound types, please consult chapter “Defining compound types”.

Defining a string propertyPermanent link for this heading

The string keyword denotes a data type that stores a string of characters and can be used for defining string properties.

The length of a string can be specified enclosed in parentheses. A string can have a maximum length of 254 characters. If the length is not specified, the default length of 254 characters is assumed.

Note: String lists can be used for multiline input fields.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Task : BasicObject {
    // String property holding a maximum of 254 characters
    string shortdescription;

    // Sized string property holding a maximum of 2 characters
    string(2) state;

    // String list property that is displayed as a multiline input field
    string[] longdescription;
  }
}

Defining a Boolean propertyPermanent link for this heading

The boolean keyword is used to define properties to store the Boolean values (true and false).

Note: A Boolean property can actually have three states in Fabasoft Folio as it can also be undefined.

Example

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

  class Application : Case {
    boolean approved;
  }
}

Defining an integer number propertyPermanent link for this heading

The integer keyword denotes a simple data type and can be used to define integer number properties that store values consisting of up to 10 digits.

Integers may be signed or unsigned. Unsigned integers are capable of representing only non-negative values whereas signed integers are capable of representing negative values as well.

For defining unsigned integers use the unsigned integer keywords.

For an integer, its size in digits can be specified enclosed in parentheses. Valid size values are from 1 up to 10 digits. If no size value is specified, the default size of 10 digits is assumed.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class TaxReport : BasicObject {
    // Integer number property with 10 digits
    integer netchange;

    // Sized integer number property with 3 digits
    integer(3) taxrate;

    // Unsigned integer number property with 10 digits
    unsigned integer taxpayers;

    // Sized unsigned integer number property with 4 digits
    unsigned integer(4) fiscalyear;
  }
}

Defining a floating-point number propertyPermanent link for this heading

The float keyword denotes a floating-point number data type that represents a real number and can be used to define floating-point number properties to store values consisting of up to 16 digits in total with a maximum of 9 digits of precision.

The float keyword can be preceded by the keyword unsigned to denote an unsigned float which can only represent non-negative values.

For a floating-point number property, the size in digits before and the number of digits of precision can be specified enclosed in parentheses. If no size values are specified, the default sizes of 10 digits before with 2 digits of precision are assumed.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class AssetPerformance : BasicObject {
    // Floating-point number property with 10 digits before
    // and 2 digits of precision

    float assetvalue;

    // Sized floating-point number property of a 3 digit number with
    // 2 digits of precision

    float(3,2) ytdchange;

    // Sized unsigned floating-point number property of an 8 digit number
    // with 6 digits of precision

    unsigned float(8,6) exchangerate;
  }
}

Defining a date propertyPermanent link for this heading

The date keyword is used for defining a property to store a date value.

The datetime keyword is used for defining a property that stores both a date and a time value.

For the datetime keyword, you can append the suffix local to force that the value is converted to local time each time the property is accessed using a kernel interface. Alternatively, you can add the optional suffix universal, which is omitted by default. A universal date/time value is not converted to the user’s local time zone when it is accessed.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Milestone : BasicObject {
    // Date only property
    date deadline;

    // Date and time property with local time conversion enabled
    datetime documentreceivedat local;

    // Date and time property with local time conversion disabled
    datetime kickoffmeetingat;
  }
}

Defining a time propertyPermanent link for this heading

The time keyword is used for defining a property to store a time value.

Time values are stored in seconds in an integer number property of data type COOSYSTEM@1.1:INTEGER. The COOATTREDIT@1.1:CTRLTimestamp control is used for displaying time values in time format.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  struct Session {
    string sessiontitle;
    time sessionstartat;
    time sessionendat;
  }

  class Conference : BasicObject {
    // Compound property storing a list of conference sessions
    Session[] sessions;
  }
}

Defining a time span propertyPermanent link for this heading

The timespan keyword is used for defining a property to store a time span.

The time span is stored in an integer number property of data type COOSYSTEM@1.1:INTEGER. The COOATTREDIT@1.1:CTRLTimespan control is used for displaying the time span in days, hours, minutes, and seconds.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class MailPollingDefinition : BasicObject {
    // Time span for defining the e-mail polling interval
    timespan pollinginterval;
  }
}

Defining a currency propertyPermanent link for this heading

The currency keyword is used to define a currency property that represents an amount of money in a certain currency.

For a currency property, the size in digits before and the number of digits of precision can be specified enclosed in parentheses.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Project : CompoundObject {
    // Currency property for storing an amount of money in a currency
    // that can be selected by the user

    currency projectvalue;


    // Sized currency property of a 12 digit number with
    // 4 digits of precision

    currency(12,4) foreignchange;
  }
}

Defining a content propertyPermanent link for this heading

A content property that is defined using the content keyword can store any kind of binary data, such as a Microsoft Word or LibreOffice document.

A file can be imported into a content property from the file system, and conversely content that is stored in a content property can be exported to the file system.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Project : CompoundObject {
    // Content property for storing a project plan in a binary format
    content projectplan;
  }
}

Defining a dictionary propertyPermanent link for this heading

A dictionary is a list of key-value pairs. Each key-value pair consists of a string which is used as a key for addressing the dictionary entry, and a value or a list of values of the same Fabasoft Folio data type.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class StatusLog : BasicObject {
    // Dictionary property for storing key-value pairs
    dictionary valuedict;
  }
}

Defining an object pointer propertyPermanent link for this heading

An object pointer property can store a pointer to an object or a list of pointers to objects.

No explicit keyword is required for defining an object pointer property. Instead, the object class of the objects that shall be referenced by the new object pointer property is used as data type.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class PeerGroup : BasicObject {
    // Object pointer for referencing a user object
    User responsibleuser;

    // Object list for storing a list of user objects
    User[] groupmembers;
  }
}


By default, instances of all object classes that are directly or indirectly derived from the object class provided in the definition can be selected in the object pointer. A default object pointer property will also allow the creation of new object instances within the property. However, for object pointer properties, you can provide an extended definition of the object classes allowed and not allowed in the property in order to limit the selectable and creatable items.

The allow keyword can be used to define a list of object classes that should be allowed in the object pointer property, and the exclude keyword can be used for excluding object classes. Both the object classes listed in the allow block and in the exclude block must be either directly or indirectly derived from the object class provided in the object pointer property definition.

For each of the object classes listed within an allow block, the create keyword can be added after the reference of the object class to allow the creation of instances of this object class in the object pointer property. If the create keyword is omitted, no instances can be created directly within the object pointer property.

Object classes listed within an allow or exclude block must be separated by semicolons.

The allowcommonclasses keyword defines that the object pointer property can contain all common object classes (all object classes with common set to true).

Example

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

  class Department : BasicObject {
    // This definition creates an object pointer for referencing a
    // person object; it will not allow the creation of a new person

    // object within the object pointer

    Person deptmanager {
      allow {
        Person;
      }
    }

    // This definition creates an object list for storing objects that
    // can contain persons and employees but no contact persons; only

    // employee objects can be created in this list

    Person[] deptmembers {
      allow {
        Person;
        Employee create;
      }
      exclude {
        ContactPerson;
      }
    }
    // This definition creates an object list for storing all
    // common documents classes

    ContentObject[] documents {
      allowcommonclasses = true;
    }
  }
}

Defining enumeration typesPermanent link for this heading

In contrast to properties, which are defined directly within an object class, an enumeration type can only be defined as a separate objmodel model element.

A custom enumeration type can be defined using the enum keyword which must be followed by a reference and a block containing the permissible enumeration items separated by commas.

Each enumeration item can be assigned a specific integer value. For enumeration items that are not assigned to a specific integer value, the compiler automatically generates integer values. To do so, the compiler simply increments the integer value of the preceding enumeration item by 1, starting with value 1 for the first item if it does not have an assigned value.

Note: It is highly recommended to explicitly assign integer values to every enumeration item to avoid errors with extensions of the enumeration type later on.

Example

objmodel APPDUCXSAMPLE@200.200
{
  // Enumeration type consisting of three enumeration items which are
  // assigned system generated integer values, starting with 1

  // This kind of writing is not recommanded, because of the automatic numeration

  // it is highly error-prone on extension or expansions

  enum ProjectState {
    PS_PLANNED,
    PS_UNDERWAY,
    PS_COMPLETED
  }

  // Enumeration type consisting of four enumeration items with
  // explicitly assigned integer values

  enum ShipType {
    ST_DESTROYER = 100,
    ST_CRUISER = 200,
    ST_BATTLESHIP = 300,
    ST_SUBMARINE = 400
  }

  // Enumeration type consisting of six enumeration items with an
  // explicitly assigned starting value; the remaining enumeration items

  // get assigned integer values 5001, 5002, 5003 and so on.

  enum NewEnglandStates {
    ST_CONNECTICUT = 5000,
    ST_NEWHAMPSHIRE,
    ST_MAINE,
    ST_MASSACHUSETTS,
    ST_RHODEISLAND,
    ST_VERMONT
  }

  // Enumeration type consisting of enumeration items with partially
  // assigned integer values

  enum DrinkType {
    DT_SHOT = 800,        // integer value 800 manually assigned
    DT_LONGDRINK = 850,   // integer value 850 manually assigned
    DT_SOUR,              // integer value 851 generated by compiler
    DT_FIZZ,              // integer value 852 generated by compiler
    DT_HIGHBALL,          // integer value 853 generated by compiler
    DT_SOFTDRINK = 900, // integer value 900 manually assigned
    DT_OTHER              // integer value 901 generated by compiler
  }
}


Note: Existing enumeration types can be extended with additional enumeration items. For details on how to extend an existing enumeration type with additional enumeration items, please consult chapter “Extending an existing enumeration type”.

Using the keyword obsolete enumeration values can be defined as disabled. Drop down lists for enumeration values in the user interface do not contain disabled values.

Example

objmodel APPDUCXSAMPLE@200.200
{
  // Enumeration type consisting of four enumeration items with
  // exp
licitly assigned integer values, some of them disabled

  enum ShipType {

    ST_DESTROYER = 100,
    ST_CRUISER = 200,
    obsolete ST_BATTLESHIP = 300,
    obsolete ST_SUBMARINE = 400
  }

}

In rare cases it is necessary to specify some other attributes for the type. This is accomplished by using generic assignments before the block of enumeration values.

Example

objmodel APPDUCXSAMPLE@200.200
{
  // Enumeration type consisting of four enumeration items with
  // exp
licitly assigned integer values and some generic assignments before

  enum ShipType {

    typemultiple = true;

    typelistunique = true;
    ST_DESTROYER = 100,
    ST_CRUISER = 200,
    ST_BATTLESHIP = 300,
    ST_SUBMARINE = 400
  }

}

Defining an enumeration propertyPermanent link for this heading

As with an object pointer property, no explicit keyword is required for defining an enumeration property. Instead, you must provide the enumeration type which you want to assign to the new enumeration property.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  enum Transmission {
    TR_AUTOMATIC = 10000,
    TR_MANUAL = 10001
  }

  enum Options {
    OP_LEATHERSEATING = 20000,
    OP_AIRCONDITIONING = 20001,
    OP_FOGLAMPS = 20002
  }

  class Car : BasicObject {
    // Enumeration property that can store a single enumeration item
    Transmission transmission;

    // Enumeration property that can store a list of enumeration items
    Options[] options;
  }
}

Defining compound typesPermanent link for this heading

A compound type is a structure that can contain a list of properties of any valid Fabasoft Folio data type. Similarly to enumeration types, compound types can be defined or extended within an objmodel block.

Defining a new compound typePermanent link for this heading

A custom compound type can be defined using the struct keyword that must be followed by a reference and a block containing the properties that should become part of the compound type separated by semicolons.

You can either reference existing properties or define new properties directly within a compound type.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  // Compound type for storing publications
  struct Publication {
    string title;                   // new property for storing the title
    userfirstname;                  // reuse first name property
    usersurname;                    // reuse surname property
    integer(4) yearofpublication;   // new year of publication property
    string isbn;                    // new isbn property

    typecast = TypeCastPublication; // type cast
  }
}

Defining the key for a compound typePermanent link for this heading

For a compound type, you can define one or more key properties. The key is evaluated for determining unique entries in a property using the compound type.

The properties making up the key must be referenced in a block that is assigned to COOSYSTEM@1.1:typeuniqueattrs.

In addition to setting the key properties for a compound type, you can also define that compound properties using this compound type can contain unique entries only. To enforce unique keys, COOSYSTEM@1.1:typelistunique must be set to true.

In the following example, the APPDUCXSAMPLE@200.200:isbn property is specified as the key for compound type “Publication”. Additionally, the COOSYSTEM@1.1:typelistunique is set to true so the compound type will only allow entries with a unique ISBN.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  struct Publication {
    string isbn;
    string title;
    typelistunique = true;    // require unique entries
    typeuniqueattrs = {       //
      isbn                    // list of key properties
    }                         //
  }
}


Note:
You can also extend existing compound types with new properties. For details on how to extend an existing compound type with new properties, please consult chapter “Extending an existing compound type”.

Defining a type cast for a compound typePermanent link for this heading

Optionally a type cast may be defined. In expressions the type cast allows you to assign values directly to properties of the compound type, based on the type of the value without need to explicitly specify the property. The type cast defines which type should be assigned to which property. The TypeCastPrototype has two parameters: source and target.

In the following example string lists are assigned to features and integers and floats are assigned to productioncosts. In an expression you can make following assignment: Feature feature = 300;. The result is the same as when writing feature.productioncosts = 300;.

Note: The direct assignment to the compound property productioncosts works because for currencies a default type cast is provided by default.

Example

app.ducx Object Model Language

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  struct Feature {
    currency productioncosts;
    string[] features;

    typecast = TypeCastFeature;
  }
}

app.ducx Use Case Language

usecases APPDUCXSAMPLE@200.200
{
  TypeCastFeature(parameters as TypeCastPrototype) {
    variant Object {
      impl = expression {
        Feature target = {};
        if (typeof(source) == #STRINGLIST) {
          target.features = source;
        }
        else if (typeof(source) == #INTEGER || typeof(source) == #FLOAT) {
          target.productioncosts = source;
        }

        target;
      }
    }
  }
}

Using a primary property for direct assignmentsPermanent link for this heading

For some compound properties it is likely that only one property of the compound property is set (e.g. FSCVAPP@1.1001:applytofield). For this case a property of the compound property can be marked by setting COOSYSTEM@1.1:typeprimaryattr. Additionally the predefined type cast COOSYSTEM@1.1:TypeCast has to be used.

In the following example title is marked as primary property thus assignments like Publication publication = “An Introduction to Fabasoft app.ducx”; are possible.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  struct Publication {
    string title;
    userfirstname;
    usersurname
    integer(4) yearofpublication;
    string isbn;

    typecast = TypeCast;
    typeprimaryattr = title;
  }

}


For following compound types primary properties are defined:

Compound type

Primary property

FSCVAPP@1.1001:Branch

FSCVAPP@1.1001:identopt

FSCVAPP@1.1001:ApplyToField

FSCVAPP@1.1001:identopt

COOSYSTEM@1.1:LanguageStringList

COOSYSTEM@1.1:langstring

COOSYSTEM@1.1:LanguageContentList

COOSYSTEM@1.1:langcontent

COOSYSTEM@1.1:Content

COOSYSTEM@1.1:contcontent

COOSYSTEM@1.1:Currency

COOSYSTEM@1.1:currvalue

Table 4: Compound types and corresponding primary properties

Note: Direct assignments can not only be utilized in expressions but also in domain specific languages for initializing values or defining instances.

Specifiying a concrete compound typePermanent link for this heading

Sometimes it is necessary to use a more specialized compound type as type for a compound property. This can be achieved by listing the required type after the struct keyword.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  struct<TypeCustomizationPointDef> CPManualCreated {
    ObjectClass objcls;

    component;

    string title;

  }
}

Defining a compound propertyPermanent link for this heading

In the same way as for an enumeration property, the definition of a compound property does not require a special keyword. Instead, the compound type is used as data type for the new compound property.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  struct OrderPosition {
    integer quantity;
    Product product;
  }

  class Product : BasicObject {
    ...
  }

  class Order : CompoundObject {
    // Compound property for storing a list of order positions
    OrderPosition[] orderpositions;

    // Compound property that is reusing the compound type
    // COOSYSTEM@1.1:Content

    Content orderdescription;
  }
}

Defining a link propertyPermanent link for this heading

A link property allows you to create a bidirectional relationship between objects. There are two ways to establish such a relationship. On the one hand the backlink keyword can be used to create explicitly back link objects that manage the bidirectional relationship, on the other hand just the link keyword can be used. In the second case no back link objects are created.

The backlink keyword is used for defining a back link property. It must be followed by a reference and curly braces.

Use link when referencing a link or back link property from an object pointer property in order to establish a bidirectional relationship.

Back link properties must be directly assigned to an object class. You cannot use the back link properties in a compound type. However, an object pointer property referencing a back link property can also be part of a compound type.

In the following example, an order has an object pointer property pointing to an invoice. However, an invoice also needs to know to which order it belongs to. Therefore, a back link property is defined for pointing back to the order. The back link ensures that the integrity of the relationship between linked objects is maintained automatically. Whenever the order’s invoice object pointer property is changed, the change is reflected in the invoice.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Order : CompoundObject {
    Invoice orderinvoice {
      link = invoiceorder;
    }
  }

  class<ContentObjectClass> Invoice : ContentObject {
    backlink<Order> invoiceorder readonly;
  }
}

The following example shows the use of only the link keyword. The links ensure that the integrity of the relationship between linked objects is maintained automatically. Whenever the order’s invoice object pointer property is changed, the change is reflected in the invoice and vice versa.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Order : CompoundObject {
    Invoice orderinvoice {
      link = invoiceorder;
    }
  }

  class<ContentObjectClass> Invoice : ContentObject {
    Order invoiceorder {
      link = orderinvoice;
    }
  }
}

Defining an expression propertyPermanent link for this heading

An expression property is a string list property to hold the expression and has additional information regarding the evaluation context. Most of these additional information can be specified with additional elements in the attribute definition.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class StatusLog : BasicObject {

    expression boolean logexpr(string data, out string line) {

      scope = PARSCOPE_GLOBALSCOPEWITHOBJECT;

  }
}

This expression property describes an expression with the following behavior:

  • It operates on an object.
  • It gets a string value data in the global scope.
  • It creates a string value line in the global scope.
  • It returns true or false.

It is also possible to specify the argument list using a prototype (see chapter Defining a prototype).

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class StatusLog : BasicObject {

    expression boolean logexpr(parameters as LogPrototype) {

      scope = PARSCOPE_GLOBALSCOPEWITHOBJECT;

  }
}

Property modifier prefixesPermanent link for this heading

When defining new properties within an object class or within a compound type, you can add so-called property modifier prefixes before the property’s reference.

unique is currently the only available modifier prefix, which can be used to define that values of a list property have to be unique.

Example

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

  class Order : CompoundObject {
    unique OrderPosition[] orderpositions;
  }
}

Property modifier suffixesPermanent link for this heading

When defining new properties within an object class or within a compound type, you can add so-called property modifier suffixes (also referred to as modifiers) after the property’s reference. Modifiers allow you to change the appearance of a property as well as some other aspects pertaining to the representation of property values.

Table 5 contains a list of supported modifiers along with a brief description.

Modifier

Description

not null

The property must contain a value.

readonly

The property is not changeable in any circumstance.

readonly(ui)

The property is not changeable in the user interface.

readonly(inst)

The property is not changeable when the software component of the component object is in the “Installed” state.

volatile

The property is not cached by the Fabasoft Folio Kernel. This means that the get action or value expression is evaluated each time the property is accessed.

volatile(tx)

The property is cached in the current transaction by the Fabasoft Folio Kernel. This means that the get action or value expression is evaluated each first time the property is accessed in a transaction. This will improve performance if the calculation of the property is extensive. Please have in mind that the values stored in the transaction are transferred to the client in case of a detach operation. Therefore, values like large lists or contents will produce an additional higher overhead.

Note: You can use COOSYSTEM@1.1:ObjectRefresh() to enforce the recalculation of all properties defined with a get action or value expression. In the first parameter of COOSYSTEM@1.1:ObjectRefresh()a property list can be specified to limit the refresh to those properties.

invisible

The property is not visible in the user interface.

Table 5: Property modifier suffixes

If multiple modifiers are appended to a property, they must be separated by whitespaces.

Example

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

  enum OrderState {
    OS_PENDING = 100,
    OS_APPROVED = 101,
    OS_DISCARDED = 102,
    OS_SHIPPED = 103,
    OS_COMPLETED = 104,
    OS_ARCHIVED = 105
  }

  class Order : CompoundObject {
    datetime orderdate readonly(ui);
    OrderState orderstate readonly(ui);
    Person ordercustomer not null {
      allow {
        Person;
      }
    }
    OrderPosition[] orderpositions not null;
    integer orderpositioncount volatile readonly;
    Invoice orderinvoice readonly(ui);
    currency ordertotal readonly(ui);
  }
}