/ Dynamics

[X++] Find method template

When creating new tables it is best to implement a find method to make it easy to retrieve a record from foreign code.

Since we got templates in the AX Editor we can extend them with whatever we want - like a template for find methods!

xppSource

First you need to add a method to the class xppSource to implement the actual functionallity:

Source CreateFindMethod(TableName _tableName, boolean _useReplacementKey = false)
{
    DictTable   dictTable = new DictTable(tableName2id(_tableName));
    DictIndex   dictIndex = new DictIndex(tableName2id(_tableName),
                    (_useReplacementKey && dictTable.replacementKey() != 0) ? dictTable.replacementKey() : dictTable.primaryIndex());
    DictField   dictField;
    int         fieldIndex;

    if (dictIndex == null)
        throw error(strFmt('Couldn\'t find primary index for table %1', _tableName));

    // method signature returning the table
    source += strFmt('public static %1 find(', _tableName);

    // add the primary key fields as the parameters to the find method
    for (fieldIndex = 1; fieldIndex <= dictIndex.numberOfFields(); fieldIndex++)
    {
        dictField = new DictField(dictTable.id(), dictIndex.field(fieldIndex));
        source += strFmt('%1 _%2, ', extendedTypeId2name(dictField.typeId()), dictField.name());
    }
    source += strFmt('boolean _update = false)\n');

    indentLevel = 0;
    this.beginBlock();

    // Declare the table
    source += this.indent() + strFmt('%1 %1;\n', _tableName);
    source += '\n';

    // Set update yes/no
    source += this.indent() + strFmt('%1.selectForUpdate(_update);\n', _tableName);

    // select firstonly
    source += this.indent() + strFmt('select firstOnly %1\n', _tableName);
    source += this.indent() + '    where ';
    // add the primary key fields in the where clause
    for (fieldIndex=1; fieldIndex<=dictIndex.numberOfFields(); fieldIndex++)
    {
        dictField = new DictField(dictTable.id(), dictIndex.field(fieldIndex));
        if (fieldIndex == 1)
        {
        	source += strFmt('%1%2.%3 == _%3', ((fieldIndex>1) ? '&& ' : ''), _tableName, dictField.name());
        }
        else
        {
            source += '\n';
            source += this.indent() + strFmt('    %1%2.%3 == _%3', ((fieldIndex>1) ? '&& ' : ''), _tableName, dictField.name());
        }
    }
    source += ';\n';

    source += '\n';

    // return the buffer
    source += this.indent() + strFmt('return %1;\n', _tableName);

    this.endBlock();

    return source;
}
EditorScripts

Then we need to add a method to the EditorScripts to make it visible in the macro menu in the editor.
Note that the menu is built by keywords. So when we want to place it under Template->Methods and therefore we call the method template_method_find:

public void template_method_find(Editor editor)
{
    xppSource       xppSource = new xppSource();
    Source          template;
    str             path = editor.path();
    TreeNode        treeNode = path ? TreeNode::findNode(path) : null;
    TableName       tableName;
    #TreeNodeSysNodeType

    if (treeNode)
    {
        treeNode = treeNode.AOTparent();
        if (treeNode && treeNode.treeNodeType().id() == #NT_MEMBERFUNCLIST)
        {
            treeNode = treeNode.AOTparent();
            if (treeNode && treeNode.treeNodeType().id() == #NT_DBTABLE)
            {
                tableName = treeNode.treeNodeName();
            }
        }
    }

    if (!tableName)
    {
        warning('Find method applies to tables only');
        return;
    }

    template = xppSource.yavFindMethod(tableName);

    editor.insertLines(template);
}
Result

So finally you can type find and press tab or via the macro menu and the result looks like this:
Result Image

[X++] Find method template
Share this

Subscribe to robsCode