No-Code 開発プラットフォーム『Questetra BPM Suite』では、ワークフローアプリ内に Script Code (ECMAScript/JavaScript)を組み込むことも可能です。言い換えれば、コーディングスキルのある方は “複雑なデータ加工” や “外部APIとの通信” といった高度な自動化(無人化)を実現することが可能です。なお、Script Code には著作権が発生します。第三者によってパッケージ化(モジュール化)された[サービスタスク]を利用する場合、許諾条件(ライセンス)に注意が必要です。

R2300: Workflow Script Example

0. Overview

工程の自動化は、『自動工程[スクリプトタスク]へ Script Code をセット』、もしくは『独自の自動工程[サービスタスク]をプログラミング』(アドオン自動工程の実装)で実現します。プロセス(token)が自動工程([スクリプトタスク]や[サービスタスク])に到達すれば、自動的に当該スクリプトが実行されます。

// ScriptTask Code Example 0a: Hello World
engine.log( "Hello World !" );
engine.log( "Hello Server-side Automation !!" );

0-1. Script engine

実行可能な Script Code は ECMAScript (by Ecma International) に準拠した JavaScript コードです。(ECMAScript 2022: 2022-12-12時点)

Java オブジェクトへのアクセスも可能です。たとえば、ArrayList オブジェクトにデータを追加するには add() メソッド、削除するには remove() メソッド、要素数を取得するには size() メソッド、要素を取り出すには get() メソッドを使用します。

// ScriptTask Code Example 0-2a: Access to Java object
for ( let i = 0; i < filesInput.size(); i++ ){
  const strInputFileName = filesInput.get(i).getName();
  engine.log( strInputFileName );
}

/*
- java.util.ArrayList, `public int size()`
    - Returns the number of elements in this list.
- java.util.ArrayList, `public E get(int index)`
    - Returns the element at the specified position in this list.
*/
  • GraalJS:
    • engine-type: 2
    • 2020-10-12 RELEASEDBPMS v12.2
  • Nashorn:
    • engine-type: 1
    • 2018-06-11 RELEASEDBPMS v11.7
    • 2021-05-25 DEPRECATED
    • 2022-04-11 OBSOLATEBPMS v14.0
  • Rhino:
    • engine-type: 0
    • 2013-10-07 RELEASEDBPMS v9.7
    • 2020-11-13 DEPRECATED
    • 2021-07-12 OBSOLATEBPMS v13.1
workflow script task overview

0-2. Versioning

  • [スクリプトタスク] で実行されるコードは、ワークフローアプリ(プロセスモデル)のバージョンに依存します。
    • プロセストークンは、プロセス開始時のアプリバージョンで流れます。
    • そのアプリバージョンで設定されていた Script Code が実行されます。
  • [サービスタスク] で実行されるコードは、ワークフローアプリのバージョンに 依存しません
    • トークン到達時の最新の Script Code が実行されます。
    • (ダイナミックリンクライブラリの仕組みと同様)
ワークフローアプリの Version が違えば、{データ項目}も{ワークフロー図}も違う。

0-3. Type Error

JavaScript では、要求データ型への型変換が適宜暗黙的になされます(型強制)。しかしながら、Java メソッドを呼び出す際は、明示的な型変換を要するので注意が必要です。クラスにアクセスできない場合(不可逆変換を含む) TypeError が発生します。

// "java.lang.Integer" to "number"
let num = processInstance.getProcessInstanceId() -
          processInstance.getProcessInstanceSequenceNumber();
engine.log( num.toString() );  // "123444"


// "java.lang.Boolean" to "boolean"
if( processInstance.getProcessInstanceDebug() ){
  engine.log( "match if" );
}else{
  engine.log( "match else" );
}  // "match else"
engine.log( processInstance.getProcessInstanceId().toString() ); // ok
engine.log( processInstance.getProcessInstanceId() );  // TypeError

//  Cannot convert '123456'(language: Java, type: java.lang.Integer)
//  to Java type 'java.lang.String': Invalid or lossy primitive coercion.


engine.log( processInstance.getProcessInstanceDebug().toString() ); // ok
engine.log( processInstance.getProcessInstanceDebug() );  // TypeError

//  Cannot convert 'false'(language: Java, type: java.lang.Boolean)
//  to Java type 'java.lang.String': Invalid or lossy primitive coercion.

0-4. Resources

Script がアクセス可能なリソース(データやオブジェクト)は、当該プロセス(プロセスインスタンス)に関するデータ範囲に限られます。たとえば、過去のプロセス(プロセスインスタンス)で入力された業務データには、(REST API等の別ルートを経由しない限り)、アクセスできません。

  1. プロセス(プロセスインスタンス)の変数
    • [Process/プロセス] properties — by workflow engine (Script ReadOnly)
      • [Process ID/プロセスID] : p123
      • [Start Time/開始日時] : 2023-12-31 23:59
      • [End Time/終了日時] : 2024-01-01 01:23
      • [Start User/開始ユーザ] : {"uid":45, "name": "tanaka"}
      • [Start Organization/開始組織] : {"gid": "56", "name": "sales div"}
      • [Debug] : false
      • etc.
    • [Process/プロセス] values — by task operators (Script READ-WRITE)
      • [Process Title/件名] : “Shipping to Suzuki”
      • #{#q_Family_Name} : “Suzuki”
      • #{#q_Given_Name} : “Ichiro”
      • #{#q_Customer} : “SUZUKI Ichiro”
      • #{#q_Ship_Date} : “2023-01-23”
      • #{#q_Birth} : “1970-01-01”
      • #{#q_Age} : 53
      • #{#q_Attached} : [{"name": "Invoice.txt", "Content-Type": "text/plain"}]
      • #{#q_Care_Mark} : [{"dnb":"折曲厳禁"},{"dry":"水濡注意"}]
      • #{#q_Satisfaction} : [{"3":"どちらとも言えない"}]
      • etc.
  1. ワークフローアプリ(プロセスモデル)の変数
    • [Workflow App/アプリ] properties — by workflow engine (Script ReadOnly)
      • [Workflow App ID] : m2345
      • [Workflow App version] : 567
    • [Diagram/ワークフロー図] definition — by process designer (Script inaccessible)
    • [Data Item/データ項目] definitions — by process designer (Script ReadOnly)
      • [Data Type] : STRING
      • [Item Name] : “Family Name”
      • [Field Name] : “q_Family_Name”
    • [ServiceTask/サービスタスク] configuration — by process designer (Script ReadOnly)
      • [Lower Limit of Random Number] : 0
      • [Upper Limit of Random Number] : 10
  2. ワークフロー基盤の変数
    • System environment variable(Script ReadOnly)
      • “Time zone” : “GMT+09:00”
      • “Minute Offset” : 540
    • System Settings variable — set by system admin (Script ReadOnly)
      • [Usr] : {“user id”:1,”email”:”SouthPole@questetra.com”},{},,
      • [Role] : {“role id”:12,”role name”:”managers”},{},,
      • [Master] : {“example.com”: “Example Inc”},{},,
    • [Process Log], [Open Chat](Script WriteOnly)
      • engine.log( "Hello World !" );

1. Process level Methods

1-1. Access to Process Property

  1. JavaNum processInstance.getProcessInstanceId()
    • Return: [Process ID/プロセスID] of this process instance
  2. QuserView processInstance.getProcessInstanceInitQuser()
    • Return: [Process Start User/プロセス開始ユーザ]
  3. JavaNum processInstance.getProcessInstanceInitQuserId()
    • Return: ID of [Process Start User/プロセス開始ユーザ]
  4. string processInstance.getProcessInstanceInitQuserName()
    • Return: Name of [Process Start User/プロセス開始ユーザ]
  5. QgroupView processInstance.getProcessInstanceInitQgroup()
    • Return: [Process Start Organization/プロセス開始組織]
  6. JavaNum processInstance.getProcessInstanceInitQgroupId()
    • Return: ID of [Process Start Organization/プロセス開始組織]
  7. string processInstance.getProcessInstanceInitQgroupName()
    • Return: Name of [Process Start Organization/プロセス開始組織]
  8. AddableTimestamp processInstance.getProcessInstanceStartDatetime()
    • Return: [Process Start Time/プロセス開始日時]
  9. JavaNum processInstance.getProcessInstanceSequenceNumber()
    • Return: [Process Sequence/プロセス連番]
  10. boolean processInstance.getProcessInstanceDebug()
    • Return: true if this Process instance is for debug
  • string: JavaScript string (java.lang.String)
  • boolean: JavaScript boolean (java.lang.Boolean)
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • BigDecimal: java.math.BigDecimal
  • QuserView: com.questetra.bpms.core.event.scripttask.QuserView
  • QgroupView: com.questetra.bpms.core.event.scripttask.QgroupView
  • AddableTimestamp: com.questetra.bpms.util.AddableTimestamp
// ScriptTask Code Example 1-1: Get process properties
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

engine.log( processInstance.getProcessInstanceId().toString() );
  // "123456"
engine.log( processInstance.getProcessInstanceInitQuser().getEmail() );
  // "SouthPole@example.com"
engine.log( processInstance.getProcessInstanceInitQuserId().toString() );
  // "1"
engine.log( processInstance.getProcessInstanceInitQuserName() );
  // "SouthPole"
engine.log( processInstance.getProcessInstanceInitQgroup().getEmail() );
  // "all@example.com"
engine.log( processInstance.getProcessInstanceInitQgroupId().toString() );
  // "1"
engine.log( processInstance.getProcessInstanceInitQgroupName() );
  // "Org"
engine.log( processInstance.getProcessInstanceStartDatetime().toString() );
  // "2023-01-23 12:34"
engine.log( processInstance.getProcessInstanceSequenceNumber().toString() );
  // "12"
engine.log( processInstance.getProcessInstanceDebug().toString() );
  // "false"

let num = processInstance.getProcessInstanceId() -
          processInstance.getProcessInstanceSequenceNumber();
engine.log( num.toString() );  // "123444"

if( processInstance.getProcessInstanceDebug() ){
  engine.log( "match if" );
}else{
  engine.log( "match else" );
}  // "match else"

