Generating Code from the Model

5 minutes to read Download PDF Edit

Introduction

To help you to find out how you can write code to alter your model, the SDK ships with a nice reverse engineering tool. Given a fully loaded model unit, you can generate the JavaScript code that would create that very same unit using code. This way, you can build a template model in the Mendix Modeler, then generate the code you would need to write to achieve the same.

For the impatient

To generate the code for a fully-loaded unit you can use the following code:

import {utils} from "mendixmodelsdk";

console.log(utils.serializeToJs(someFullyLoadedModelUnit));

Example

Let’s say you want to generate a set of entities in a domain model that looks like this:

First you need to create the two entities in the domain model and commit that to Team Server. Next, you need to write a script like this:

/// <reference path='typings/tsd.d.ts' />
import {ModelSdkClient, IModel, IModelUnit, domainmodels, utils} from "mendixmodelsdk";
import {MendixSdkClient, Project, OnlineWorkingCopy, loadAsPromise} from "mendixplatformsdk";
import when = require("when");
const username = `{YOUR_USERNAME}`;
const apikey = `{YOUR_API_KEY}`;
const client = new MendixSdkClient(username, apikey);
// Please change your project Id and name to something you prefer.
let projectName = `{YOUR_PROJECT_NAME}`;
let projectId = `{YOUR_PROJECT_ID}`;
let moduleName = `MyFirstModule`;
let project = new Project(client, projectId, projectName);
project.createWorkingCopy()
    .then((workingCopy) => {
        const dm = workingCopy.model().allDomainModels()
            .filter(dm => dm.qualifiedName === moduleName)[0];
        return loadAsPromise(dm).then((loadedDomainModel) => {
            console.log(utils.serializeToJs(loadedDomainModel)); //print out the generated JavaScript
            return workingCopy;
        });
    })
    .done(() => {
        console.log(`success!`);
    }, (error) => {
        console.log(`error: ${error}`);
    });

When you execute the script, you will get the following output of your console. You can also pipe the output to a file if the model is more complex:

(function (domainModel1, model) {
	/*
	 * JavaScript code generated by mendixmodelsdk.sdk.extras.JavaScriptSerializer
	 * from unit with id '84776610-13b2-48cb-a265-d5e984d63129' of type DomainModels$DomainModel
	 * in working copy 'TS-585506fb-1348-4573-adb8-c778c8f2e9ad/null@null'
	 * on 23-11-2015.
	 */
	var noGeneralization1 = domainmodels.NoGeneralization.create(model);
	noGeneralization1.persistable = true;
	var stringAttributeType1 = domainmodels.StringAttributeType.create(model);
	stringAttributeType1.length = 200;
	var storedValue1 = domainmodels.StoredValue.create(model);
	var address = domainmodels.Attribute.create(model);
	address.name = "Address";
	address.type = stringAttributeType1;   // Note: for this property a default value is defined.
	address.value = storedValue1;   // Note: for this property a default value is defined.
	var stringAttributeType2 = domainmodels.StringAttributeType.create(model);
	stringAttributeType2.length = 200;
	var storedValue2 = domainmodels.StoredValue.create(model);
	var phone = domainmodels.Attribute.create(model);
	phone.name = "Phone";
	phone.type = stringAttributeType2;   // Note: for this property a default value is defined.
	phone.value = storedValue2;   // Note: for this property a default value is defined.
	var person = domainmodels.Entity.create(model);
	person.name = "Person";
	person.location = {"x":210,"y":230};
	person.generalization = noGeneralization1;   // Note: for this property a default value is defined.
	person.attributes.push(address);
	person.attributes.push(phone);
	var noGeneralization2 = domainmodels.NoGeneralization.create(model);
	noGeneralization2.persistable = true;
	var stringAttributeType3 = domainmodels.StringAttributeType.create(model);
	stringAttributeType3.length = 200;
	var storedValue3 = domainmodels.StoredValue.create(model);
	var roleName = domainmodels.Attribute.create(model);
	roleName.name = "RoleName";
	roleName.type = stringAttributeType3;   // Note: for this property a default value is defined.
	roleName.value = storedValue3;   // Note: for this property a default value is defined.
	var role = domainmodels.Entity.create(model);
	role.name = "Role";
	role.location = {"x":590,"y":230};
	role.generalization = noGeneralization2;   // Note: for this property a default value is defined.
	role.attributes.push(roleName);
	var associationDeleteBehavior1 = domainmodels.AssociationDeleteBehavior.create(model);
	var role_Member = domainmodels.Association.create(model);
	role_Member.name = "Role_Member";
	role_Member.deleteBehavior = associationDeleteBehavior1;   // Note: for this property a default value is defined.
	role_Member.parentConnection = {"x":0,"y":54};
	role_Member.childConnection = {"x":100,"y":51};
	domainModel1.entities.push(person);
	domainModel1.entities.push(role);
	domainModel1.associations.push(role_Member);
	role_Member.parent = role;
	role_Member.child = person;
})

