Number sequences

The vehicle table is a main table, for which we normally provide the ability to control the primary ID, VehicleId, via a number sequence. A number sequence allows the user to control how numbers are generated in terms of format and what happens if a record is deleted. This section describes how to hook into it.

All forms that are Main, Worksheet, or WorksheetHeader should use the following pattern.

Defining a number sequence

The first step is to define a number sequence that can be applied to our vehicleId field. A number sequence is associated with a particular EDT, ConFMSVehicld in our case. So, it is that EDT for which we define the number sequence, not the field.

We create a number sequence reference to the EDT in code using the number sequence framework. To create a number sequence reference, the framework requires us to write a new class that extends the NumberSeqApplicationModule class. In it, we will define a number sequence and associate it with our EDT, as follows:

  1. Create a new class. Name it ConFMSNumberSeqModuleFleetManagement.
  2. View the code for the class and change the class declaration so that it extends NumberSeqApplicationModule:
    class ConFMSNumberSeqModuleFleetManagement extends NumberSeqApplicationModule
    {
    }
  3. In the AOT, right-click on the class and override the numberSeqModule method.
  4. The numberSeqModule method must return a value from the NumberSeqModule base enum. We will return NumberSeqModule::TMS:
    public NumberSeqModule numberSeqModule()
    {
        // This tells the framework which module our
        // sequence belongs to. We always place custom
        // sequences in a standard module, as changing
        // standard enums should be avoided.
        return NumberSeqModule::TMS;
    }
  5. Next, override the loadModule method.
  6. This method is where we will set up a NumberSeqDatatype class object that defines the reference:
    protected void loadModule()
    {
        NumberSeqDatatype datatype = NumberSeqDatatype::construct();
    
        // Datatype number sequence properties for Vehicle Id
        //Associate the number sequence definition to our EDT
        datatype.parmDatatypeId( extendedTypeNum(ConFMSVehicleId) );
        //Provide help text for the number sequence
        // Remember to create a label for this
        datatype.parmReferenceHelp( literalStr("Unique key for Fleet Vehicle") );
        //Set default values for the number sequence
        //don't force unused numbers to be reused, unless we 
        //specifically need this feature
        datatype.parmWizardIsContinuous(false);
        datatype.parmWizardIsManual(NoYes::No);
        datatype.parmWizardIsChangeDownAllowed(NoYes::No);
        datatype.parmWizardIsChangeUpAllowed(NoYes::No);
        datatype.parmWizardHighest(999999);
        datatype.parmSortField(1);
        //There will be just one number sequence shared 
        // by every DataArea
        datatype.addParameterType( NumberSeqParameterType::DataArea, false, false );
        //finally create the reference
        this.create(datatype);
    }

    Note

    In this example, by returning NumberSeqModule::TMS, we have assigned our number sequence to the transport management module. This is because we want this reference to appear in the parameters form within transport management.

  7. Finally, to run the module and generate our number sequence definition, we create and run the following job:
    static void ConFMSGenerateNumberSequences(Args _args)
    {
        NumberSeqApplicationModule::loadAll();
    }

You can now generate the number sequence. Guidance for this is available at http://msdn.microsoft.com/en-us/data/hh242127.

Configuring the table to automatically apply the number sequence

We now need to instruct our forms to use the number sequence to populate the VehicleId field.

Note

It is standard practice to apply the number sequence from the form, although it is also possible to do it from the table. The framework supports the ability to assign a number on creation, which is returned to the number sequence's free list of numbers if the user cancels the creation. This is controlled by the continuous option.

First, we need a way to get a reference to the number sequence from code. We will use an existing method as a template:

  1. Find the TMSParameters table in the AOT and drag it into the Tables node of your project.
  2. Press Ctrl + N to create a new method on the TMSParameters table.
  3. Now replace the method with this:
    server static NumberSequenceReference conFMSNumRefConFMSVehicleId()
    {
        return NumberSeqReference::findReference( extendedTypeNum(ConFMSVehicleId));
    }

    Note

    It may save time if you copy an existing number sequence method of this pattern, for example, numRefTMSTransportationOrderNum. Be careful, however, as copying and pasting is a main cause of errors that are hard to debug, and sometimes, detect.

The forms will use a NumberSeqFormHandler object to get number sequence values from the framework and, if necessary, return them to the pool if they aren't used. To do this, follow these steps:

  1. Find the ConFMSVehicleTableCreate form in the AOT and view the class declaration code.
  2. After the ConFMSVehicleTableForm object we added earlier, we will add a new NumberSeqFormHandler object:
    public class FormRun extends ObjectRun
    {
        ConFMSVehicleTableForm formHandler; 
        NumberSeqFormHandler numberSeqFormHandlerVehicleId;
    }
  3. Create a new form level method called numSeqFormHandlerVehicleId(). This method will instantiate numberSeqFormHandlerVehicleId, if necessary, and then return it:
    public NumberSeqFormHandler numSeqFormHandler()
    {
        if (!numberSeqFormHandlerVehicleId )
        {
          numberSeqFormHandlerVehicleId = NumberSeqFormHandler::newForm( TMSParameters::conFMSNumRefConFMSVehicleId() .NumberSequenceId,
              element, conFMSVehicleTable_ds, fieldNum(ConFMSVehicleTable, VehicleId) );
        }
        return numberSeqFormHandlerVehicleId ;
    }

    Note

    The NumberSeqFormHandler instance is created by passing the number sequence identifier as well as the specific form and data source to apply the number sequence to.