1-2. Access to Process Value

  1. string processInstance.getProcessInstanceTitle()
    • Return: [Title/件名] of this process
  2. null processInstance.setProcessInstanceTitle( stringTitle )
    • Parameter: New [Title/件名] to overwrite
  3. {Qdata} engine.findData( QdataPocket )
    • Parameter: Container definition (e.g. {number:1,type:"Numeric",,,})
  4. {Qdata} engine.findDataByVarName( stringFieldName )
    • Parameter: [Field Name/フィールド名] of this data container (QdataPocket)
  5. {Qdata} engine.findDataByName( stringItemName )
    • Parameter: [Item Name/項目名]
  6. {Qdata} engine.findDataByNumber( stringDataDefinitionNumber )
    • Parameter: Number
  7. {Qdata} engine.findDataByNumber( numberDataDefinitionNumber )
    • Parameter: Number
  8. null engine.setData( QdataPocket, {Qdata} )
    • Parameter: Data container definition
    • Parameter: New data object to overwrite
  9. null engine.setDataByVarName( stringFieldName, {Qdata} )
    • Parameter: [Field Name/フィールド名] of this data container (QdataPocket)
    • Parameter: New data
  10. null engine.setDataByName( stringItemName, {Odata} )
    • Parameter: [Item Name/項目名] of this data container (QdataPocket)
    • Parameter: New data
  11. null engine.setDataByNumber( stringDataDefinitionNumber, {Qdata} )
    • Parameter : Number of this data container (QdataPocket)
    • Parameter: New data
  12. null engine.setDataByNumber( numberDataDefinitionNumber, {Qdata} )
    • Parameter : Number of this data container (QdataPocket)
    • Parameter: New data
  • if no data is stored, returns “null” instead of {Qdata}.
  • if “null” is set as parameter, data will be deleted.
  • QdataPocket
    • Something like a container that stores data
    • The definition for each [Data Item] defined by process designer
  • {Qdata}
    • The value (data or object) stored in each QdataPocket
    • The value type depends on the definition of each [Data Item]
  • {Qdata} as Return
    • if no data, {Qdata}: null
    • if [String], {Qdata}: string (java.lang.String)
    • if [Numeric], {Qdata}: BigDecimal
    • if [Select], {Qdata}: ArrayList of ItemView
    • if [Date], {Qdata}: AddableDate
    • if [Datetime], {Qdata}: AddableTimestamp
    • if [File], {Qdata}: ArrayList of QfileView
    • if [User], {Qdata}: QuserView
    • if [Organization], {Qdata}: QgroupView
    • if [Table], {Qdata}: QtableMatrix
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
  • BigDecimal: java.math.BigDecimal
  • ArrayList: java.util.ArrayList
  • ItemView: com.questetra.bpms.core.event.scripttask.ItemView
  • AddableDate: com.questetra.bpms.util.AddableDate
  • AddableTimestamp: com.questetra.bpms.util.AddableTimestamp
  • QfileView: com.questetra.bpms.core.event.scripttask.QfileView
  • QuserView: com.questetra.bpms.core.event.scripttask.QuserView
  • QgroupView: com.questetra.bpms.core.event.scripttask.QgroupView
  • QtableMatrix: com.questetra.bpms.core.event.scripttask.ScriptListArray
// ScriptTask Code Example 1-2a: Get STRING, Set TITLE
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strCustomer = engine.findDataByVarName( "q_Family_Name" );
engine.log( strCustomer ); // "Suzuki"
let strNewTitle = "Shipping to " + strCustomer;
processInstance.setProcessInstanceTitle( strNewTitle );
  // New Title: "Shipping to Suzuki"
// ScriptTask Code Example 1-2b: Get DATE, Set DECIMAL
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

main();
function main(){
  const qdateBirth = engine.findDataByVarName( "q_Birth" );

  const dateBirth  = convertAddabledate2Jsdate( qdateBirth );
  engine.log( dateBirth.toISOString() ); 
  // case "q_Birth"="2000-04-01 (+09:00)", "2000-03-31T15:00:00.000Z"

  const dateToday  = new Date();
  const num8DigitBirth = dateBirth.getFullYear() * 10000 +
                         (dateBirth.getMonth() + 1) * 100 +
                         dateBirth.getDate();
  const num8DigitToday = dateToday.getFullYear() * 10000 +
                         (dateToday.getMonth() + 1) * 100 +
                         dateToday.getDate();
  // "2000-04-01" -> "20000401"
  const numAge = Math.floor((num8DigitToday - num8DigitBirth) /10000);

  engine.setDataByVarName( "q_Age",
                           new java.math.BigDecimal( numAge ) );
  // case "today" = "2023-02-01" on +09:00, "22"
}

function convertAddabledate2Jsdate ( AddableDate ) {
  let numMilliSec = AddableDate.getTime(); // Epoch milliseconds
  return new Date( numMilliSec );
}
// ScriptTask Code Example 1-2c: Get SELECT, Set Multiline-STRING
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

main();
function main(){
  let qcheckedNotices = engine.findDataByVarName( "q_Handle_With_Care" );
  // `java.util.ArrayList`

  if( qcheckedNotices === null ){
    throw new Error( "\n AutomatedTask Error:" +
                     " No Notices checked \n" );
  }
  engine.log( " #of Notice: " + qcheckedNotices.size() ); // " #of Notice: 2"

  let arrNotices = []; // JavaScript `Array`
  for ( let i = 0; i < qcheckedNotices.size(); i++ ){
    let strTmp = qcheckedNotices.get(i).getValue() + ": " +
                 qcheckedNotices.get(i).getDisplay();
    arrNotices.push( strTmp );
  }

  let strNotices = arrNotices?.join( '\n' ) ?? "";
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Optional_chaining

  engine.setDataByVarName( "q_Alert_Message", strNotices );
  // "frg: FRAGILE / 割れ物注意"
  // "dry: KEEP DRY / 水濡れ注意"
}

2. WorkflowApp level Methods

2-1. Access to WorkflowApp Property

  1. JavaNum processInstance.getProcessModelVersion()
    • Return: [Version/バージョン] of WorkflowApp on which the process is running
  2. JavaNum processInstance.getProcessModelInfoId()
    • Return: [App ID/アプリID] of WorkflowApp
  3. string processInstance.getProcessModelInfoName()
    • Return: [App Name/アプリ名] of WorkflowApp
  4. string processInstance.getProcessModelInfoCategory()
    • Return: [Category/カテゴリ] of WorkflowApp
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • BigDecimal: java.math.BigDecimal
// ScriptTask Code Example 2-1: Get workflow-app properties
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

engine.log( processInstance.getProcessModelVersion().toString() );
  // "123"
engine.log( processInstance.getProcessModelId().toString() );
  // "23"
engine.log( processInstance.getProcessModelInfoName() );
  // "S101: Order Fulfillment"
engine.log( processInstance.getProcessModelInfoCategory() );
  // "Sales Div"

2-2. Access to WorkflowApp DataItems (QdataPocket)

  1. ArrayList engine.findDataDefinitions()
    • (ArrayList of QdataPocket)
    • Return: List of all DataItem definitions
  2. QdataPocket engine.findDataDefinitionByVarName ( stringFieldName )
    • Return: DataItem definition (QdataPocket)
    • Parameter: [Field Name] of DataItem
  3. QdataPocket engine.findDataDefinitionByName ( stringName )
    • Return: DataItem definition (QdataPocket)
    • Parameter [Item Name] of DataItem
      • (If multiple with the same name, returns the first)
  4. QdataPocket engine.findDataDefinitionByNumber ( stringDataDefinitionNumber )
    • Return: DataItem definition (QdataPocket)
    • Parameter: Number of DataItem
  5. QdataPocket engine.findDataDefinitionByNumber ( numberDataDefinitionNumber )
    • Return: DataItem definition (QdataPocket)
    • Parameter: Number of DataItem
  • ArrayList: java.util.ArrayList
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
  • QcolumnPocket: com.questetra.bpms.core.event.scripttask.SubDataDefinitionView
  • QtableMatrix: com.questetra.bpms.core.event.scripttask.ScriptListArray
  1. string QDATAPOCKET.getVarName()
    • Return: [Field Name] of DataItem definition
  2. string QDATAPOCKET.getName()
    • Return: [Item Name] of DataItem definition
  3. JavaNum QDATAPOCKET.getNumber()
    • Return: Number of DataItem definition
  4. boolean QDATAPOCKET.matchDataType ( stringDataType )
    • Return: true, if match with DataItem definition
      • QDATAPOCKET:”String” && stringDataType:”STRING”
        • more strictly “STRING_TEXTFIELD”, “STRING_TEXTAREA”
      • QDATAPOCKET:”Numeric” && stringDataType:”DECIMAL”
      • QDATAPOCKET:”Select” && stringDataType:”SELECT”
        • more strictly “SELECT_SINGLE”, “SELECT_CHECKBOX”
      • QDATAPOCKET:”Date” && stringDataType:”DATE”
        • more strictly “DATE_YMD”, “DATE_Y”, “DATE_YM”, “DATE_MD”
      • QDATAPOCKET:”Datetime” && stringDataType:”DATETIME”
      • QDATAPOCKET:”File” && stringDataType:”FILE”
      • QDATAPOCKET:”User” && stringDataType:”QUSER”
      • QDATAPOCKET:”Organization” && stringDataType:”QGROUP”
      • QDATAPOCKET:”Table” && stringDataType:”LIST”
Only for TABLE
  1. ArrayList QDATAPOCKET.getSubDataDefinitions()
    • (ArrayList of QcolumnPocket)
    • Return: List of all column definitions
  2. QtableMatrix QDATAPOCKET.createListArray()
    • Return: Empty table object
  3. string QCOLUMNPOCKET.getVarName()
    • Return: [Field Name] of column definition
  4. string QCOLUMNPOCKET.getName()
    • Return: [Item Name] of column definition
  5. JavaNum QCOLUMNPOCKET.getNumber()
    • Return: Number of column definition
  6. boolean QCOLUMNPOCKET.matchDataType ( stringColDataType )
    • Return: true, if match with Column definition
      • QCOLUMNPOCKET:”String” && stringColDataType:”STRING”
      • QCOLUMNPOCKET:”Numeric” && stringColDataType:”DECIMAL”
      • QCOLUMNPOCKET:”Select” && stringColDataType:”SELECT”
      • QCOLUMNPOCKET:”Date” && stringColDataType:”DATE”

