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.
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:
ConFMSNumberSeqModuleFleetManagement
.NumberSeqApplicationModule
:class ConFMSNumberSeqModuleFleetManagement extends NumberSeqApplicationModule { }
numberSeqModule
method.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; }
loadModule
method.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); }
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.
We now need to instruct our forms to use the number sequence to populate the VehicleId field.
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:
TMSParameters
table in the AOT and drag it into the Tables node of your project.TMSParameters
table.server static NumberSequenceReference conFMSNumRefConFMSVehicleId() { return NumberSeqReference::findReference( extendedTypeNum(ConFMSVehicleId)); }
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:
ConFMSVehicleTableCreate
form in the AOT and view the class declaration code.ConFMSVehicleTableForm
object we added earlier, we will add a new NumberSeqFormHandler
object:public class FormRun extends ObjectRun { ConFMSVehicleTableForm formHandler; NumberSeqFormHandler numberSeqFormHandlerVehicleId; }
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 ; }
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:
ConFMSVehicleTableCreate
form.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(); }
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; }
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); } }
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.
3.144.255.87