Code Type

A CodeType is a structure to represent a tree key-code association. They are used in SmartField and SmartColumn.

  • implements: ICodeType<T>

  • extends: AbstractCodeType<T>

Description

CodeTypes are e.g. used in SmartFields, ListBoxes or TreeBoxes to let the user choose between a finite list of values. The value(s) stored by the field correspond to the key(s) of the selected code.

Scout SmartField Hierarchy SWT

A CodeType can be seen as a tree of Codes. Each code associates to the key (the Id) other properties: among others a Text and an IconId.

In order to have the same resolving mechanism (getting the display text of a key), CodeTypes are also used in SmartColumns. To choose multiple values in the list, the fields ListBox (flat CodeType) and TreeBox (hierarchical CodeType) can be used.

Organisation of the codes

The codes are organized in a tree. Therefore, a CodeType can have one or more child codes at the root level, and each code can have other child codes. Often a flat list of codes (without nested codes) is sufficient to cover most of the needs.

Child codes are ordered in their parent code. This is implemented using the @Order annotation on the code class.

Type of the key

The type of the key is defined by its generic parameter <T>. It is very common to use a type from the java.lang.* package (like Long or String), but any Java Object is suitable. It must:

  • implement Serializable

  • have correctly implemented equals() and hashCode() functions

  • be present in the server and the client

There is no obligation to have the same type for the Id between the codes of a CodeType (meaning the same generic type parameter for the codes inner-class). However, it is a good practice to have the same type between the codes of a CodeType, because the Id might be used as value of e.g. a SmartField. Therefore, the generic parameter describing the type of value of a SmartField must be compatible with the type of the codes contained in the CodeType.

Using a CodeType

In Java

SmartField or SmartColumn

CodeType in a SmartField (or SmartColumn).

@ClassId("08ccc68e-7b72-4fe0-b666-245ddb8b8441")
public class YesOrNoSmartField extends AbstractSmartField<Boolean> {

  // other configuration of properties.

  @Override
  protected Class<? extends ICodeType<?, Boolean>> getConfiguredCodeType() {
    return YesOrNoCodeType.class;
  }
}

If the SmartField (or SmartColumn) works with a CodeType, a specific LookupCall is instantiated to get the LookupRows based on the Codes contained in a CodeType.

Accessing a code directly

Scout-runtime will handle the instantiation and the caching of CodeTypes.

This function returns the text corresponding to the key using a CodeType:

  public String getCodeText(boolean key) {
    ICode c = BEANS.get(YesOrNoCodeType.class).getCode(key);
    if (c != null) {
      return c.getText();
    }
    return null;
  }

In TypeScript

CodeTypes can also be used in TypeScript. Typical examples are CodeLookupCall, SmartField or SmartColumn.

Generally there are two options: either the CodeTypes and their corresponding Codes are managed directly in TypeScript (then there is no such CodeType in Java) or a Java CodeType should be made available in the TypeScript code as well.

TypeScript only

CodeTypes can be managed using the codes utility. See the following example:

import {codes} from '@eclipse-scout/core';

codes.init([{
  id: '1',
  codes: [{
    id: 'code0',
    children: [{ id: 'code01' }, { id: 'code02' }]
  }]
}]);
codes.add({
  id: '2',
  codes: [{
    id: '2.1'
  }, {
    id: '2.2'
  }]
});

// returns 3 codes (default is recursive): code0, code01 and code02
codes.get('1').codes();

codes.remove(['1', '2']);

If there is no CodeType in the JavaCode, it would of course also be possible to use other TypeScript specific structures like enums instead of Scout CodeTypes. To use CodeTypes is especially handy if they already exist in the JavaCode and the structure and values should be reused.

Reuse a Java CodeType in TypeScript

The easiest way to expose a Java CodeType to TypeScript is by adding the @ApiExposed annotation to it as shown in this example:

@ApiExposed (1)
@ObjectType("sample.ExposedCodeType") (2)
@ClassId("00ee23a3-3a63-4c9e-80b9-25f0c0bf3c85")
public class ExposedCodeType extends AbstractCodeType<String, String> { (3)
  private static final long serialVersionUID = 1L;
  public static final String ID = "10000";

  @Override
  public String getId() {
    return ID;
  }