2-3. Access to ServiceTask Configuration

  1. string configs.get ( stringConfigName )
    • Parameter: “name” attribute of <config> element
    • if <config> form-type: “TEXTFIELD”, “TEXTAREA”, “SELECT” (editable)
      • Return: String value the process designer has entered
    • if <config> form-type: “TEXTFIELD” (el-enabled), “TEXTAREA” (el-enabled)
      • Return: String value evaluated
    • if <config> form-type: “SELECT”
      • Return: Number of DataItem (QdataPocket)
    • if <config> form-type: “SELECT_ITEM”
      • Return: “value” attribute of <item> element
    • if <config> form-type: “TOGGLE”
      • Return: String “true” or string “false”
    • if <config> form-type: “QUSER”
      • Return: String ID of User
    • if <config> form-type: “OAUTH2”
      • Return: Name of [HTTP Authorization Setting]
  2. QdataPocket configs.getObject( stringConfigName )
    • Parameter: “name” attribute of <config> element
    • if <config> form-type: “SELECT”
      • Return: Data container (QdataPocket) configured by process designer
    • if <config> form-type: “SELECT_ITEM”
      • (ItemView instead of QdataPocket)
      • Return: Option object of <item> configured by process designer
    • if <config> form-type: “TOGGLE”
      • (boolean instead of QdataPocket)
      • Return: true or false
    • if <config> form-type: “QUSER”
      • (QuserView instead of QdataPocket)
      • Return: User configured by process designer
    • else “TEXTFIELD”, “TEXTAREA”, “OAUTH2”, “SELECT” (editable entered)
      • Return: null
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
  • ItemView: com.questetra.bpms.core.event.scripttask.ItemView
  • QuserView: com.questetra.bpms.core.event.scripttask.QuserView
<?xml version="1.0" encoding="UTF-8"?><service-task-definition>

<label>Service Task Addon Example</label>
<help-page-url>https://support.questetra.com/</help-page-url>
<summary></summary>

<configs>
  <config name="SelectConfA1" form-type="SELECT" select-data-type="STRING">
    <label>A1: Select STRING DATA to Log Output</label>
  </config>
</configs>

<engine-type>2</engine-type>
<license>(C) Questetra, Inc. (MIT License)</license>
<last-modified>2023-02-01</last-modified>

<script><![CDATA[// GraalJS Script (engine type: 2)
// ServiceTask Code Example 2-3: Data Logging

main();
function main(){ 
  const strPocketFamilyName = configs.getObject( "SelectConfA1" );
  const strFamilyName       = engine.findData( strPocketFamilyName );
  engine.log( strFamilyName );
}
]]></script>

<icon>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAMSURBVBhXY1Da6AMAAhgBIOLgkG8AAAAASUVORK5CYII=</icon>

</service-task-definition>

Addon-XML Examples: https://support.questetra.com/ja/category/addons/

3. WorkflowPlatform level Methods

3-1. Access to Environment Variable

  1. string engine.getTimeZoneId()
    • Return: TimeZoneId (e.g., “GMT+09:00”)
  2. JavaNum engine.getTimeZoneOffsetInMinutes()
    • Return: Offset time in minutes (e.g., 540)

3-2. Access to System Settings

  1. QuserView — [User] info — “4-2.quserDao”
  2. QgroupView — [Organazation] info — “4-2.qgroupDao”
  3. QroleView — [Role] info — “4-2.qroleDao”
  4. ItemDao — [Master] info — “4-4.itemDao”
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QuserView: com.questetra.bpms.core.event.scripttask.QuserView
  • QgroupView: com.questetra.bpms.core.event.scripttask.QgroupView
  • QroleView: com.questetra.bpms.core.event.scripttask.QroleView
  • ItemView: com.questetra.bpms.core.event.scripttask.ItemView
// ScriptTask Code Example 3-1a: Get Timezone
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strMsg = engine.getTimeZoneId() + "\n" +
             engine.getTimeZoneOffsetInMinutes();

engine.log( strMsg );
// "GMT+09:00"
// "540"

3-3. Logging

  1. null engine.log ( stringMessage )
    • Parameter: Log output to the console
  2. OpenChatFeed feedService.begin()
    • Return: New OpenChat message (like a envelope)
  3. OpenChatFeed OPENCHATFEED.setMessage( stringMessage )
    • Return: OpenChat message
    • Parameter: A string value for the new post message
  4. OpenChatFeed OPENCHATFEED.setShareQgroup ( QgroupView_qorg )
    • Return: OpenChat message
    • Parameter: Scope of sharing (Shared Organization)
  5. OpenChatFeed OPENCHATFEED.attachFile ( QfileView_file )
    • Return: OpenChat message
    • Parameter: Attached file
  6. OpenChatFeed OPENCHATFEED.attachLink ( stringUrl )
    • Return: OpenChat message
    • Parameter: Attached URL
  7. JavaNum OPENCHATMSG.post()
    • Return: ID of the posted message
  8. JavaNum feedService.getPostingLimit()
    • Return: The maximum number of message posts

Note: A summary of the JavaScript Error object is also output to the console.

  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • OpenChatFeed: com.questetra.bpms.core.event.scripttask.FeedServiceWrapper.FeedMessageWrapper
// ScriptTask Code Example 3-3a: Post to OpenChat
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let OpenchatMsg = feedService.begin(); // Create FeedMessageWrapper
    OpenchatMsg = OpenchatMsg.setMessage( "Hello OpenChat" );
const numPost   = OpenchatMsg.post();
engine.log( " AutomatedTask OpenChat Message ID: "  + numPost );
         // " AutomatedTask OpenChat Message ID: 1902925" and posted
// engine.log( numPost ); // TypeError: java.lang.Integer to java.lang.String

4. Methods for {Qdata} (Questetra data objects)

  • 戻り値としての {Qdata} :
    • STRING [String/文字] → string
    • DECIMAL [Numeric/数値] → BigDecimal
    • QUSER [User/ユーザ] → QuserView
    • QGROUP [Organization/組織] → QgroupView
    • DATE [Date/日付] → AddableDate
    • DATETIME [Datetime/日時] → AddableTimestamp
    • SELECT [Select/選択] → ArrayList of ItemView
    • FILE [File/ファイル] → ArrayList of QfileView
    • LIST [Table/テーブル] → QtableMatrix
Questetra 格納データ object、 JavaScript で取得

4-0. Handle STRING

  • string engine.findData( QdataPocket )
  • string engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, string )
  • null engine.setDataByVarName( stringFieldName, string )

データタイプ[String/文字]に格納されている値は、java.lang.String 型の値として取得されます。ただ java.lang.String は JavaScript の文字列リテラル string と同一とみなされます。厳密等価演算子 (===) は true を返します。したがって本稿では戻り値を “string” と記載しています。なお、Java java.lang.String (Java オブジェクトからの戻り値)と、JavaScript string (JavaScriptの文字列リテラル)が区別されていた時期(Rhino 時代)があったため、その名残りで “+ ''” といった暗黙型変換が記されているコードが散見されます。

// ScriptTask Code Example 4-0: Strict equality in STRING
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strCustomer = engine.findDataByVarName( "q_Family_Name" );
engine.log( strCustomer ); // "Suzuki"
if ( strCustomer === "Suzuki" ) {
  engine.log( "Yes, Suzuki" ); // "Yes, Suzuki"
} else {
  engine.log( "No, Suzuki" );
}
engine.setDataByVarName( "q_Family_Name", "Mr. " + strCustomer );

4-1. Handle DECIMAL

  • BigDecimal engine.findData( QdataPocket )
  • BigDecimal engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, BigDecimal )
  • null engine.setDataByVarName( stringFieldName, BigDecimal )

データタイプ[Numeric/数値]のデータ項目(QdataPocket)に格納されている値は java.lang.BigDecimal 型 です。JavaScript プリミティブ型の数値(number)と、ほぼ同様に取り扱うことができます。算術演算子(Arithmetic operators)や Math メソッド(例 “Math.floor()” )でも利用可能です。(Questetra オリジナルのメソッドはありません)

  • Methods associated with data type [Numeric/数値]
    • JavaScript Number
    • JavaScript Math
    • java.lang.
    • java.lang.Math
    • java.math.BigDecimal
    • java.text.DecimalFormat
  • BigDecimal: java.math.BigDecimal
// ScriptTask Code Example 4-1a: Get DECIMAL, Set DECIMAL
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let qnumberYear = engine.findDataByVarName( "q_Year" );
let numHarf = qnumberYear / 2;

// engine.log( qnumberYear ); // TypeError: java.lang.BigDecimal to java.lang.String
// engine.log( numHarf );     // TypeError: java.lang.Double to java.lang.String

   engine.log( qnumberYear.toString() ); // "2023"
   engine.log( numHarf    .toString() ); // "1011.5"

// engine.setDataByVarName( "q_Year", numHarf ); // validation error: not java.math.BigDecimal (java.lang.Double)
   engine.setDataByVarName( "q_Year", new java.math.BigDecimal( numHarf ) );
     // "1011" stored ((depends on [Number of decimal places / 小数点以下の桁数] ))
Get DECIMAL, Use Java Formatter
// ScriptTask Code Example 4-1b: Get DECIMAL, Use Java Formatter
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let qnumYear = engine.findDataByVarName( "q_Year" );
let qnumPi   = engine.findDataByVarName( "q_Pi10digits" );

engine.log( qnumYear.toString() ); // "2023"
engine.log( qnumPi  .toString() ); // "3.1415926535"

let strMsg = "";
strMsg += "\n" + new java.text.DecimalFormat('#,###.##').format( qnumYear );
strMsg += "\n" + new java.text.DecimalFormat('#,###.##').format( qnumPi );
strMsg += "\n" + new java.text.DecimalFormat('##0.00%') .format( qnumYear );
strMsg += "\n" + new java.text.DecimalFormat('##0.00%') .format( qnumPi );
engine.log( strMsg );
/*
1,011
3.14
101100.00%
314.16%
*/

4-2. Handle QUSER QGROUP QROLE

  • QuserView engine.findData( QdataPocket )
  • QuserView engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, QuserView )
  • null engine.setDataByVarName( stringFieldName, QuserView )
  • QgroupView engine.findData( QdataPocket )
  • QgroupView engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, QgroupView )
  • null engine.setDataByVarName( stringFieldName, QgroupView )
  1. QuserView quserDao.findByEmail( stringUserEmail )
    • Return: User object (QuseView)
    • Parameter: Email address registered in the user account
  2. QuserView quserDao.findById( numberUserId )
    • Parameter: Id number registered in the user account
  3. ArrayList quserDao.findByQgroup( QgroupView_qorg )
    • (ArrayList of QuserView)
    • Return: List of all users who belong to the Organization
  4. ArrayList quserDao.findByQgroupAndPosition( QgroupView_qorg, booleanIsLeader )
    • (ArrayList of QuserView)
    • Return: List of all users who belong as Leader or Member
    • Parameter: true if as Leader
  5. ArrayList quserDao.findByQrole( QroleView_qrole )
    • (ArrayList of QuserView)
    • Return: List of all users who belong to the Role
  6. JavaNum QUSERVIEW.getId()
    • Return: ID of User
  7. string QUSERVIEW.getName()
    • Return: Name of User
  8. string QUSERVIEW.getEmail()
    • Return: Email of User
