Property definitions - fieldenms/tg GitHub Wiki

Property definitions

Abstract

The central concept in TG is "entity", which consists of "properties". This article discusses structural aspects of property definitions with the main emphasis on deriving the metadata, used for database interactions.

Properties are fundamental constituent parts of entities that define their structure and define the relationships between entities. Properties carry the type information and the integrity constraints. Please refer to Entities and their validation for more details about integrity constraints.

In Java terms, a property is a field declared as part of an entity (descendant of AbstractEntity) that is annotated with @IsProperty, which has a getter and a setter (explicit or implicit).

Categorisation of properties

All properties are classified according to the following essential criteria:

  1. Nature
  • Persistent - backed by a data storage, where property values can be saved to and retrieved from.

  • Transient - not backed by a data storage.

    Typically used in synthetic and action entities, but also applicable to persistent entities. Transient properties are further categorised into:

    • Calculated - usually read-only values, derived by computing the associated EQL expression.
    • CritOnly - used to provide additional search criteria, hence application is limited to Synthetic Entities.
    • Plain - all other transient properties, which can be used for intermediate state with all the benefits properties provide (e.g., integrity constraints).
  1. Type
  • Entity - entity types.
  • Collectional - represent a collection of values.
  • Primitive - types with a single component (e.g., String, Integer).
  • Component - product types with one or more distinct attributes, where identity is defined by values of those attributes (e.g. Money, Kilometer, Tonn).
  • Special – a set of special types that do not fall into any of the above categories, introduced mainly as an implementation convenience, but also convey modelling aspects (see below for more details).

More about Types

The following property types are supported by the platform.

Entity

Technically speaking, any class that extends AbstractEntity is an entity type.

However, there are different intentions of creating entity types, which lead to further categorisation.

  1. Domain Entities: entities that represent a domain concept such as a vehicle, person, etc.

    Such entities can be persistent or synthetic and their instances can exist in their own right. Action entities are also domain entities, but they cannot be property types.

    Persistent and synthetic entities are product types, and represent a domain concept or association between domain concepts.

  2. Value Entities: entities that exist strictly to be used as property types for properties of a domain entity.

    The two main representatives are: Union Entities and PropertyDescriptor.

    PropertyDescriptor is a convenient abstraction to represent meta-information about entity properties in a way that application users can benefit from.

    For example, it is possible to model a configuration entity that could be used by users to designate properties of certain entity as required, or to assign some default values upon instantiation of those entities. Such configuration entity would have a property of type PropertyDescriptor, which can be represented as an autocompleter in the UI, and users would be able to search and select properties with a drop-down list.

    Union Entities model sum types or tagged union. Their purpose is to hold a value that could take on several different, but fixed, persistent entity types. Only one of the entity types can be in use at any one time, and an active property explicitly indicates, which entity type is in use. All union entities should extend AbstractUnionEntity.

    For example, domai entity Rotable can be in several "kinds" of locations – Workshop and Vehicle. This can be modelled as union entity Location with two properties workshop: Workshop and vehicle: Vehicle, and the system would guarantee that only one of those properties could have a value, and all the usual things like EQL support, UI support, etc.

Collectional

Any type assignable to java.util.Collection and parameterised with a type listed in items 1-3 (boxing of primitive types applies).

Additionally, any type assignable to Map.

Primitive

Types that represent what is considered to be an atomic value.

  • Standard Java: Long, Integer, BigDecimal, Date, String, boolean, Class, Currency, byte[].
  • Platform: Colour, Hyperlink.

Component

Component types represent values that have internal structure, but are not entities.

A component type is composed of one or more components.

For example, type Money may be defined with 2 components:

  • amount : BigDecimal
  • currency : Currency

Component types provided by the platform are:

  • Money

  • RichText

    Rich text cannot be used as a part of an entity key as it is not designed to have identity.

Special types

The are helper types. And there are currently only 2:

  1. DynamicEntityKey – a special type to represent composite key with one or more key members.
  2. NoKey – a special type to represent property key for action-entities that do have any practical use for a key.

Collectional properties

Apart from the set of supported collection element types, the following rules apply to definitions of collectional properties:

  1. The field must be declared using the final modifier.

Accessors (getters) and setters

Entity definition must include a pair of accessor and setter methods for every declared property.

Accessors

Accessor is synonymous with getter and serves the same purpose. The naming convention permits 2 kinds of prefixes immediately followed by the capitalised name of the property:

  1. is -- intended to be used with boolean properties
  2. get -- intended to be used with all other types of properties

In most cases an accessor method should simply return the property's value as-is. However, for collectional properties an unmodifiable view should be returned to facilitate immutability. The standard Collections class provides a rich variety of methods for this purpose.

Setters

Setter (also called mutator) is a method of a single argument that updates the respective property's value. The only naming convention uses prefix set followed by the capitalised name of the property.

A setter method must be declared with public or protected visibility.

It is recommended to match the return type of a setter with the type of its declaring entity type, in order to benefit from method chaining. This can be achieved by ending a setter's body with return this.

All setter methods must be annotated with @Observable in order to enable interception.

In most cases a setter method should update its property's value in a straightforward manner -- by means of assignment. However, for collectional properties (which are final) it is required to first clear the collection and then add all elements of the argument.

@Observable
public Vehicle setParts(final List<Part> parts) {
    this.parts.clear();
    this.parts.addAll(parts);
    return this;
}

Other property attributes

Additionally, a property may admit a combination of the following characteristics:

  1. Requiredness

    Property must be assigned a value. After assignment, the value cannot be removed, only replaced.

  2. KeyMembership

    Property constitutes a part of its entity's key. Implies Requiredness.

  3. OptionalKeyMembership

    Requires KeyMembership, excludes Requiredness.

  4. Finality

    The first value that a property is persisted with remains unchanged for the whole lifetime of an entity.

  5. ...

⚠️ **GitHub.com Fallback** ⚠️