Flowable 6.8:フォームデータのリプレイ方法

前回の記事では、フォームとそのデータストレージについて学びました。フォームは、ユーザーがカスタマイズしたページであり、その中核となるのは要素のキー(key)と、ユーザーが入力した値(value)です。プロセスの開始時に、これらのデータはact_ru_variableテーブルに保存されます。フォームの値だけでなく、プロセスで定義された条件式なども同様に保存されます。

以下は、ユーザーがカスタマイズしたフォームの例です。

ユーザーはこのフォームにデータを入力し、プロセスを開始します。

プロセスが開始されると、履歴フォームのデータを確認できます。

1. データのリプレイ

赤色で示した部分は、プロセスリスナー(以前の記事で説明済み)を使用して取得した業務データです。

インターフェースから、フォームのデータがformElementsコレクションに保存されていることがわかります。

矢印が示す部分がフォームの値です。この値はフォーム要素に設定され、ユーザーが値を入力しなかった場合は、フォームのデフォルト値が使用されます。この例ではユーザーが値を入力したため、そのデータが表示されています。

ユーザーが値を入力すると、その値が優先して使用されるのは、フォームがMapコレクションであるためです。Mapの特性は、順序がなく、重複が許可されず、インデックスもないことです。重複が許可されないため、ユーザーが値を入力すると、データベースを照会して、既存の値を上書きするからです。

2. インターフェースのVoオブジェクト

このインターフェースの戻り値オブジェクトは以下の通りです。

public class FlowableDetailVo {
    /**
     * タスクフォーム情報
     */
    private FormConfiguration taskFormData;

    /**
     * 履歴プロセスノード情報
     */
    private List<ProcessNodeVo> historyProcNodeList;
    /**
     * プロセスフォームリスト
     */
    private List<FormConfiguration> processFormList;
    private List<ReactFormConfig> reactFormConfigList;
    private ReactFormConfig taskReactFormConfig;
    /**
     * プロセスXML
     */
    private String bpmnXml;
    private FlowViewerVo flowViewer;
    /**
     * タスクフォーム情報が存在するか
     * @return true:存在;false:存在しない
     */
    public Boolean isExistTaskForm() {
        return ObjectUtil.isNotEmpty(this.taskFormData);
    }
}

その中のReactFormConfigがこのフォームオブジェクトです。

public class FormConfiguration {
    /**
     * タイトル
     */
    private String title;

    /**
     * フォーム値
     */
    private List<Map<String, Object>> formElements;
    private Map<String, Object> selectedItem;
    private Map<Object, Object> globalConfig;
    private Map<String, Object> formConfig;
    
    // ゲッターとセッター
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public List<Map<String, Object>> getFormElements() { return formElements; }
    public void setFormElements(List<Map<String, Object>> formElements) { this.formElements = formElements; }
    // ... 他のゲッターとセッター
}

このようなフォームオブジェクトを設計した理由がお分かりでしょう。次に、フォームが生成するJSONを見てみましょう。

テキストにコピーして確認すると、これはJSONオブジェクトであり、フォームの様々な属性を表しています。その中のformElementsがフォーム要素の値です。

赤色の枠がフォーム要素の名前、緑色の枠が要素のデフォルト値です。

3. 履歴ノードのフォーム情報の取得

// タスクノードのパラメータをクエリし、Mapに変換
Map<String, Object> variables = historyService.createHistoricVariableInstanceQuery()
        .processInstanceId(historicProcIns.getId())
        .taskId(activityInstance.getTaskId())
        .list()
        .stream()
        .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));

履歴ノード情報を取得するには、act_hi_varinstテーブルからプロセスインスタンスID(PROC_INST_ID_)に基づいて、そのプロセスが保存したすべての変数値を取得します。

Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)の部分は、変数をMap<VariableName, VariableValue>に変換するものです。テーブルを見れば、PROC_INST_ID_を基にNAME_とTEXT_の値を取得していることが明確にわかります。

次に、現在のフォーム要素を反復処理し、取得した履歴ノードの値をそこに設定します。

4. データのリプレイ

【コメントを詳しくご覧ください】

/**
 * フォーム項目の内容を埋める
 *
 * @param formConfig <strong>Reactのフォーム設定情報</strong>
 * @param historicalData <strong>フォームの内容、つまり上記で取得した履歴プロセスのMapコレクション</strong>
 * @param isDisplayOnly <strong>このブール値は、現在のプロセスフォームを取得するか、履歴プロセスフォームを取得するかを区別するためのもの</strong>
 */
public static void populateFormData(FormConfiguration formConfig, Map<String, Object> historicalData, boolean isDisplayOnly) {
    for (Map<String, Object> element : formConfig.getFormElements()) {
        assignValueToElement(element, historicalData, isDisplayOnly);
    }
}

このメソッドのelementは、個々のフォーム要素です。キーに注意してください。

/**
     * 値を割り当てる
     *
     * @param element
     * @param historicalData
     */
    private static void assignValueToElement(final Map<String, Object> element, final Map<String, Object> historicalData, boolean isDisplayOnly) {
        if (!element.containsKey("formItemConfig")) {
            return;
        }
        Map<String, Object> elementConfig = (Map<String, Object>) element.get("formItemConfig");
        String elementKey = Convert.toStr(element.get("key"));
        Object value = historicalData.get(elementKey);
        if (value != null) {
            elementConfig.put("initialValue", value);
        }
        if (isDisplayOnly) {
            Map<String, Object> configMap = (Map<String, Object>) element.get("config");
            if (!configMap.isEmpty()) {
                configMap.put("disabled", true);
            }
        }
    }
}

上記のコードで、赤色で示したブール変数について説明します。ここでは、フォームオブジェクトの値にtrueを設定し、disabled(無効化)をtrueにします。これにより、フォームは編集できなくなり、ユーザーに履歴フォーム情報を表示するだけになります。

フォームのconfig要素のdisabledをtrueに設定すると、そのフォーム要素は無効化され、承認者が履歴ノードのフォームを表示するために使用されます。

以上がフォームデータのリプレイの説明です。今回は「プロセス履歴詳細インターフェース」の約1/5しか説明していません。

関連コードは多岐にわたります。必要であれば、私にメッセージを送ってください(無料)

タグ: Flowable BPMN Java Workflow FormData

6月21日 23:19 投稿