Skip to main content
Skip table of contents

Enumerations

Attribute values can be primitive (string, integer, date, ...), complex (i.e. an instance or instances of other classes e.g. Address), or enumerations which allow you to provide a list of localizable values e.g. Title = Mr., Mrs., Dr., ... that typically appear in drop-down lists.

Learning Objectives

This lesson introduces Enumerations and how to use them as attribute types in classes. By completing this module, you will learn:

  • How to use Enumerations in your models.
  • How NexJ Studio allows you to store captions to allow for translation of strings.
  • How to use an associated class that does not make use of the reverse attribute.

Key Concepts

Enumerations are a special type of Class that provide a list of values along with localizable captions. They represent lists of values with localizable captions. They are a design-time and run-time concept, meaning they are created in NexJ Studio and are part of the Model, but are also loaded into database tables for use and modification at run-time. They provide a standardized way to create lists of values, like the days of the week, and localize them or associate them with UI elements like combo boxes. They can also be associated in a parent child relationship such as country and state.

Create the training:LanguageEnum enumeration

Enumerations are created in NexJ Studio as part of the Model. However, at run time, the enumeration values are also loaded into database tables for use and modification.

In this lesson, you create an enumeration called training:LanguageEnum, that stores the names of four different languages. You then define both English and French values for the enumeration.

Users of your application may choose to work in either the English or French locale. When someone working in the French locale is asked to set a Person's preferred communication language they are presented the choice of anglais, français, espagnol, chinois, or italien. Someone working in an English locale would have the choices English, French, Spanish, Chinese, and Italian.

Create the new enumeration:

  1. In the Navigator, select Business Model/Enumerations. A list of the available enumerations is presented. As with other model elements, enumerations defined in the base model appear with grey icons. Enumerations defined in the model that you are editing appear with color icons.
  2. Right-click in the navigator and select New Enumeration.
  3. In the New Enumeration window, set the name of the new enumeration to training:LanguageEnum and click Finish.
    The Enumeration editor opens. You configure enumerations by supplying a type code, classification settings, and association properties to other enumerations.
  4. Go to the source tab and paste the following code

Paste this XML into the source tab or enter the information manually as follows

XML
<Enumeration description="Languages spoken by people." typeCode="TSLANGUAGE">
   <Locales>
      <Locale caption="Spoken language" description="Spoken language" name="en"/>
      <Locale caption="Langue parlé" description="Langue parlé" name="fr"/>
   </Locales>
   <Values>
      <Value hasBehavior="true" name="ENGLISH" value="en">
         <Locales>
            <Locale caption="English" name="en"/>
            <Locale caption="anglais" name="fr"/>
         </Locales>
      </Value>
      <Value hasBehavior="true" name="FRENCH" value="fr">
         <Locales>
            <Locale caption="French" name="en"/>
            <Locale caption="français" name="fr"/>
         </Locales>
      </Value>
      <Value hasBehavior="true" name="SPANISH" value="es">
         <Locales>
            <Locale caption="Spanish" name="en"/>
            <Locale caption="espagnol" name="fr"/>
         </Locales>
      </Value>
      <Value hasBehavior="true" name="CHINESE" value="zh">
         <Locales>
            <Locale caption="Chinese" name="en"/>
            <Locale caption="chinois" name="fr"/>
         </Locales>
      </Value>
      <Value hasBehavior="true" name="ITALIAN" value="it">
         <Locales>
            <Locale caption="Italian" name="en"/>
            <Locale caption="italien" name="fr"/>
         </Locales>
      </Value>
   </Values>
</Enumeration>

Switch back to the Overview tab and you will see something like...

