finos / spring-bot

Spring Boot + Java Integration for Symphony/Teams Chat Platform Bots and Apps
https://springbot.finos.org
Apache License 2.0
60 stars 35 forks source link

Entity JSON format for maps, etc. #113

Closed robmoffat closed 3 years ago

robmoffat commented 3 years ago

Bug Report

{
    "koreai": {
        "type": "org.finos.symphony.toolkit.koreai.response.koreAIResponse",
        "version": "1.0",
        "response": {  ...
        },
        "template": {
            "type": "template",
            "payload": {
                "template_type": "button",
                "text": "jjj",
                **"buttons": [
                    "java.util.arrayList",
                    [**
                        {
                            "type": "java.util.linkedHashMap",
                            "type": "postback",
                            "title": "Playbooks",
                            "payload": "playbooks"
                        },
                        {
                            "type": "java.util.linkedHashMap",
                            "type": "postback",
                            "title": "SSH Keys",
                            "payload": "ssh"
                        },
                        {
                            "type": "java.util.linkedHashMap",
                            "type": "postback",
                            "title": "Support",
                            "payload": "support"
                        }
                    ]
                ]
            }
        },
        "messageML": "<br />",
        "symphonyTemplate": "button",
        "options": []
    }
}

Check out the embedded ArrayList - it shouldn't do that.

robmoffat commented 3 years ago

As well as the above, we should use an annotation to decide which classes need to be given type and version. Something like:

@JsonDeserialize(as = RoomDef.class)
@EntityJson(version="1.0", className="a.b.c.d.room") // both class name and version are optional.  version defaults to 1.0.  
public interface Room extends Addressable {

    public String getRoomName();

    public String getRoomDescription();

    public boolean isPub();

    public String getId();
}
robmoffat commented 3 years ago

By doing this we wouldn't need code like this:

public EntityJsonConverter(Workflow wf, ObjectMapper objectMapper) {
        super(wf);
        List<Class<?>> extendedClassSpace = new ArrayList<Class<?>>();
        extendedClassSpace.add(RoomDef.class);
        extendedClassSpace.add(UserDef.class);
        extendedClassSpace.add(User.class);
        extendedClassSpace.add(Room.class);
        extendedClassSpace.add(Button.class);
        extendedClassSpace.add(ButtonList.class);
        extendedClassSpace.add(RoomList.class);
        extendedClassSpace.add(ErrorMap.class);
        extendedClassSpace.add(HeaderDetails.class);

-- from EntityJsonConverter

robmoffat commented 3 years ago

There are 2 hashtag classes: one in EntityJson, one in ChatWorkflow. They serve different purposes:

We need to remove the one from EntityJson and have just one version.

The format should follow Symphony:

  "hash789" : {
    "type" : "org.symphonyoss.taxonomy",
    "version" : "1.0",
    "id" : [ {
      "type" : "org.symphonyoss.taxonomy.hashtag",
      "version" : "1.0",
      "value" : "#production"
    } ]
  },

NB, cashtags and mentions also work the same way

amsidhlokhande commented 3 years ago

For List like List, List and List it is creating wrong format of the file file. Below is the example with json and ftl file for different Primitive type of List JSON:

{
  "workflow_001" : {
    "type" : "example.symphony.demoworkflow.expenses.person",
    "version" : "1.0",
    "stringList" : [ "StringList1", "StringList2" ],
    "integerList" : [ 10, 20, 30 ],
    "numberList" : [ 100, 200 ],
    "longList" : [ 1000, 2000 ]
  },
  "errors" : {
    "type" : "org.finos.symphony.toolkit.workflow.form.errorMap",
    "version" : "1.0",
    "contents" : { }
  },
  "buttons" : {
    "type" : "org.finos.symphony.toolkit.workflow.form.buttonList",
    "version" : "1.0",
    "contents" : [ {
      "type" : "org.finos.symphony.toolkit.workflow.form.button",
      "version" : "1.0",
      "name" : "longList.table-add-done",
      "buttonType" : "ACTION",
      "text" : "Add"
    } ]
  },
  "header" : {
    "type" : "org.finos.symphony.toolkit.workflow.form.headerDetails",
    "version" : "1.0",
    "name" : "Person Form",
    "description" : "Person Instructions",
    "tags" : [ {
      "name" : "symphony-workflow",
      "id" : "symphony-workflow",
      "tagType" : "HASH"
    }, {
      "name" : "example-symphony-demoworkflow-expenses-person",
      "id" : "example-symphony-demoworkflow-expenses-person",
      "tagType" : "HASH"
    }, {
      "name" : "org-finos-symphony-toolkit-workflow-form-buttonlist",
      "id" : "org-finos-symphony-toolkit-workflow-form-buttonlist",
      "tagType" : "HASH"
    }, {
      "name" : "example-symphony-demoworkflow",
      "id" : "example-symphony-demoworkflow",
      "tagType" : "HASH"
    }, {
      "name" : "org-finos-symphony-toolkit-workflow-form-errormap",
      "id" : "org-finos-symphony-toolkit-workflow-form-errormap",
      "tagType" : "HASH"
    } ]
  },
  "keyword1" : {
    "type" : "org.symphonyoss.taxonomy",
    "version" : "1.0",
    "id" : [ {
      "type" : "org.symphonyoss.taxonomy.hashtag",
      "version" : "1.0",
      "value" : "symphony-workflow"
    } ]
  },
  "keyword2" : {
    "type" : "org.symphonyoss.taxonomy",
    "version" : "1.0",
    "id" : [ {
      "type" : "org.symphonyoss.taxonomy.hashtag",
      "version" : "1.0",
      "value" : "example-symphony-demoworkflow-expenses-person"
    } ]
  },
  "keyword3" : {
    "type" : "org.symphonyoss.taxonomy",
    "version" : "1.0",
    "id" : [ {
      "type" : "org.symphonyoss.taxonomy.hashtag",
      "version" : "1.0",
      "value" : "org-finos-symphony-toolkit-workflow-form-buttonlist"
    } ]
  },
  "keyword4" : {
    "type" : "org.symphonyoss.taxonomy",
    "version" : "1.0",
    "id" : [ {
      "type" : "org.symphonyoss.taxonomy.hashtag",
      "version" : "1.0",
      "value" : "example-symphony-demoworkflow"
    } ]
  },
  "keyword5" : {
    "type" : "org.symphonyoss.taxonomy",
    "version" : "1.0",
    "id" : [ {
      "type" : "org.symphonyoss.taxonomy.hashtag",
      "version" : "1.0",
      "value" : "org-finos-symphony-toolkit-workflow-form-errormap"
    } ]
  },
  "formdata" : [ **"java.lang.long"**, 0 ]
}

FTL:

<messageML><card iconSrc="data:image/svg+xml,%0A%3Csvg width='28px' height='28px' fill='%23000000' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' viewBox='0 0 100 100' enable-background='new 0 0 20 20' xml:space='preserve'%3E%3Cpath d='M87.2,54.039c-0.722,0-1.406,0.148-2.038,0.397c-3.721-9.993-12.229-17.654-22.741-20.203V21.047 c1.607-0.392,2.989-1.565,3.551-3.251c0.867-2.604-0.543-5.416-3.149-6.285c-2.604-0.867-5.418,0.545-6.285,3.151 c-0.865,2.603,0.545,5.419,3.15,6.285c0.133,0.043,0.267,0.057,0.4,0.089v12.725c-1.734-0.287-3.504-0.473-5.32-0.473h-9.515 c-1.741,0-3.438,0.176-5.105,0.44V21.047c1.608-0.392,2.988-1.565,3.551-3.251c0.867-2.604-0.543-5.416-3.149-6.285 c-2.604-0.867-5.419,0.545-6.286,3.151c-0.865,2.603,0.545,5.419,3.15,6.285c0.133,0.043,0.267,0.057,0.401,0.089v13.143 c-10.614,2.495-19.213,10.194-22.96,20.257c-0.631-0.249-1.314-0.396-2.035-0.396c-3.064,0-5.548,2.483-5.548,5.547v8.946 c0,3.063,2.484,5.547,5.547,5.547v12.615H87.2V74.079c3.063,0,5.546-2.483,5.546-5.547v-8.946 C92.746,56.522,90.264,54.039,87.2,54.039z M33.577,69.465c-2.983,0-5.405-2.42-5.405-5.404c0-2.987,2.422-5.406,5.405-5.406 c2.985,0,5.405,2.419,5.405,5.406C38.982,67.045,36.562,69.465,33.577,69.465z M66.661,69.465c-2.987,0-5.406-2.42-5.406-5.404 c0-2.987,2.419-5.406,5.406-5.406c2.983,0,5.4,2.419,5.4,5.406C72.062,67.045,69.645,69.465,66.661,69.465z'%3E%3C/path%3E%3C/svg%3E" 
  accent="tempo-bg-color--blue">
  <header>${entity.header.name}

<#-- starting template -->
<form 
  id="java.lang.Long">
 <span class="tempo-text-color--red">${entity.errors.contents['entity.formdata']!''}</span>
 <text-field 
  name="entity.formdata"
  placeholder="entity.formdata">${entity.formdata!''}</text-field>
  <p><#list entity.buttons.contents as button>
    <button 
         name="${button.name}"
         type="${button.buttonType?lower_case}">
      ${button.text}
    </button>
  </#list></p>
</form>
<#-- ending template -->
  </header> 
  <body>
    <p>${entity.header.description}</p>
    <ul>
      <#list entity.header.tags as tag>
        <li><hash tag="${tag.id}" /></li>
      </#list>
    </ul>
  </body>
</card>
</messageML>

Instead of adding simply long value it is creating an array like this "formdata" : [ "java.lang.long", 0 ] It can be resolved if the presentation is like "formdata" : 0

This is mostly happing with the List of primitive of Long, Float, Double etc

robmoffat commented 3 years ago

All fixed in the workflow refactor apart from the initial commit - there is no way around the issue of the array-type, since we are expecting an array, but actually we need to know the type of the array.

However, in the above commit I've allowed deserialisation to work in EntityJson with java.util.* classes so that we can deserialise the stuff where we have @amsidhlokhande's issue, or the one mentioned in the first comment.