If you want to re-create the entities of an existing domain model, you will need to alter the script a little bit. Replace the first line with:

function generate(domainModel1, model) {

The original code expects a unit as the first argument. The unit is supposed to be the container for the domain model. However, you don’t want to create a new domain model, you are going to re-use an existing domain model instead. Therefore, you need to remove this line:

var domainModel1 = domainmodels.DomainModel.createIn(unit);

Remove the last bracket on the last line so your JavaScript code will look like this:

(function (domainModel1, model) {
    /*
     * JavaScript code generated by mendixmodelsdk.sdk.extras.JavaScriptSerializer
     * from unit with id '84776610-13b2-48cb-a265-d5e984d63129' of type DomainModels$DomainModel
     * in working copy 'TS-585506fb-1348-4573-adb8-c778c8f2e9ad/null@null'
     * on 23-11-2015.
     */
    var noGeneralization1 = domainmodels.NoGeneralization.create(model);
    noGeneralization1.persistable = true;
.
.
.
.
.
.
    role_Member.parentConnection = { "x": 0, "y": 54 };
    role_Member.childConnection = { "x": 100, "y": 51 };

    domainModel1.entities.push(person);
    domainModel1.entities.push(role);
    domainModel1.associations.push(role_Member);
    role_Member.parent = role;
    role_Member.child = person;
}    

For the next step, you will create a script that make use of the function. The script is written in TypeScript, so it will be able to run a JavaScript code just fine. This script will create a blank project and modify the domain model in the ‘MyFirstModule’ module.

/// <reference path='./typings/tsd.d.ts' />

import {MendixSdkClient, Project, OnlineWorkingCopy, loadAsPromise} from 'mendixplatformsdk';
import {IModel, domainmodels, utils, projects} from 'mendixmodelsdk';
import when = require('when');
const username = `{YOUR_USERNAME}`;
const apikey = `{YOUR_API_KEY}`;
const client = new MendixSdkClient(username, apikey);

client.platform().createNewApp(`GeneratedApp3-${Date.now() }`)
    .then(project => project.createWorkingCopy())
    .then(workingCopy => {
        const dm = workingCopy.model().allDomainModels()
            .filter(dm => dm.qualifiedName === `MyFirstModule`)[0];
        return loadAsPromise(dm).then((loadedDomainModel) => {
            generate(loadedDomainModel, workingCopy.model()); //call the generated JavaScript here
            return workingCopy;
        });
    })
    .then(workingCopy => workingCopy.commit())
    .done(
    revision => console.log(`Successfully committed revision: ${revision.num() }. Done.`),
    error => {
        console.log(`error: ${error}`);
    });

//The generated code
function generate(domainModel1, model) {
.
.
.
.

Execute the script. You should have a new project with the generated entities.

Go back to your learning path for the Mendix SDK.