Now that we have a NumberSeqFormHandler instance, we can use it. It has methods to call when creating a new record, validating and writing the record, and closing the form:

  1. Expand the Data Sources node and then the ConFMSVehicleTable node in the ConFMSVehicleTableCreate form.
  2. Right-click on the Methods node and override the create method, as follows:
    public void create(boolean _append = false)
    {
        //Before create - validate the number sequence
        element.numSeqFormHandlerVehicleId() .formMethodDataSourceCreatePre();
    
        super(_append);
        //After create - get next number
        element.numSeqFormHandlerVehicleId() .formMethodDataSourceCreate();
    }
  3. Next, override the validateWrite() method and use the number sequence form handler to validate that the vehicle ID conforms to the sequence definition:
    public boolean validateWrite()
    {
        boolean ret = super();
        if(ret)
        {
            // validate that the vehicle id conforms to
            // the sequence definition
            ret = element.numSeqFormHandlerVehicleId() .formMethodDataSourceValidateWrite();
        }
        return ret;
    }
  4. Now we are going to amend the write method on the data source. It was already overridden earlier, so now we simply add a new line after the call to super() but before we hand over the record to the form handler:
    void write()
    {
        // if the user didn't press OK, or the record exists,
        // don't save the record.
        if (element.closedOk() && 
            ConFMSVehicleTable.RecId == 0)
        {
            ConFMSVehicleTable.insert();
            
            //After write – call number sequence action
            element.numSeqFormHandlerVehicleId().formMethodDataSourceWrite();
            
            formHandler.parmVehicleTable(ConFMSVehicleTable);
        }
    }
  5. Finally, override the close method in the actual form:
    public void close()
    {
        super();
        //after close - number sequence, form close action.
        element.numSeqFormHandlerVehicleId().formMethodClose();
    }

Now open the ConFMSVehicleTable form and click on the New button. The create form will automatically fill in a vehicle ID from the number sequence. Save the record and create another; the next vehicle ID number will be used.

We have applied the number sequence pattern to the create process. To finish it, we must also apply it to the read, update, and delete processes. All of these are handled from the ConFMSVehicleTable form, so we must add code there as well.

To handle the update process on the ConFMSVehicleTable form, we will intercept the validateWrite, write, and close methods as we did on the create form. The form will require a numSeqFormHandlerVehicleId method of its own. The full code for this is as follows.

Here are the form-level methods:

public class FormRun extends ObjectRun
{
    ConFMSVehicleTableForm formHandler;

    NumberSeqFormHandler numberSeqFormHandlerVehicleId;
}

public NumberSeqFormHandler numSeqFormHandler()
{
    if (!numberSeqFormHandlerVehicleId )
    {
      numberSeqFormHandlerVehicleId = 
        NumberSeqFormHandler::newForm
        (
        TMSParameters::
            conFMSNumRefConFMSVehicleId().NumberSequenceId,
        element, 
        conFMSVehicleTable_ds, 
        fieldNum(ConFMSVehicleTable, VehicleId) 
        );
    }
    return numberSeqFormHandlerVehicleId;
}

The following is the code required to add to the ConFMSVehicleTable form data source:

public boolean validateWrite()
{
    boolean ret;
    ret = super();
    if(ret)
    {
        ret = element.numSeqFormHandlerVehicleId()
            .formMethodDataSourceValidateWrite();
    }
    return ret;
}

public void write()
{
    super();
    element.numSeqFormHandlerVehicleId()
        .formMethodDataSourceWrite();
}

public void close()
{
    super();
    element.numSeqFormHandlerVehicleId()
        .formMethodClose();
}

The NumberSeqFormHandler class has two more form event actions. These are formMethodDataSourceDelete() and formMethodDataSourceLinkActive().

The formMethodDataSourceDelete method is to be called before the data source delete method calls to super(). It will let the number sequence know that the current vehicle ID is no longer in use. This is important if the number sequence is set up as a continuous number sequence:

public void delete()
{
    //release the number sequence value.
    element.numSeqFormHandlerVehicleId().formMethodDataSourceDelete();
    //now delete the record
    super();
}

The formMethodDataSourceLinkActive method is to be called from within the linkActive data source method. It is called when the user changes the record on a linked data source (which could be a dynamic link to another form):

public void linkActive()
{
    super();
    element.numberSeqFormHandlerVehicleId()
        .formMethodDataSourceLinkActive();
}

The linkActive method is included to cover the case where a linked data source moves the record cursor. If this occurs and the current record cannot be saved, it will abort the number sequence generation.

More information on linkActive() is available at:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.200.14