If you were to enter the enumeration information by hand, you would do the following. Since we pasted the source in, this is for information and reference only.

  1. Enter the Description Languages spoken by people.
  2. Set the Type Code property to TSLANGUAGE. This uniquely identifies the enumeration and is used when persisting the enumeration and its values.
  3. Set the Classification property to system. This specifies that the enumeration values are intended for use in the business logic and not exposed in a user interface.
  4. In the Locales list, click the Add button
    to add two locales. Add locales and captions for English (en) and French (fr):
    • The first has a default Locale value of en. Set its caption to Spoken language.
    • Set the second's locale value to fr and set its caption of Langue parlé (To type the é character, hold down the ALT key and type the ASCII code 130 on the numeric keypad.)
      These values serve a similar purpose as the Caption value did for your classes, acting as a label for the enumeration.
  5. In the Values list, click the Add button

    to add the following four values to the list:

    Values to add to the training:LanguageEnum enumeration

    NameValueHas BehaviorCode UpdateableDisplay
    Updateable
    ENGLISHentruefalsetrue
    FRENCHfrtruefalsetrue
    SPANISHestruefalsetrue
    CHINESEzhtruefalsetrue
    ITALIANittruefalsetrue


    Setting Has Behavior to true allows you to write code that accesses the enumeration values directly, and base business logic on them.

  6. Select the ENGLISH row.

  7. In the Value Captions list area, click the Add button

    to add the following two captions:

    Value captions for ENGLISH

    LocaleCaption
    enEnglish
    franglais
  8. Now select each of the other values in turn, and set their captions as follows:

    Value captions for FRENCH

    LocaleCaption
    enFrench
    frfrançais (ç = ALT+135)


    Value captions for SPANISH

    LocaleCaption
    enSpanish
    frespagnol


    Value captions for CHINESE

    LocaleCaption
    enChinese
    frchinois

    Value captions for ITALIAN

    LocaleCaption
    enItalian
    fritalien
  9. Save your changes.

You have now defined two possible captions for each of the four values that this enumeration can take on. The caption that displays is based on the locale setting at run time. For example, if the value of the enumeration is set to zh (CHINESE), and my locale settings are set to English, then the caption is displayed as "Chinese". However, if I am working in a French locale, the caption is displayed as "chinois".

More about enumeration classifications

There are four behaviors that you can define for an Enumeration by setting its classification property.

system
Values are created at design time and only used in code for business logic. Values never get displayed in user interfaces.

sysDisplay
Values are not editable at run time, and are critical for business logic and system behavior. Values can be displayed to the user through user interfaces.

sysEdit
Values are critical to business function, but certain aspects can be modified at run time.

custom
Values are added at run time by users.

Using an enumeration as a complex attribute

Now that you have created the enumeration, you can use it to create a complex attribute for the training:Person class.

To add an enumeration to the training:Person class:

  1. Open the training:Person class for editing.
  2. In the Attributes tab, add a new attribute called primaryLanguage with a Type of training:LanguageEnum. Leave all the other attribute properties with their default values.
  3. Save your changes.

Review the class diagram

View the model changes that you have made by expanding the training:Entity diagram.

  1. Open the training:Fundamentals diagram. (Business Model → Diagrams)
  2. Right-click the class name of the training:Person class and select Unhide Attribute → primaryLanguage.
  3. Click the primaryLanguage attribute and drag it onto a blank area on the diagram.
  4. Rearrange the diagram so that you can see all of the elements clearly. It should now resemble the following picture:
  5. Click the Save button
    in the toolbar to save your changes.

Persistence Mapping

Enumerations are not persisted the same way as classes. Instead of having a Persistence Mapping tab, enumerations are automatically persisted in the EnumDisplay table. All you need to do in the logical persistence is add a column to the class that uses the enumeration and create a virtual index on that column.

Up until now, you have configured class persistence mapping first, then performed any further configuration in the logical data source. This time you first define the logical persistence for the new attribute, then you map the attribute.