QGROUP
  1. QgroupView qgroupDao.findById( numberOrgId )
    • Return: Organization object (QgroupView)
    • Parameter: ID of Organization
  2. QgroupView qgroupDao.findByName( stringOrgName )
    • Parameter: Name of Organization
  3. QgroupView qgroupDao.findParentQgroup( QgroupView_qorg )
    • Parameter: QgroupView (Organization)
  4. QgroupView qgroupDao.findPrimaryQgroup( QuserView_quser )
    • Parameter: QuserView (User)
  5. ArrayList qgroupDao.findByQuser( QuserView_quser )
    • (ArrayList of QgroupView)
    • Return: List of all organizations which the User belongs to
  6. ArrayList qgroupDao.findByQuserAndPosition( QuserView_quser, booleanIsLeader )
    • (ArrayList of QgroupView)
    • Return: List of all organizations which the User belongs to as Leader
    • Parameter: true if as Leader
  7. JavaNum QGROUPVIEW.getId()
    • Return: ID of Organization
  8. string QGROUPVIEW.getName()
    • Return: Name of Organization
  9. string QGROUPVIEW.getEmail()
    • Return: Email of Organization
QROLE
  1. QroleView qroleDao.findById( numberId )
    • Return: Role object (Qrole)
    • Parameter: ID of Role
  2. QroleView qroleDao.findByName( stringName )
    • Return: QroleView (Role)
    • Parameter: Name of Role
  3. ArrayList qroleDao.findByQuser( QuserView_quser )
    • (ArrayList of QroleView)
    • Return: List of all Roles which the User belongs to
  4. JavaNum QROLEVIEW.getId()
    • Return: ID of Role
  5. string QROLEVIEW.getName()
    • Return: Name of Role
  • QuserView: com.questetra.bpms.core.event.scripttask.QuserView
  • QgroupView: com.questetra.bpms.core.event.scripttask.QgroupView
  • QroleView: com.questetra.bpms.core.event.scripttask.QroleView
  • ArrayList: java.util.ArrayList
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
// ScriptTask Code Example 4-2a: Refer Platform, Set QUSER
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

const numUid   = Math.ceil( Math.random() * 10 ) ; // 1 - 10
const quserWin = quserDao.findById( numUid ); // `null` or **QuserView**
const strEmail = quserWin?.getEmail() ?? "(no winners)";
engine.log( "Winner: " + strEmail );
  // e.g., "(no winners)", "Winner: Midway@questetra.com",,,
engine.setDataByVarName( "q_Worker", quserWin ); // deleted if `null`

4-3. Handle DATE and DATETIME

  • AddableDate engine.findData( QdataPocket )
  • AddableDate engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, java.sql.Date )
  • null engine.setDataByVarName( stringFieldName, java.sql.Date )
  • AddableTimestamp engine.findData( QdataPocket )
  • AddableTimestamp engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, java.sql.Timestamp )
  • null engine.setDataByVarName( stringFieldName, java.sql.Timestamp )
  1. AddableDate new com.questetra.bpms.util.AddableDate()
    • Return: Now
  2. AddableDate new com.questetra.bpms.util.AddableDate( numEpochMillisec )
    • Return: Specified date
    • Parameter: Epoch Millisec (from 1970-01-01 00:00 UTC)
  3. JavaNum ADDABLEDATE.getTime()
    • Return: Epoch Millisec (1970-01-01 00:00 UTC to ADDABLEDATE 00:00 JST)
  4. AddableDate ADDABLEDATE.addDays( numDays )
    • Return: N days in the future (or past if negative)
    • Parameter: Positive or negative integer
  5. AddableDate ADDABLEDATE.addMonths( numMonths )
    • Return: N months in the future (or past if negative)
    • Parameter: Positive or negative integer
  6. AddableDate ADDABLEDATE.getFirstDateInMonth()
    • Return: First day of the month
  7. AddableDate ADDABLEDATE.getLastDateInMonth()
    • Return: Last day of the month
  8. AddableTimestamp ADDABLEDATE.getFirstTimeInDate()
    • Return: 00:00 of the day
  9. string ADDABLEDATE.toString()
    • Return (DATE_YMD): e.g. 2023-03-31
    • Return (DATE_YM): e.g. 2023-03
    • Return (DATE_Y): e.g. 2023
    • Return (DATE_MD): e.g. 03-31
DATETIME
  1. AddableTimestamp new com.questetra.bpms.util.AddableTimestamp()
    • Return: Now
  2. AddableTimestamp new com.questetra.bpms.util.AddableTimestamp( numEpochMillisec )
    • Return: Specified date
    • Parameter: Epoch Millisec (from 1970-01-01 00:00 UTC)
  3. JavaNum ADDABLETIMESTAMP.getTime()
    • Return: e.g. 1970-01-01 00:00 UTC to ADDABLETIMESTAMP JST
  4. AddableTimestamp ADDABLETIMESTAMP.addMinutes( numMinutes )
    • Return: N minutes in the future (or past if negative)
    • Parameter: Positive or negative integer
  5. AddableTimestamp ADDABLETIMESTAMP.addHours( numHours )
    • Return: N hours in the future (or past if negative)
    • Parameter: Positive or negative integer
  6. AddableTimestamp ADDABLETIMESTAMP.addDays( numDays )
    • Return: N days in the future (or past if negative)
    • Parameter: Positive or negative integer
  7. AddableTimestamp ADDABLETIMESTAMP.addMonths( numMonths )
    • Return: N months in the future (or past if negative)
    • Parameter: Positive or negative integer
  8. AddableTimestamp ADDABLETIMESTAMP.getFirstTimeInDate()
    • Return: 00:00 of the day
  9. AddableTimestamp ADDABLETIMESTAMP.getFirstTimeInMonth()
    • Return: 00:00 of the first day of the month
  10. AddableTimestamp ADDABLETIMESTAMP.getLastTimeInMonth()
    • Return: 23:59 of the last day of the month
  11. string ADDABLETIMESTAMP.toString()
    • Return: Local time (eg, “2023-03-31 14:59“)
DateFormatter
  1. string dateFormatter.format( stringTimeZoneId, stringFormat, AddableDate_d )
  2. string dateFormatter.format( stringTimeZoneId, stringFormat, AddableTimestamp_t )
    • Return: Formatted datetime string
    • Parameter: Time zone id
    • Parameter: Date and Time Pattern
    • Parameter: ADDABLETIMESTAMP (date time)
  3. string dateFormatter.format( stringFormat, AddableTimestamp_t )
    • Return: Formatted datetime string
    • Parameter: Date and Time Pattern
    • Parameter: ADDABLETIMESTAMP (date time)
  4. AddableTimestamp dateFormatter.parse( stringParser, stringTime )
    • Return: ADDABLETIMESTAMP (date time)
    • Parameter: Date and Time Pattern
    • Parameter: Formatted datetime string
  • JavaScript Date
  • java.util.Locale
  • java.util.Date
  • java.sql.Date
  • java.sql.Timestamp
  • java.text.SimpleDateFormat
  • AddableDate: com.questetra.bpms.util.AddableDate
  • AddableTimestamp: com.questetra.bpms.util.AddableTimestamp
  • DateFormatter: com.questetra.bpms.core.event.scripttask.DateFormatWrapper
  • ArrayList: java.util.ArrayList
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
// ScriptTask Code Example 4-3a: Get/Set DATE, Get/Set TIME
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

// on JST (GMT+9) platform
let qDate1 = engine.findDataByVarName( "q_date_ymd" ); // as '2023-03-31'
let qDate2 = engine.findDataByVarName( "q_date_ym" );  // as '2023-03'
let qDate3 = engine.findDataByVarName( "q_date_y" );   // as '2023'
let qDate4 = engine.findDataByVarName( "q_date_md" );  // as '03-31'
let qTime1 = engine.findDataByVarName( "q_datetime" ); // '2023-03-31 00:01'
let qTime2 = qTime1.addMonths( -1 );
let qTime3 = qTime1.addMonths( -1 ).getLastTimeInMonth();

engine.log( qDate1.getTime().toString() );
engine.log( qDate2.getTime().toString() );
engine.log( qDate3.getTime().toString() );
engine.log( qDate4.getTime().toString() );
engine.log( qTime1.getTime().toString() );
engine.log( qTime2.getTime().toString() );
engine.log( qTime3.getTime().toString() );

/*
"1680188400000" (2023-03-31T00:00:00.000+09:00)
"1677596400000" (2023-03-01T00:00:00.000+09:00)
"1672498800000" (2023-01-01T00:00:00.000+09:00)
"954428400000"  (2000-03-01T00:00:00.000+09:00)
"1680188460000" (2023-03-31T00:01:00.000+09:00)
"1677510060000" (2023-02-28T00:01:00.000+09:00)
"1677596399999" (2023-02-28T23:59:59.999+09:00)
*/

engine.setDataByVarName( "q_datetime", qTime3 );    // as '2023-02-28 23:59'
// engine.setDataByVarName( "q_Ship_Date", qTime3 );// Type Error
engine.setDataByVarName( "q_date_ymd", new java.sql.Date( qTime3.getTime()) );
                                                    // as '2023-02-28'
Create DATE, Set DATE
// ScriptTask Code Example 4-3b: Create DATE, Set DATE
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let jsdateNow = new Date();
// let jsdateNow = new Date( 2023, 2, 31, 0, 1, 23, 456 );
let qdateNow  = new com.questetra.bpms.util.AddableDate();
let qtimeNow  = new com.questetra.bpms.util.AddableTimestamp();

engine.log( jsdateNow.getTime().toString() );
            // "1680188483456" (2023-03-31T00:01:23.456+09:00)
engine.log( qdateNow .getTime().toString() );
            // "1680188400000" (2023-03-31T00:00:00.000+09:00)