  @Order(1000)
  @ClassId("72cb3fd6-9fe6-4659-ab9b-96086b902c27")
  public static class FirstCode extends AbstractCode<String> {
    private static final long serialVersionUID = 1L;
    public static final String ID = "1";

    @Override
    public String getId() {
      return ID;
    }
  }

  @Order(2000)
  @ClassId("5621b905-4dc0-4ffa-a764-f6372ed36768")
  public static class SecondCode extends AbstractCode<String> {
    private static final long serialVersionUID = 1L;
    public static final String ID = "2";

    @Override
    public String getId() {
      return ID;
    }
  }
}
1 Marks the CodeType to be exposed by the Scout API. Such CodeTypes may then be accessed using the REST API. For more control over the exposed CodeTypes create an implementation of IApiExposedCodeTypeContributor.
2 Specifies the TypeScript objectType for the CodeType. Only necessary if there is a dedicated TypeScript class for this CodeType.
3 The IDs must be serialized to Strings to expose them in the REST API. This works most straight forward, if String IDs are used in Java too. If this is not possible, the Ids will be converted using toString. If this is not sufficient you can implement an ICodeTypeDoIdConverter and manually convert your IDs.

On the TypeScript side you have to specify the URL to the API that exposes the marked CodeType so that they can be fetched. For this the URL to codes is added to the init config of your TypeScript App:

new App().init({
  bootstrap: {
    textsUrl: 'texts.json',
    permissionsUrl: 'api/permissions',
    codesUrl: 'api/codes'
  }
});

The url api/codes points to the CodeResource of the org.eclipse.scout.rt.api module. To make this work you need to ensure there is a dependency to that module in the pom.xml of your server module.

Because in the example above a custom objectType has been specified, a corresponding CodeType class must be created in TypeScript. This is only required if you need some custom fields or functions on your CodeType, but it is often quite handy.

import {Code, CodeType} from '@eclipse-scout/core';

export class ExposedCodeType extends CodeType<string> {
  first: Code<string>; (1)
  second: Code<string>; (1)
}
1 Optional: A field that matches the simple classname of the Java Code (lowercase first letter, no 'Code' suffix) can be added to the TypeScript CodeType. If such a field is available, the corresponding Code is automatically stored in that field. This makes accessing specific Codes easier (see examples below). If the automatic name matching should not be used the Java Code can be annotated with @FieldName to explicitly specify the name of the TypeScript field.
All attributes from the Java CodeType are automatically applied to the TypeScript CodeType. So there is no need to repeat any ID values, texts or other configuration of the Java code!

It is then possible to access the CodeType in TypeScript. Some examples:

import {codes} from '@eclipse-scout/core';
import {ExposedCodeType} from '../index';

let idOfFirstCode = codes.get(ExposedCodeType).first.id; // Access CodeType by class and Code by field. Returns '1'.
let isSecondCodeActive = codes.get('10000').get('2').active; // Access CodeType and Code by id. Returns true.
let allCodesRecursively = codes.get(ExposedCodeType).codes(); // Access all codes of a CodeType. Returns two Codes.

Static CodeType

Java Code and structure

Scout CodeType Structure

The common way to define a CodeType is to extend AbstractCodeType. Each code is an inner-class extending AbstractCode. Like usual the properties of Codes and CodeTypes can be set by overriding any of the inherited methods starting with getConfigured.

See the Java Code of a simple YesOrNoCodeType having just two codes:

  • YesOrNoCodeType.YesCode

  • YesOrNoCodeType.NoCode

Create a new CodeType with the IDE

Eclipse

Use File → New → Scout → Scout Code Type to generate a new CodeType.

IntelliJ

Right-click on a Java package (production, not test) → New → Scout Element → Code Type.

Dynamic CodeType

Code types are not necessarily hardcoded. It is possible to implement other mechanisms to load a CodeType dynamically.

The description of the Codes can e.g. come from a database or any other data source. If you want to do so, you just need to implement the method corresponding to the event LoadCodes.

It is possible to use the static and the dynamic approach together. In this case, if there is a conflict (2 codes for the same id) the event OverwriteCode is triggered.

Note for advanced users:

Each CodeType is instantiated for

  • each language

  • each partition

Note: A CodeType class is instantiated for each Locale and managed by the CodeService.