Because the training:Person class is persisted in the Entity table, you edit the logical definition of the Entity table to persist the primaryLanguage attribute:

  1. In the Persistence layer, click the Data Sources tab.
  2. Double-click training:DB to open it and select the Entity table.
  3. In the Columns tab, add the following column:

    Column to add to the TrainingEntity table

    Column NameTypeAllocationAllow NullsPrecisionCase Insensitive
    primaryLanguagestringvaryingtrue50false
  4. In the Indexes tab, create the following index:

    Index to add to the TrainingEntity table

    NameTypeUniqueIndex Columns
    Entity.FK_LanguagevirtualfalseprimaryLanguage

    The index is virtual and does not result in the creation of any index in the database. It serves as a logical link between the values of the attribute and the EnumDisplay table that stores the values of all enumerations.

  5. Save your changes.

Update the class persistence mapping

Edit the class Persistence Mapping for the training:Person class:

  1. Open the training:Person class and select the Persistence Mapping tab.
  2. In the Attribute Mappings section, click the Select Attribute Mappings button
    and add primaryLanguage to the list.
  3. Set the Source Key, and Destination Key values for the primaryLanguage attribute as follows:

    Association attribute mapping for the Person class

    AttributeSource KeyDestination Key
    primaryLanguageEntity.FK_LanguageEnumDisplay.SK1

    EnumDisplay.SK1 is a virtual index in the valueCode column of the EnumDisplay table, in which the enumeration's possible values and captions are stored.

  4. Save your work.
    Now, when the value of the primaryLanguage is persisted for the training:Person class, a pointer to the appropriate row of the EnumDisplay table is stored in the Entity table. The values and their captions, however, are persisted in the EnumDisplay table.

Edit the upgrade file

Add a new set up upgrade steps to update the data source.

Update the upgrade file:

To update the upgrade file:

  1. In the Persistence layer on the Data Sources tab right-click the training:DB datasource and select Generate Upgrade Steps.
  2. Leave the default values for Upgrade and Current Data Source.
  3. Select Old Model as the Old Data Source. You are going to use a published model as the old model.
  4. Select Published Model JAR and then click the browse button. Select the model you published at the end of the last lesson and click Next.
  5. Whenever you upgrade a database, you must increment the version number by a whole number. For example, if the version retrieved from the published JAR file is 4.36; change the Version to 5.36.
  6. Enter the following as the Description: Added the primary language enumeration as an attribute to the Person class.
  7. Even though virtual indexes are not persisted in the database, the Upgrade Steps list contains a CreateIndex TrainingEntity.FK_Language step. This step makes no changes to the database. It is included to allow the upgrade process to know the state of the metadata as accurately as possible and improves validation and other code.

Load the training:LanguageEnums enumeration

You now need to add an upgrade step to populate the enumerations from the model into the data store. The platform automatically reloads enumerations from the model into the data source when the data source's loaded flag is set to 0. You need to set this value to 0 to cause the enumerations to be loaded.

The enumerations are in the DefaultRelationalDatabase datasource so we need to create an upgrade for that datasource.

To load the training:LanguageEnums enumeration:

  1. In the Upgrade Steps list, click 
    Load.
  2. Set the version to 7.1092.1307.167.53

  3. Click Finish to save your changes.

To complete the upgrade file modification update the model version from the Model Library to match the latest upgrade version.

Publish and upgrade

Complete the development cycle by carrying out the following activities:

  • Optionally Publish the Model
  • Upgrade the database

Test your work

When Model Server starts up, it automatically applies any system upgrades if the store's loaded flag is 0. Run the Server Console.

To test the enumerations in your model, use an existing or create a new scratchpad and test your persistence with the following code. Run it one command at a time.

