Push isMany attribute custom element

Hi there,

i created a custom element with the following json extension:

Summary
{
  "name": "MassDataTaskExample",
  "uri": "http://example/",
  "prefix": "mdt",
  "xml": {
    "tagAlias": "lowerCase"
  },
  "types": [
    {
        "name": "AnalyzedNode",
        "extends": [
            "bpmn:FlowNode"
        ],
        "properties": [
            {
            "name": "suitable",
            "isAttr": true,
            "type": "Integer"
            }
        ]
    },
    {
      "name": "MassDataTask",
      "superClass": [
        "bpmn:Task"
      ],
      "properties": [
        {
          "name": "key",
          "isAttr": true,
          "type": "Integer"
        }, 
        {
          "name": "keyName",
          "isAttr": true,
          "type": "String"
        },
        {
          "name": "comments",
          "isMany": true,
          "type": "Comment"
        }
      ]
    },
    {
      "name": "Comment",
      "properties": [
        {
          "name": "author",
          "isAttr": true,
          "type": "String"
        },
        {
          "name": "text",
          "isBody": true,
          "type": "String"
        }
      ]  
    }    
  ],
  "emumerations": [],
  "associations": []
}

My needs are: A new custom element, that looks differently and has more custom attributes. This element should be able to be exported and imported by my application. BPMN 2.0 compatibility is not necessary, but if there is an easy way to do this feel free to correct my approach.

I can render this custom element and add certain properties.

I am currently doing this in the following way:

const businessObject = bpmnFactory.create('mdt:MassDataTask');

      businessObject.suitable = 70;
      businessObject.key = 50;
      businessObject.keyName = "test"

This works just fine. I can export and import the xml etc. However i am unable to add a comment to comments.

The XML looks like this:

<mdt:massDataTask id="Activity_0sb0sm0" suitable="70" key="50" keyName="test" />

This is all i need. If it is possible like this i would prefer this or do i absolutly need extensionElements?

I already looked at several posts like:

And the moddle-extension example. There we use superClass ā€˜Elementā€™, is this absoluty necessary to add an isMany attribute?

I create comments like this:

let commentOne = moddle.create('mdt:Comment', {
        "author": "Klaus",
        "text": "Das ist ein Text"
});

And tried stuff like:

let massDataTaskDetails = getExtensionElement(businessObject, 'mdt:MassDataTask');
      let comment = massDataTaskDetails ? massDataTaskDetails.get("comments")[0] : null; 
      console.log("comment author: " + comment);
      console.log("comment text: " + comment);  
      massDataTask.comments.push(commentOne);

      comments.splice(1, 1);
      comments.push(commentOne);

But most of the stuff is undefined

If anyone could help me creating one or two comments and add them to my custom element i would appreciate it a lot and would gladly share my work with custom elements.

Thanks in advance!

As youā€™re in the realm of moddle I think it makes sense for you to understand how it works and which APIs it offers.

In particular, when accessing comments from an entity, you shall lazy initialize that is many relationship:

let commentable = ...
let comment = bpmnFactory.create('mdt:Comment', ...);

commentable.get('comments').push(comment);

Hope that helps.

Again thank you very much nikku. As already mentioned i am currently unable to test your suggestion.

If i get it to work i will gladly share my solution.

Thanks again :v:

1 Like

Took me a while to find the time to test it, sry for that!

Dunno if that was exactly what you suggested, however i was able to implement what i need.

If i only use the JSON file that is mentioned above i was able to set comments in the following way:

let businessObject = element.businessObject;

businessObject.keyName = "Test1Name";
businessObject.key = "16";

let comment = moddle.create('mdt:Comment');

comment.author = "Test3AuthorNeu";
comment.text = "NeuText als Body"

let comment2 = moddle.create('mdt:Comment');

comment2.author = "2terAuthor";
comment2.text = "2ter text"

let comments = [];
comments.push(comment, comment2);

businessObject.comment = comments

The result in XML is:

<mdt:massDataTask id="Activity_0fry1oc" key="17" keyName="Test2Name">
      <mdt:comment author="Test3AuthorNeu">NeuText als Body</mdt:comment>
      <mdt:comment author="2terAuthor">2ter text</mdt:comment>
</mdt:massDataTask>

This should be sufficient for our needs.

However it is also possible to create something like this:

<mdt:massDataTask id="Activity_0fry1oc">
      <bpmn2:extensionElements>
        <t1:test1 testName="Test2Name" testID="17">
          <t1:comment author="Test3AuthorNeu">NeuText als Body</t1:comment>
          <t1:comment author="2terAuthor">2ter text</t1:comment>
        </t1:test1>
      </bpmn2:extensionElements>
</mdt:massDataTask>

I should mention that with both ways you are able to import and export the xml without problems.
To my current knowledge extensionElements are only usable with ā€œsuperClassā€: [ ā€œElementā€ ] in the JSON file.
To achieve the above output i did the following:
Create a second JSON file:

{
    "name": "Test1",
    "uri": "http://Test/Test1",
    "prefix": "t1",
    "xml": {
      "tagAlias": "lowerCase"
    },
    "types": [
        {
            "name": "Test1",
            "superClass": [ "Element" ],
            "properties": [
            {
                "name": "testName",
                "isAttr": true,
                "type": "String"
            },
            {
                "name": "testID",
                "isAttr": true,
                "type": "Integer"
            },
            {
                "name": "comment",
                "isMany": true,
                "type": "Comment"
              }
            ]
        },
        {
            "name": "Comment",
            "properties": [
              {
                "name": "author",
                "isAttr": true,
                "type": "String"
              },
              {
                "name": "text",
                "isBody": true,
                "type": "String"
              }
            ]
        }   
    ],
    "emumerations": [],
    "associations": []
  }

And then set the businesslogic like this:

let test1 = getExtensionElement(businessObject, 'mdt:MassDataTask');

const extensionElements = businessObject.extensionElements || moddle.create('bpmn:ExtensionElements');

    if (!test1) {
      test1 = moddle.create('t1:Test1');

      extensionElements.get('values').push(test1);
    }

    test1.testName = "Test2Name";
    test1.testID = 17;

    let comment = moddle.create('t1:Comment');
    comment.author = "Test3AuthorNeu";
    comment.text = "NeuText als Body"

    let comment2 = moddle.create('t1:Comment');

    comment2.author = "2terAuthor";
    comment2.text = "2ter text"

    let comments = [];
    comments.push(comment, comment2);

    test1.comment = comments;

    modeling.updateProperties(element, {
      extensionElements: extensionElements,
      //suitable: suitabilityScore
    });

Because i use a complete custom element neither are BPMN 2.0 compatible. However if i were to use ā€œbpmn:Taskā€ instead of my own element, would the xml with extensionElement be compatible with BPMN2.0? It would look like this:

<bpmn:Task id="Activity_0fry1oc">
      <bpmn2:extensionElements>
        <t1:test1 testName="Test2Name" testID="17">
          <t1:comment author="Test3AuthorNeu">NeuText als Body</t1:comment>
          <t1:comment author="2terAuthor">2ter text</t1:comment>
        </t1:test1>
      </bpmn2:extensionElements>
</bpmn:Task>

And if i set the xml directly like in the first example it would not be compatible right? Would other application like camunda be able to import our xml in the extensionElement way?
Also was my examination wrong and it is indeed possible to use extensionElements without superClass: [ ā€œElementā€ ]?

Again thank you very much! Hope this helps somebody aswell