🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Bootcamp: Chapter 15 - Code Snippets
This page was created by Stephanie on 2024-03-21. Last edited by Wikiadmin on 2026-07-29.

You can use this OCL code in the Car.GetNewRegistrationNumber():String method to generate the next registration number in the ABC123 format for the Chapter 15 bootcamp exercise.

Purpose

This method reads the current registration-number counter from SysSingleton.oclSingleton, advances the counter, and returns the new value as three letters followed by a three-digit number.

For example, when the stored values represent AAA001, the method advances them and returns AAA002. The numeric part is formatted with leading zeroes, so a value of 2 is returned as 002.

Prerequisites

Complete the setup in Training:Bootcamp:Chapter 15 before adding the expression.

The method uses these Integer? attributes on SysSingleton:

Attribute Initial value in the bootcamp exercise Purpose
RegNumberLetter1Current 65 Stores the UTF-32 value for the first letter.
RegNumberLetter2Current 65 Stores the UTF-32 value for the second letter.
RegNumberLetter3Current 65 Stores the UTF-32 value for the third letter.
RegNumberNumberPartCurrent 1 Stores the numeric part of the registration number.

Set both the default value and the InitialValue to 65 for each letter attribute. Set the InitialValue of RegNumberNumberPartCurrent to 1. The value 65 is converted to A by Char.ConvertFromUtf32.

Add the method expression

  1. Create the GetNewRegistrationNumber():String method on Car, as described in Training:Bootcamp:Chapter 15.
  2. Open the method expression editor.
  3. Replace the expression with the following code.
  4. Save the model. When using MDrivenServer, upload the model so the new SysSingleton attributes are added to the database schema.
let sing=SysSingleton.oclSingleton in (
  let letter1=sing.RegNumberLetter1Current+1 in
  (
    sing.RegNumberLetter1Current:=(letter1>Char.ConvertToUtf32('Z',0))->casetruefalse(sing.RegNumberLetter2Current:=sing.RegNumberLetter2Current+1; Char.ConvertToUtf32('A',0),letter1)
  );
  let letter2=sing.RegNumberLetter2Current in
  (
    sing.RegNumberLetter2Current:=(letter2>Char.ConvertToUtf32('Z',0))->casetruefalse(sing.RegNumberLetter3Current:=sing.RegNumberLetter3Current+1; Char.ConvertToUtf32('A',0),letter2)
  );
  let letter3=sing.RegNumberLetter3Current in
  (
    sing.RegNumberLetter3Current:=(letter3>Char.ConvertToUtf32('Z',0))->casetruefalse(Char.ConvertToUtf32('A',0),letter3)
  );
  let numberpart=sing.RegNumberNumberPartCurrent+1 in
  (
    sing.RegNumberNumberPartCurrent:=(numberpart>999)->casetruefalse(0,numberpart)
  );
Char.ConvertFromUtf32(sing.RegNumberLetter1Current)+Char.ConvertFromUtf32(sing.RegNumberLetter2Current)+Char.ConvertFromUtf32(sing.RegNumberLetter3Current)+sing.RegNumberNumberPartCurrent.ToString('000')

)

How the expression works

Use one shared counter

let sing=SysSingleton.oclSingleton gets the singleton object that holds the four current counter values. Every call updates this shared state rather than storing a counter on an individual Car object.

Advance letters and roll over at Z

The expression stores letters as UTF-32 integer values. It increments the first letter first.

  • If the first letter is not past Z, it retains the incremented value.
  • If it is past Z, it resets that letter to A and increments the next letter.
  • The same rollover logic is applied from the second letter to the third letter.
  • When the third letter is past Z, it resets to A.

For example, when the letter counters reach AZZ, advancing the first letter produces BAA after the rollovers are applied.

Advance and format the numeric part

The numeric counter is incremented and reset to 0 when it becomes greater than 999.

ToString('000') formats the stored number as three digits:

Stored numeric value Formatted value
2 002
25 025
999 999

Return one result

The final expression concatenates the converted letters and formatted number, returning one String result.

The semicolon (;) separates expressions that must be evaluated in sequence. In this method, earlier expressions update the singleton counters and the final concatenation is the returned result. Do not end the expression with a semicolon: an OCL expression must return one result, and the result of a semicolon sequence is its last expression.

Important: concurrent assignment

This code maintains the shared counter, but the Chapter 15 exercise also introduces the SysAsyncTicket model pattern. Use that pattern when assignment must be serialized. Without serialization, two users assigning a number at roughly the same time can be given the same registration number. Continue with Training:Bootcamp:Chapter 15 to import and use the pattern recognized by MDrivenServer.

Test the method

  1. Run the model with persistence set to MDrivenServer, as instructed in Training:Bootcamp:Chapter 15.
  2. Evaluate the method for a Car in the debugger.
  3. Call it again and verify that the numeric portion advances, for example from AAA002 to AAA003 when using the specified initial values.
  4. Test a rollover boundary by setting a current letter value to the UTF-32 value for Z, then evaluating the method and checking that the letter resets to A and the next letter advances.

See also