CODE
; Obtain the value for the enumeration with the name ENGLISH
(training:LanguageEnum'ENGLISH)

; Obtain an instance of the training:LanguageEnum enumeration where the name is ENGLISH
(training:LanguageEnum'get'ENGLISH)

; Obtain the caption value of the ENGLISH instance of the enumeration
((training:LanguageEnum'get'ENGLISH)'caption)

; Define a new person instance with a primary language of English. Note that the primaryLanguage attribute is assigned an instance of the enumeration.
 (training:Person'new
   (: lastName "Wren")
   (: firstName "Terg")
   (: initials "L")
   (: primaryLanguage (training:LanguageEnum'get'ENGLISH))
)
(commit)

; Define p as a shorthand to the instance that you just created.
(define p (read-instance training:Person '() '(= lastName "Wren") '()))

; Obtain the value of the primary language attribute, which is the ENGLISH enumeration instance.
(p'primaryLanguage)

; Obtain the value of the caption of the p class' primary language.
((p'primaryLanguage)'caption)

; JavaScript Version...
#"training:LanguageEnum".ENGLISH
#"training:LanguageEnum".get(#"string->symbol"("ENGLISH"))
#"training:LanguageEnum".get(#"'ENGLISH")

#"training:LanguageEnum".get(#"'ENGLISH").caption
new #"training:Person"({lastName : "Wren", firstName : "Terg", initials : "L", primaryLanguage : #"training:LanguageEnum".get(#"'ENGLISH")})
commit();

var p = #"read-instance"(#"training:Person", null, scm("'(= lastName \"Wren\")"), null);

p.primaryLanguage

p.primaryLanguage.caption



To see how the captions that are returned change depending on your locale:

  1. Stop the console
  2. Change the Windows Regional Options of your system to French (France).
  3. Restart the Server Console and rerun the following commands, one at a time:

    CODE
    ; Obtain the value for the enumeration with the name ENGLISH
    (training:LanguageEnum'ENGLISH)
    
    ; Obtain an instance of the LanguageEnum enumeration, where the name is ENGLISH
    (training:LanguageEnum'get'ENGLISH)
    
    ; Obtain the caption value of the ENGLISH instance of the enumeration
    ((training:LanguageEnum'get'ENGLISH)'caption)
    
    ; Define p as a shorthand to the instance that you just created.
    (define p (read-instance training:Person '() '(= lastName "Wren") '()))
    
    ; Obtain the value of the primary language attribute, which is the ENGLISH enumeration instance.
    (p'primaryLanguage)
    
    ; Obtain the value of the caption of the p class' primary language.
    ((p'primaryLanguage)'caption)
    
    ; or in JavaScript
    #"training:LanguageEnum".ENGLISH
    #"training:LanguageEnum".get(#"string->symbol"("ENGLISH"))
    #"training:LanguageEnum".get(#"'ENGLISH")
    
    #"training:LanguageEnum".get(#"'ENGLISH").caption
    
    var p = #"read-instance"(#"training:Person", null, scm("'(= lastName \"Wren\")"), null);
    
    p.primaryLanguage
    
    p.primaryLanguage.caption
    
    
    

    Info

    When the caption is returned, you receive the French value.

  4. Stop the console and return your regional settings to English

To get an understanding of how the enumeration has been persisted in the database, query the training database with the following queries:

Microsoft SQL Server 

SQL
select * FROM NJEnumDisplay WHERE typeCode IN ('TSLANGUAGE')
select id, classCode, firstName, lastName, companyId, businessNumber,
 primaryLanguage from TRNEntity where lastName in ('Wren')


In particular notice the following features, which result from using the Class Table pattern of persistence:

  • The typeCode identified the rows of the NJEnumDisplay table that pertain to the enumerations. You can see this more clearly by removing the WHERE clause from the select statement.
  • The value stored in the primaryLanguage column of the TRNEntity table is the value of the enumeration. This is due to the persistence mapping you created that linked the Entity.FK_Language key and the EnumDisplay.SK keys.

Info

When using the scratchpad editor, on a new line type (Lang and then press Ctrl+Space. This enables Code Assist which makes writing code much easier. It allows you to inspect possible code completions, view function documentation and it provides function signatures. Code Assist is available in all Scheme editor areas within NexJ Studio.Assist which makes writing code much easier. It allows you to inspect possible code completions, view function documentation and it provides function signatures. Code Assist is available in all Scheme editor areas within NexJ Studio.









JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.