engine.log( qtimeNow .getTime().toString() );
            // "1680188483458" (2023-03-31T00:01:23.458+09:00)

engine.log( jsdateNow.toString() );
                               // "Fri Mar 31 2023 00:01:23 GMT+0900 (GMT+9)"
engine.log( qdateNow .toString() ); // "2023-03-31"
engine.log( qtimeNow .toString() ); // "2023-03-31 00:01"

engine.setDataByVarName( "q_date_ymd",
       new java.sql.Date( jsdateNow.getTime()) ); // as '2023-03-31'
engine.setDataByVarName( "q_date_ym",
       new java.sql.Date( jsdateNow.getTime()) ); // as '2023-03'
engine.setDataByVarName( "q_date_y",
       new java.sql.Date( jsdateNow.getTime()) ); // as '2023'
engine.setDataByVarName( "q_date_md",
       new java.sql.Date( jsdateNow.getTime()) ); // as '03-31'
engine.setDataByVarName( "q_datetime",
  new java.sql.Timestamp( jsdateNow.getTime()) ); // as '2023-03-31 00:01'
Parse DATETIME
// ScriptTask Code Example 4-3c: Parse DATETIME
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

main();
function main(){

// HEADER DATE: (email "Date", http "Last-Modified", etc)
let strHeaderTime1 = "Sat, 01 Apr 2023 02:34:56 +0900 (JST)";
let strHeaderTime2 = "Sat, 1 Apr 2023 02:34:56 +0900 (JST)";
let strHeaderTime3 = "Fri, 31 Mar 2023 17:34:56 +0000 (UTC)";
let strHeaderTime4 = "Fri, 31 Mar 2023 17:34:56 GMT";
let strHeaderTime5 = "Fri, 31 Mar 2023 09:34:56 -0800 (PST)";

// JSON DATE:
let strJsonTime6 = "2023-04-01T02:34:56+09:00";
let strJsonTime7 = "2023-03-31T17:34:56Z";
let strJsonTime8 = "2023-03-31T09:34:56-08:00";

//// Parse on JST (GMT+9) platform
// 1. Parsing with JavaScript constructor
  // NOTE: If not ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ) 
  //  Parsing of strings with `Date(str)` is strongly discouraged
let jsTime11 = new Date( strHeaderTime1 );
let jsTime12 = new Date( strHeaderTime2 );
let jsTime13 = new Date( strHeaderTime3 );
let jsTime14 = new Date( strHeaderTime4 );
let jsTime15 = new Date( strHeaderTime5 );
let jsTime16 = new Date( strJsonTime6 );
let jsTime17 = new Date( strJsonTime7 );
let jsTime18 = new Date( strJsonTime8 );
engine.log( jsTime11.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime12.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime13.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime14.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime15.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime16.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime17.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( jsTime18.toISOString() ); // "2023-03-31T17:34:56.000Z"
engine.log( " --- " );

// 2. Parsing with JavaScript function
let jsTime26 = parseYmdhsAsLocal( strJsonTime6 );
engine.log( jsTime26.toISOString() ); // "2023-03-31T17:34:00.000Z"
engine.log( " --- " );

// 3. Parsing with Java
let strParser1 = "yyyy-MM-dd'T'HH:mm:ssXXX";
  // https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html
  // https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/text/SimpleDateFormat.html
let strFormatter = strParser1;
let addableT316 = dateFormatter.parse( strParser1, strJsonTime6 );
let addableT317 = dateFormatter.parse( strParser1, strJsonTime7 );
let addableT318 = dateFormatter.parse( strParser1, strJsonTime8 );
engine.log( dateFormatter.format( strFormatter, addableT316 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, addableT317 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, addableT318 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( " --- " );

let localeEn    = new java.util.Locale("en");
let javaParser2 = new java.text.SimpleDateFormat(
                  "EEE, d MMM yyyy HH:mm:ss XX (z)", localeEn );
let jdate321    = javaParser2.parse( strHeaderTime1 );
let jdate322    = javaParser2.parse( strHeaderTime2 );
let jdate323    = javaParser2.parse( strHeaderTime3 );
//let jdate324    = javaParser2.parse( strHeaderTime4 ); // Unparseable
let jdate325    = javaParser2.parse( strHeaderTime5 );
engine.log( dateFormatter.format( strFormatter, jdate321 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, jdate322 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, jdate323 ) ); // "2023-04-01T02:34:56+09:00"
//engine.log( dateFormatter.format( strFormatter, jdate324 ) );
engine.log( dateFormatter.format( strFormatter, jdate325 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( " --- " );

let javaParser3 = new java.text.SimpleDateFormat(
                  "EEE, dd MMM yyyy HH:mm:ss zzz", localeEn );
let jdate331    = javaParser3.parse( strHeaderTime1 );
let jdate332    = javaParser3.parse( strHeaderTime2 );
let jdate333    = javaParser3.parse( strHeaderTime3 );
let jdate334    = javaParser3.parse( strHeaderTime4 );
let jdate335    = javaParser3.parse( strHeaderTime5 );
engine.log( dateFormatter.format( strFormatter, jdate331 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, jdate332 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, jdate333 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, jdate334 ) ); // "2023-04-01T02:34:56+09:00"
engine.log( dateFormatter.format( strFormatter, jdate335 ) ); // "2023-04-01T02:34:56+09:00"
} // end of "main()"

function parseYmdhsAsLocal ( strDate ){ // for "jsTime26"
  const arrNumParts = strDate.match( /\d+/g );
  let numYear       = parseInt( arrNumParts[0], 10 );
  let indexMonth    = parseInt( arrNumParts[1], 10 ) - 1;
  let numDay        = parseInt( arrNumParts[2], 10 );
  let numHours      = parseInt( (arrNumParts?.[3] ?? "0"), 10 );
  let numMinutes    = parseInt( (arrNumParts?.[4] ?? "0"), 10 );
  return new Date( numYear, indexMonth, numDay, numHours, numMinutes );
}

4-4. Handle SELECT

  • ArrayList engine.findData( QdataPocket )
    • (ArrayList of ItemView)
  • ArrayList engine.findDataByVarName( stringFieldName )
    • (ArrayList of ItemView)
  • null engine.setData( QdataPocket, ArrayList<stringIds> )
  • null engine.setDataByVarName( stringFieldName, ArrayList<stringIds> )

各プロセスに格納されている[Select/選択]型データは、 ArrayList 型として取得されます。単一選択 SELECT_SINGLE 方式の場合、その最大サイズは1となります。(≒1つの選択肢しか格納できません)。 複数選択 SELECT_CHECKBOX 方式の場合、選択されている選択肢オブジェクト ItemView が全て格納されています。 — SELECT_SINGLE: “size() == 1” or null, SELECT_CHECKBOX: “size() >= 1” or null.

engine.findData() 等により ItemView のリストを取得します。しかし更新時は string のリストにて行います( setData() 等による)。また、ワークフロー基盤に格納されているマスターデータは、itemDao.findByValue() もしくは itemDao.findAll() メソッドにて参照します。

  1. ItemView itemDao.findByValue( stringFileName, booleanIsShared, stringId )
    • Return: One option (ItemView) extracted from [Master file/選択肢マスタ]
    • Parameter: The registered name as [Master file/選択肢マスタ]
    • Parameter: true if as shared
    • Parameter: ID of the option
  2. ArrayList itemDao.findAll( stringFileName, booleanIsShared )
    • (ArrayList of ItemView)
    • Return: List of all options in [Master file/選択肢マスタ]
    • Parameter: The registered name as [Master file/選択肢マスタ]
    • Parameter: true if as shared
  3. string ITEMVIEW.getValue()
    • Return: ID of the option
  4. string ITEMVIEW.getDisplay()
    • Return: Label of the option
  • ItemView: com.questetra.bpms.core.event.scripttask.ItemView
  • ArrayList: java.util.ArrayList
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
// ScriptTask Code Example 4-4a: Get SELECT, Set SELECT
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let radioSelected = engine.findDataByVarName( "q_Opinion" );
  // ArrayList "size() == 1" or `null`

if ( radioSelected === null ){
  let radioOverwrite = new java.util.ArrayList();
      radioOverwrite.add( "3" ); // ≪3,Neutral / どちらとも言えない≫
  engine.setDataByVarName( "q_Opinion", radioOverwrite );
  engine.log ( "Radio box, Overwritten. (ID=3)" );
} else {
  engine.log ( radioSelected.get(0).getValue() );   // "2"
  engine.log ( radioSelected.get(0).getDisplay() ); // "Agree / そう思う"
}
// ScriptTask Code Example 4-4b: Get SELECT, Set SELECT
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strId    = engine.findDataByVarName( "q_Opinion" )?.get(0).getValue() ?? "n/a";
let strLabel = engine.findDataByVarName( "q_Opinion" )?.get(0).getDisplay() ?? "";
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Optional_chaining
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing

if ( strId === "n/a" ){
  let radioOverwrite = new java.util.ArrayList();
      radioOverwrite.add( "3" ); // ≪3,Neutral / どちらとも言えない≫
  engine.setDataByVarName( "q_Opinion", radioOverwrite );
  engine.log ( "Radio box, Overwritten. (ID=3)" );
} else {
  engine.log ( strId );    // "2"
  engine.log ( strLabel ); // "Agree / そう思う"
}
Get Checkbox SELECT
// ScriptTask Code Example 4-4c: Get Checkbox SELECT
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let checkboxSelected = engine.findDataByVarName( "q_Care" );
let arrKeyValue = [];

if ( checkboxSelected === null ){
  engine.log ( "No Checkbox selected" );
} else {
  for ( let i = 0; i < checkboxSelected.size(); i++ ) {
    arrKeyValue.push (
      '"' + checkboxSelected.get(i).getValue() +   '": ' +
      '"' + checkboxSelected.get(i).getDisplay() + '"'
    );
  }
  engine.log ( arrKeyValue.join( ',\n' ) );
}
/*
"frg": "FRAGILE / 割れ物注意",
"dnb": "DO NOT BEND / 折曲厳禁",
"dry": "KEEP DRY / 水濡れ注意"
*/
Get MASTER Directly
// ScriptTask Code Example 4-4d: Get MASTER directly
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let optionSpecified = itemDao.findByValue(
                        "country-codes-iso-3166-1-2013-alpha2-en.xml",
                        true,
                        "US"
                      )
engine.log ( "ID:    " + optionSpecified.getValue() );
engine.log ( "LABEL: " + optionSpecified.getDisplay() );
/*
ID:    US
LABEL: United States
*/

4-5. Handle FILE

  • ArrayList engine.findData( QdataPocket )
    • (ArrayList of QfileView)
  • ArrayList engine.findDataByVarName( stringFieldName )
    • (ArrayList of QfileView)
  • null engine.setData( QdataPocket, ArrayList )
  • null engine.setDataByVarName( stringFieldName, ArrayList )
  1. string QFILEVIEW.getName()
    • Return: Name of the file
  2. JavaNum QFILEVIEW.getLength()
    • Return: Size of the file
  3. string QFILEVIEW.getContentType()
    • Return: Content-Type of the file (e.g. “text/plain; charset=Shift_JIS”, “text/html” )
  4. string fileRepository.readFile ( QfileView, stringEncoding )
    • Return: String of the file (up to 1MB)
    • Parameter: Text File object
    • Parameter: Character encoding (e.g. “UTF-8”, “Shift_JIS” or “UTF-16” )
  5. null fileRepository.readFile ( QfileView, stringEncoding, function )
    • Parameter: Text File object
    • Parameter: Character encoding
    • Parameter: function be invoked after each line has been loaded. The argument is “stringLoadedLine”.
  6. ByteArray fileRepository.readFile ( QfileView )
    • Return: Byte array of the file (up to 1MB)
    • Parameter: Binary File object
  7. null fileRepository.readFile ( QfileView, numBytes, function )
    • Parameter: Binary File object
    • Parameter: Size of byte stream to load
    • Parameter: function be invoked after the specified bytes have been loaded. The argument is the loaded binary.
  8. BigDecimal BYTEARRAY.getLength()
    • Return: Length of the byte array
  9. NewQfile new com.questetra.bpms.core.event.scripttask.NewQfile ( stringFileName, stringContentType, stringText )
    • Return: Text file
  10. NewQfile new com.questetra.bpms.core.event.scripttask.NewQfile ( stringFileName, stringContentType, stringCharset, stringText )
    • Return: Text file
  11. NewQfile new com.questetra.bpms.core.event.scripttask.NewQfile ( stringFileName, stringContentType, ByteArray )
    • Return: Binary file
  12. NewQfile new com.questetra.bpms.core.event.scripttask.NewQfile ( stringFileName, stringContentType, QfileView )
    • Return: Duplicated file
  13. string NEWQFILE.getName()
    • Return: Name of the file
  14. string NEWQFILE.getLength()
    • Return: Size of the file
  15. string NEWQFILE.getContentType()
    • Return: Content-Type of the file (e.g. “text/plain; charset=Shift_JIS”, “text/html” )
Encode Decode
  1. string hex.encodeToString ( ByteArray )
    • Return: Hexadecimal values (e.g. “0101 1110” to “5E” )
    • Parameter: Binary data
  2. string base64.encodeToString ( ByteArray )
    • Return: Base64-encoded string (e.g. “010000 010100” to “QU”)
    • Parameter: Binary data
  3. string base64.encodeToString ( stringOriginal )
    • Return: Base64-encoded string
    • Parameter: Original string
  4. string base64.encodeToUrlSafeString ( stringOriginal )
    • Return: Base64-encoded string (URL and Filename Safe)
    • Parameter: Original string
  5. string base64.decodeFromString ( stringEncoded )
    • Return: Original string
    • Parameter: Base64-encoded string
  6. string base64.decodeFromUrlSafeString ( stringEncoded )
    • Return: Original string
    • Parameter: Base64-encoded string (URL and Filename Safe)
  7. ByteArray base64.decodeFromUrlSafeStringToByteArray ( stringEncoded )
    • Return: Original data
    • Parameter: Base64-encoded string
Digest Hash
  • ByteArray digest.md5 ( ByteArray )
  • ByteArray digest.md5 ( QfileView )
    • Return: MD5 hash value
    • Parameter: File object
  • ByteArray digest.sha1 ( ByteArray )
  • ByteArray digest.sha1 ( QfileView )
    • Return: SHA1 hash value
    • Parameter: File object
  • ByteArray digest.sha256 ( ByteArray )
  • ByteArray digest.sha256 ( QfileView )
    • Return: SHA256 hash value
    • Parameter: File object
  • ByteArray digest.sha384 ( ByteArray )
  • ByteArray digest.sha384 ( QfileView )
    • Return: SHA384 hash value
    • Parameter: File object
  • ByteArray digest.sha512 ( ByteArray )
  • ByteArray digest.sha512 ( QfileView )
    • Return: SHA512 hash value
    • Parameter: File object
  • NewQfile: com.questetra.bpms.core.event.scripttask.NewQfile
  • QfileView: com.questetra.bpms.core.event.scripttask.QfileView
  • ByteArray: com.questetra.bpms.core.event.scripttask.ByteArrayWrapper
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
// ScriptTask Code Example 4-5a: Get FILE
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

main();

function main() {
  let filesForInvoice = engine.findDataByVarName( "q_Attached_Files" );
  if( filesForInvoice === null) {
    throw new Error( "\n AutomatedTask RuntimeError:" +
                     " Files not attached \n" );
  }

  let strTitleList = "";
  for ( let i = 0; i < filesForInvoice.size(); i++ ) {
    strTitleList += filesForInvoice.get(i).getContentType();
    strTitleList += ": ";
    strTitleList += filesForInvoice.get(i).getName();
    strTitleList += " (";
    strTitleList += addThousandsSeparators (
                      filesForInvoice.get(i).getLength() );
    strTitleList += " byte) --- MD5: ";
    strTitleList += hex.encodeToString (
                      digest.md5( filesForInvoice.get(i) ) );
    strTitleList += "\n";
  }
  engine.log ( strTitleList );

/*
application/pdf: invoice001.pdf (41,896 byte) --- MD5: f77381a6ece4da84e15f999bcac389e1
text/csv: invoice001-sjis.csv (2,576 byte) --- MD5: 67d4467d149b9ea6940b729b01c4c600
image/jpeg: productA01.jpg (40,406 byte) --- MD5: 4dc051f8a57e12775bb4cf06cb389775
*/
}

function addThousandsSeparators ( num ) {
  return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
    // - Replace all "{number}" with "{number},".
    // - But only if immediately followed by the pattern `(\d{3})+(?!\d)`
    //   - `(\d{3})`: three numeric characters
    //   - `(?!\d)`: non-numeric character
    // https://support.questetra.com/ja/addons/string-batch-add-thousands-separators-2022/
}
// ScriptTask Code Example 4-5b: Append Text FILE
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let filesFavorites = engine.findDataByVarName( "q_Attached_Files" ) ??
       new java.util.ArrayList(); // if 'null', create empty ArrayList
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing

let strText = 
`吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。
I am a cat. As yet I have no name. I've no idea where I was born.`;

let fileAppend = new com.questetra.bpms.core.event.scripttask.NewQfile (
                   "i-am-a-cat.txt",
                   "text/plain",
                   strText
                 );

filesFavorites.add( fileAppend );
engine.log ( " Added file: " + fileAppend.getName() );

engine.setDataByVarName( "q_Attached_Files", filesFavorites );
engine.log ( " Total #of files: " + filesFavorites.size() );
/*
 Added file: i-am-a-cat.txt
 Total #of files: 4
*/

4-6. Handle LIST (Table)

  • QtableMatrix engine.findData( QdataPocket )
  • QtableMatrix engine.findDataByVarName( stringFieldName )
  • null engine.setData( QdataPocket, QtableMatrix )
  • null engine.setDataByVarName( stringFieldName, QtableMatrix )
  1. QtableMatrix QDATAPOCKET.createListArray() — “2-2-10.QdataPocket”
    • Return: Empty table object
  2. string QTABLEMATRIX.get ( numRowIndex, numColIndex )
  3. string QTABLEROW.get ( stringFieldName )
    • Return: Cell data as string
      • STRING [String/文字] → e.g. “as entered by users”
      • DECIMAL [Numeric/数値] → e.g. “1234.56”
      • SELECT [Select/選択] → e.g. “id001”
      • DATE [Date/日付] → e.g. “2023-03-31”
  4. ArrayList QTABLEROW.getCols()
    • (ArrayList of string)
  5. {Qcelldata} QTABLEMATRIX.getObject ( numRowIndex, numColIndex )
  6. {Qcelldata} QTABLEMATRIX.getObject ( numRowIndex, stringFieldName )
  7. {Qcelldata} QTABLEROW.getObject ( numColIndex )
  8. {Qcelldata} QTABLEROW.getObject ( stringFieldName )
    • Return: Cell data as object
      • STRING [String/文字] → string
      • DECIMAL [Numeric/数値] → BigDecimal
      • SELECT [Select/選択] → ItemView
      • DATE [Date/日付] → AddableDate
  9. QtableRow QTABLEMATRIX.getRow ( numRowIndex )
    • Return: Specified row
  10. ArrayList QTABLEMATRIX.getRows()
    • (ArrayList of QtableRow)
    • Return: All rows
  11. JavaNum QTABLEMATRIX.size()
    • Return: Number of rows
  12. JavaNum QTABLEROW.size()
    • Return: Number of cells
  13. QtableRow QTABLEMATRIX.addRow()
    • Appends empty row
  14. QtableRow QTABLEMATRIX.removeRow ( numRowIndex )
    • Return: Deleted row
    • Parameter: Row to delete
  15. string QTABLEROW.put ( stringFirldName, stringNewData )
    • Return: Original string (replaced by new data)
    • Parameter: New data to overwrite the specified cell
      • STRING [String/文字] → e.g. “as entered by users”
      • DECIMAL [Numeric/数値] → e.g. “1234.56”
      • SELECT [Select/選択] → e.g. “id001”
      • DATE [Date/日付] → e.g. “2023-03-31”
  16. QtableRow QTABLEMATRIX.getSummary()
    • Return: Summary row
  17. string QTABLEMATRIX.toXmlString()
    • Return: Table string in XML
    • e.g. “<list><row><col>01</col><col>1234.56</col></row><summary><col></col><col></col></summary></list>
  • ItemView: com.questetra.bpms.core.event.scripttask.ItemView
  • ArrayList: java.util.ArrayList
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
  • QtableMatrix: com.questetra.bpms.core.event.scripttask.ScriptListArray
  • QtableRow: com.questetra.bpms.core.event.scripttask.ScriptListArray.ScriptListRow
// ScriptTask Code Example 4-6a: Get/Edit/Set TABLE
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

// q_Invoice_Table
// SELECT       STRING        DATE       DECIMAL     DECIMAL    DECIMAL(sum)
// q_CategoryId q_Description q_ShipDate q_UnitPrice q_Quantity q_Amount
//                  // q_Amount(calc): q_UnitPrice * q_Quantity
// q_CategoryId:
//   01,Simple Paper Fan UCHIWA
//   02,Foldable Paper Fan SENSU

let matrixInvoice = engine.findDataByVarName( "q_Invoice_Table" ) ??
      engine.findDataDefinitionByVarName( "q_Invoice_Table" ).createListArray();


/// Case Empty
if ( Number (matrixInvoice.size()) === 0 ) {
  engine.log ( matrixInvoice.toXmlString() ); // "<list><summary/></list>"
  throw new Error( "\n AutomatedTask RuntimeError:" +
                   " Table Data is empty \n" );
}


/// Retrieve Process instance
engine.log ( "Table -- #row:" + matrixInvoice.size() + 
                " x #column:" + matrixInvoice.getRow(0).size()  );
          // "Table -- #row:2 x #column:6"
engine.log ( matrixInvoice.getObject( 0, "q_CategoryId" ).getDisplay() );
          // "Simple Paper Fan UCHIWA"
engine.log ( matrixInvoice.toXmlString() );
/* (Line breaks added for readability)
<list>
<row><col>01</col><col>Cherry Blossom SAKURA</col><col>2023-02-28</col>
     <col>59.99</col><col>3</col><col>179.97</col></row>
<row><col>02</col><col>Bellflower KIKYO</col><col>2023-02-28</col>
     <col>69.99</col><col>2</col><col>139.98</col></row>
<summary><col></col><col></col><col></col><col></col><col></col><col>319.95</col></summary>
</list>
*/


/// Overwrite
let rowFirstline   = matrixInvoice.getRow(0);
let strOverwritten = rowFirstline.put ( "q_Description", "Blue Lotus HASU" );
engine.log ( strOverwritten ); // "Cherry Blossom SAKURA"
engine.log ( matrixInvoice.toXmlString() );
/* (Line breaks added for readability)
<list>
<row><col>01</col><col>Blue Lotus HASU</col><col>2023-02-28</col>
     <col>59.99</col><col>3</col><col>179.97</col></row>
<row><col>02</col><col>Bellflower KIKYO</col><col>2023-02-28</col>
     <col>69.99</col><col>2</col><col>139.98</col></row>
<summary><col></col><col></col><col></col><col></col><col></col><col>319.95</col></summary>
</list>
*/


/// Append new line
let rowAppend = matrixInvoice.addRow();
rowAppend.put ( "q_Description", "Keychain (free gift)" );
rowAppend.put ( "q_UnitPrice", "0.00" );
rowAppend.put ( "q_Quantity", "1" );
engine.log ( matrixInvoice.toXmlString() );
/* (Line breaks added for readability)
<list>
<row><col>01</col><col>Blue Lotus HASU</col><col>2023-02-28</col>
     <col>59.99</col><col>3</col><col>179.97</col></row>
<row><col>02</col><col>Bellflower KIKYO</col><col>2023-02-28</col>
     <col>69.99</col><col>2</col><col>139.98</col></row>
<row><col></col><col>Keychain (free gift)</col><col></col>
     <col>0.00</col><col>1</col><col></col></row>
<summary><col></col><col></col><col></col><col></col><col></col><col>319.95</col></summary></list>
*/


/// Remove line
let rowRemoved   = matrixInvoice.removeRow(1);
engine.log ( matrixInvoice.toXmlString() );
/* (Line breaks added for readability)
<list>
<row><col>01</col><col>Blue Lotus HASU</col><col>2023-02-28</col>
     <col>59.99</col><col>3</col><col>179.97</col></row>
<row><col></col><col>Keychain (free gift)</col><col></col>
     <col>0.00</col><col>1</col><col></col></row>
<summary><col></col><col></col><col></col><col></col><col></col><col>319.95</col></summary></list>
*/


/// Update Process instance
engine.setDataByVarName( "q_Invoice_Table", matrixInvoice );
/*
"Simple Paper Fan UCHIWA"  "Blue Lotus HASU"  "2023-02-28"  "59.99"  "3"  "$179.97USD"
                        "Keychain (free gift)"               "0.00"  "1"  "$0.00USD"
                                                                          "$179.97USD"
*/

5. Other Supported Methods

5-1. Send Email

  1. EmailMessage emailService.begin()
    • Return: New message
  2. JavaNum emailService.getSendingLimit()
    • Return: Max number of times to send per process (“10” as of 202301)
  3. EmailMessage EMAILMESSAGE.addTo ( stringAddress, stringFullName )
    • Return: Message which address to “To:” header is appended
  4. EmailMessage EMAILMESSAGE.addCc ( stringAddress, stringFullName )
  5. EmailMessage EMAILMESSAGE.addBcc ( stringAddress, stringFullName )
  6. EmailMessage EMAILMESSAGE.setFrom ( stringAddress, stringFullName )
  7. EmailMessage EMAILMESSAGE.setReplyTo ( stringAddress, stringFullName )
  8. EmailMessage EMAILMESSAGE.setSubject ( stringSubject )
  9. EmailMessage EMAILMESSAGE.setBody ( stringBody )
    • Return: Message which plain text is set as Email Body (same “setTextBody()“)
  10. EmailMessage EMAILMESSAGE.setTextBody ( stringBody )
    • Return: Message which plain text is set as Email Body
  11. EmailMessage EMAILMESSAGE.setHtmlBody ( stringHtml )
    • Return: Message which html text is set as Email Body
  12. EmailMessage EMAILMESSAGE.addAttachment ( QfileView )
    • Return: Message which file attached (up to 5MB)
  13. EmailMessage EMAILMESSAGE.addAttachment ( stringFileName, stringContentType, stringText )
    • Return: Message which file attached with encoding
  14. null EMAILMESSAGE.send()
    • (Send Email)
  • EmailMessage: com.questetra.bpms.core.event.scripttask.EmailServiceWrapper.EmailMessageWrapper
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QfileView: com.questetra.bpms.core.event.scripttask.QfileView
// ScriptTask Code Example 5-1a: Get Email-Limit
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let numLimit = emailService.getSendingLimit();
engine.log ( numLimit.toString() ); // "10"
// ScriptTask Code Example 5-1b: Test Sending Email
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let EmailMsg = emailService.begin();
    EmailMsg = EmailMsg.addTo ( "example@example.com", "test" );
    EmailMsg = EmailMsg.setFrom ( "no-reply@example.com", "No-Reply" );
    EmailMsg = EmailMsg.setSubject ( "Test subject" );
    EmailMsg = EmailMsg.send(); // "ERROR: Body is missing"
// ScriptTask Code Example 5-1c: Test Sending Email
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let EmailMsg = emailService.begin()
                 .addTo      ( "example@example.com", "test" )
                 .setFrom    ( "no-reply@example.com", "No-Reply" )
                 .setSubject ( "Test2 subject" )
                 .setBody    ( "Hello email, from Questetra" )
                 .send();

5-2. Send HttpRequest

  1. HttpRequest httpClient.begin()
    • Return: New request
  2. JavaNum httpClient.getRequestingLimit()
    • Return: Max number of times to send per process (“10” as of 202301)
  3. string httpClient.getOAuth2Token ( stringAuthSettingName )
    • Return: AccessToken by referring to [HTTP Authorization Setting]
      • Case “OAuth2”, “{AccessToken}”
      • Case “TokenFixed”, “{enteredToken}”
  4. HttpRequest HTTPREQUEST.authSetting ( stringAuthSettingName )
    • Return: Request in which “Authorization:” header is set by referring to [HTTP Authorization Setting]
      • Case “OAuth2”, “Authorization: Bearer {AccessToken}”
      • Case “TokenFixed”, “Authorization: Bearer {enteredToken}”
      • Case “Basic Auth”, “Authorization: Basic {encodedUsernamePasswd}”
  5. HttpRequest HTTPREQUEST.googleOAuth2 ( QuserView, stringServiceName )
    • Return: Request in which “Authorization:” header is set by referring to [Google Connectivity]
  6. HttpRequest HTTPREQUEST.bearer ( stringToken )
  7. HttpRequest HTTPREQUEST.header ( stringName, stringValue )
  8. HttpRequest HTTPREQUEST.queryParam ( stringName, stringValue )
    • Return: Request which URL-encoded Parameter is appended
  9. HttpRequest HTTPREQUEST.body ( QfileView )
  10. HttpRequest HTTPREQUEST.body ( QfileView, stringContentType )
  11. HttpRequest HTTPREQUEST.body ( stringText, stringContentType )
  12. HttpRequest HTTPREQUEST.body ( ByteArray, stringContentType )
  13. HttpRequest HTTPREQUEST.formParam ( stringName, stringValue )
  14. HttpRequest HTTPREQUEST.multipart ( stringName, stringValue )
  15. HttpRequest HTTPREQUEST.multipart ( stringName, QfileView )
  16. HttpRequest HTTPREQUEST.multipart ( stringName, stringText, stringContentType, stringFileName )
  17. HttpResponse HTTPREQUEST.get ( stringUrl )
  18. HttpResponse HTTPREQUEST.post ( stringUrl )
  19. HttpResponse HTTPREQUEST.patch ( stringUrl )
  20. HttpResponse HTTPREQUEST.put ( stringUrl )
  21. HttpResponse HTTPREQUEST.delete ( stringUrl )
  22. JavaNum HTTPRESPONSE.getStatusCode()
  23. ByteArray HTTPRESPONSE.getResponse()
  24. string HTTPRESPONSE.getResponseAsString()
  25. string HTTPRESPONSE.getContentType()
  26. string HTTPRESPONSE.getCharset()
  27. ArrayList HTTPRESPONSE.getHeaderNames()
    • (ArrayList of string)
  28. ArrayList HTTPRESPONSE.getHeaderValues ( stringHeaderName )
    • (ArrayList of string)
  • HttpRequest: com.questetra.bpms.core.event.scripttask.HttpClientWrapper.HttpRequestWrapper
  • HttpResponse: com.questetra.bpms.core.event.scripttask.HttpClientWrapper.HttpResponseWrapper
  • ArrayList: java.util.ArrayList
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • ByteArray: com.questetra.bpms.core.event.scripttask.ByteArrayWrapper
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
// ScriptTask Code Example 5-2a: Send HttpRequest
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

/// prepare request1
let dateTime = new Date( 2023, 0, 1, 0, 0, 0 ); // month: 0 start
let getUri1  = "https://api.openweathermap.org/data/2.5/onecall/timemachine";
let request1 = httpClient.begin(); // HttpRequestWrapper
    request1 = request1.queryParam( "appid", "e16cdxxxxxa76b5yyyyy22ba3zzzzz20" ); 
    request1 = request1.queryParam( "lat", "43.0631985" ); 
    request1 = request1.queryParam( "lon", "141.3238222" ); // Sapporo
    request1 = request1.queryParam( "dt", ( dateTime.getTime() /1000 + "" ) );
    request1 = request1.queryParam( "units", "metric" ); 
    request1 = request1.queryParam( "lang", "ja" ); 

/// try request1
const response1     = request1.get( getUri1 ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + getUri1 );
const response1Code = response1.getStatusCode() + "";
const response1Body = response1.getResponseAsString() + "";
engine.log( " AutomatedTask ApiResponse1 Status: " + response1Code );
if( response1Code !== "200"){
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response1Code + "\n" + response1Body + "\n" );
}

/// parse response1
engine.log( response1Body );
/*
{"lat":43.0632,"lon":141.3238,"timezone":"Asia/Tokyo","timezone_offset":32400, ..
*/
// https://support.questetra.com/ja/addons/openweather-weather-history-get-by-time/

5-3. Manipulate String

  1. string escaper.escapeEcmaScript ( stringEcma )
    • Return: Escaped string
    • Parameter: ECMA string
  2. string escaper.escapeJson ( stringJson )
    • Return: Escaped string
    • Parameter: JSON string
  3. string escaper.escapeHtml ( stringHtml )
    • Return: Escaped string
    • Parameter: HTML string
  4. string escaper.escapeXml ( stringXml )
    • Return: Escaped string
    • Parameter: XML string
  5. string joiner.splitJoin ( stringLines, stringJoiner )
  6. string joiner.splitJoin ( stringLines, stringPrefix, stringSuffix )
  7. string joiner.splitJoin ( stringLines, stringPrefix, stringSuffix, stringJoiner )
    • Return: Joined string
    • Parameter: Multiline string
    • Parameter: e.g. “<br>“, “,”
  8. string joiner.join ( collections, stringJoiner, function )
  9. string joiner.join ( collections, stringPrefix, stringSuffix, function )
  10. string joiner.join ( collections, stringPrefix, stringSuffix, stringJoiner, function )
    • Return: Joined string
    • Parameter: collections data (e.g. Array, Map, Set, ArrayList,,,)
  • java.util.HashMap
  • java.util.regex.Pattern
  • java.util.regex.Matcher
// ScriptTask Code Example 5-3a: Escape STRING
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strOriginal = "Hold R&D share to <10%.";
engine.log ( escaper.escapeHtml ( strOriginal ) );
// "Hold R&D share to <10%."
// ScriptTask Code Example 5-3b: Join STRINGS
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strMultiline = 
`line-1
line-2
line-3`;
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Template_literals

engine.log ( joiner.splitJoin ( strMultiline, "<br>" ) );
// "line-1<br>line-2<br>line-3"

5-4. Manipulate XML

  1. XmlNode xpath.findNode ( XmlNode, stringXpath )
  2. XmlNode xpath.findNode ( stringXml, stringXpath )
  3. XmlNodeList xpath.findNodeList ( XmlNode, stringXpath )
  4. XmlNodeList xpath.findNodeList ( stringXml, stringXpath )
  5. string xpath.findNodeText ( XmlNode, stringXpath )
  6. string xpath.findNodeText ( stringXml, stringXpath )
  7. string XMLNODE.getNodeName()
  8. string XMLNODE.getNodeValue()
  9. JavaNum XMLNODE.getNodeType()
  10. XmlNode XMLNODE.getParentNode()
  11. XmlNodeList XMLNODE.getChildNodes()
  12. XmlNode XMLNODE.getFirstChild()
  13. XmlNode XMLNODE.getLastChild()
  14. XmlNode XMLNODE.getPreviousSibling()
  15. XmlNode XMLNODE.getNextSibling()
  16. boolean XMLNODE.hasChildNodes()
  17. string XMLNODE.getNamespaceURI()
  18. string XMLNODE.getPrefix()
  19. string XMLNODE.getLocalName()
  20. boolean XMLNODE.hasAttributes()
  21. string XMLNODE.getBaseURI()
  22. string XMLNODE.getTextContent()
  23. JavaNum XMLNODELIST.getLength()
  24. XmlNode XMLNODELIST.item( numNth )
  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
  • XmlNode: com.questetra.bpms.core.event.scripttask.XPathWrapper.NodeWrapper
  • XmlNodeList: com.questetra.bpms.core.event.scripttask.XPathWrapper.NodeListWrapper
// ScriptTask Code Example 5-4a: Parse XML
  // output by Questetra BPM Suite v14.2.2 (GraalJS)

let strRss =
`<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>My Blog</title>
    <link>https://www.example.com/blog</link>
    <description>A blog about technology, science, and culture.</description>
    <language>en-us</language>
    <lastBuildDate>Wed, 23 Feb 2023 20:00:00 GMT</lastBuildDate>
    <item>
      <title>How to Build a Chatbot</title>
      <link>https://www.example.com/blog/chatbot</link>
      <description>Learn how to build a chatbot with Python and TensorFlow.</description>
      <pubDate>Tue, 21 Feb 2023 12:00:00 GMT</pubDate>
    </item>
    <item>
      <title>The Science of Sleep</title>
      <link>https://www.example.com/blog/sleep</link>
      <description>Discover the latest research on sleep and its impact on health.</description>
      <pubDate>Mon, 20 Feb 2023 10:00:00 GMT</pubDate>
    </item>
    <item>
      <title>The Art of Storytelling</title>
      <link>https://www.example.com/blog/storytelling</link>
      <description>Explore the techniques and strategies behind great storytelling.</description>
      <pubDate>Sat, 18 Feb 2023 15:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>`; // powered by ChatGPT

engine.log ( xpath.findNodeText ( strRss, "/rss/channel/item/title" ) );
  // "How to Build a Chatbot"

/// get 1st Node only
let xnodeT = xpath.findNode ( strRss, "/rss/channel/item/title" );
engine.log ( xnodeT                   + "" ); // "[object Object]"
engine.log ( xnodeT.getNodeName()     + "" ); // "title"
engine.log ( xnodeT.getNodeValue()    + "" ); // "null"
engine.log ( xnodeT.getNodeType()     + "" ); // "1"
engine.log ( xnodeT.hasChildNodes()   + "" ); // "true" ↓★
engine.log ( xnodeT.getNamespaceURI() + "" ); // "null"
engine.log ( xnodeT.getPrefix()       + "" ); // "null"
engine.log ( xnodeT.getLocalName()    + "" ); // "title"
engine.log ( xnodeT.hasAttributes()   + "" ); // "false"
engine.log ( xnodeT.getBaseURI()      + "" ); // "null"
engine.log ( xnodeT.getTextContent()  + "" ); // "How to Build a Chatbot"
engine.log ( xnodeT.getFirstChild().hasChildNodes() + "" ); // "false" ★
engine.log ( xnodeT.getFirstChild().getNodeName()   + "" ); // "#text"
engine.log ( xnodeT.getFirstChild().getNodeValue()  + "" ); // "How to Build a Chatbot"
engine.log ( xnodeT.getFirstChild().getNodeType()   + "" ); // "3"

// https://docs.oracle.com/en/java/javase/11/docs/api/constant-values.html#org.w3c.dom.Node.ATTRIBUTE_NODE
// https://docs.oracle.com/javase/jp/11/docs/api/constant-values.html#org.w3c.dom.Node.ATTRIBUTE_NODE
// - ELEMENT_NODE: 1
// - ATTRIBUTE_NODE: 2
// - TEXT_NODE: 3
// - CDATA_SECTION_NODE: 4
// ...

6. appendix

6-1. Data types used in this reference

  • JavaNum: java.lang.Integer, java.lang.Long, java.lang.Double,,,
  • BigDecimal: java.math.BigDecimal
  • ArrayList: java.util.ArrayList
  • QdataPocket: com.questetra.bpms.core.event.scripttask.ProcessDataDefinitionView
  • QcolumnPocket: com.questetra.bpms.core.event.scripttask.SubDataDefinitionView
  • {Qdata}: (super class)
  • OpenChatFeed: com.questetra.bpms.core.event.scripttask.FeedServiceWrapper.FeedMessageWrapper
  • QuserView: com.questetra.bpms.core.event.scripttask.QuserView
  • QgroupView: com.questetra.bpms.core.event.scripttask.QgroupView
  • QroleView: com.questetra.bpms.core.event.scripttask.QroleView
  • AddableDate: com.questetra.bpms.util.AddableDate
  • AddableTimestamp: com.questetra.bpms.util.AddableTimestamp
  • DateFormatter: com.questetra.bpms.core.event.scripttask.DateFormatWrapper
  • ItemView: com.questetra.bpms.core.event.scripttask.ItemView
  • QfileView: com.questetra.bpms.core.event.scripttask.QfileView
  • NewQfile: com.questetra.bpms.core.event.scripttask.NewQfile
  • ByteArray: com.questetra.bpms.core.event.scripttask.ByteArrayWrapper
  • QtableMatrix: com.questetra.bpms.core.event.scripttask.ScriptListArray
  • QtableRow: com.questetra.bpms.core.event.scripttask.ScriptListArray.ScriptListRow
  • EmailMessage: com.questetra.bpms.core.event.scripttask.EmailServiceWrapper.EmailMessageWrapper
  • HttpRequest: com.questetra.bpms.core.event.scripttask.HttpClientWrapper.HttpRequestWrapper
  • HttpResponse: com.questetra.bpms.core.event.scripttask.HttpClientWrapper.HttpResponseWrapper
  • XmlNode: com.questetra.bpms.core.event.scripttask.XPathWrapper.NodeWrapper
  • XmlNodeList: com.questetra.bpms.core.event.scripttask.XPathWrapper.NodeListWrapper
%d