JS7® JobScheduler WorkFlow If条件分岐

# 概要

JS7 JobSchedulerのWorkFlow定義で利用するIf条件について説明します。
基本的なIf条件の利用方法、および条件指定のサンプルを取り上げます。

# 前提条件

- JS7 jobscheduler の環境準備、初期設定を済ませていること。
まだの方はこちらから
[JS7® JobScheduler 初期設定、サンプルWorkFlowの登録](https://qiita.com/saitamanokusa/items/2d3162b688329f5ecae2)
- WorkFlowの作成、実行、ログ確認などの基本操作ができること。
  こちらで簡単な操作説明をしています
  [JS7 JobScheduler 初めてのWorkFlow実行](https://qiita.com/saitamanokusa/items/1e5ab48cd2e9d38e035c)
- 基本的な変数の使い方を理解していること。
  こちらで説明をしています。
  [JS7® JobScheduler WorkFlowでの変数利用](https://qiita.com/saitamanokusa/items/333e16149741f81dbdc3)
  ※最低でも前半の「変数を使ってみる」はおさえておくこと
- 本サンプルはJobScheduler Ver. 2.3.0 で検証した内容です。
今後内容が変わる可能性があります。

# 基本的な使い方

WorkFlow If命令の Predicate 欄に、True または False で評価されるような、条件式を記述します。
このとき、Order変数（WorkFlow定義、シェルジョブ定義）を利用することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/e20f3c83-5f25-11d3-d466-835378c067f7.png)


## 条件式で利用可能なデータ型

String,Number,Boolean の3タイプが扱えます。

- String: `"i have a pen"` シングルクォート、またはダブルクォートで囲むこと
- Number: `1`, `-10`   (JAVA BigDecimal) ※小数は、計算式で扱えるが、直接記述はできない
- Boolean: `true`, `false`

## 変数の参照のしかた

変数は `$変数名` もしくは `${変数名}` `${'変数名'}`で表します。

※変数名にドットを付ける場合はクォートで囲む必要あり。 `$'mail.smtp.host'`

## 演算子

下記の演算子をサポートしています。

- 数値比較演算子：`==, !=, >, <, >=, <=, in`
- 文字列比較演算子：`==, !=, matches`
- 算術演算子：`+ - * /`
- 文字列結合：`$var1 ++ $var2`

## 否定

`!` をつけることで条件の否定となります。

## 二項演算

複数条件の論理積を`&&`で、論理和を`||`で表すことができます。

## 型変換

シェルジョブ中で定義したOrder変数は、すべてString型となります。
そのため、条件式で利用する際に、型変換用のメソッド `toNumber`, `toBoolean` が用意されています。
※toStringはありません。

## 組み込み定数

`$returnCode`, `$js7OrderId` などが組み込み定数で利用可能です。
文字通り、前JOBの リターンコード 、実行時のOrderIDが入ります。

`$returnCode`を利用するには、前Jobで On Success 時の Return Codeを追加する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/580a212c-2e26-492b-fad1-6db885e823fa.png)


:::note warn
WorkFlowの先頭のJOBで使うと、未定義エラーとなります。
:::

:::note
正常／エラー時の通知を行う場合は、WorkFlowのIf条件を使って定義するよりも、Notificationの機能を利用するほうが簡単です。
:::

# If 条件式の例

## 前提

サンプル条件式中に出てくるOrder変数は、下記のように定義したものとします。

- WorkFlowで定義：
  - Number型 `num1`, `num2`
  - String型 `str1`, `str2`
  - Bool型 `bool1`, `bool2`
- シェルジョブ中で定義：
  - String型 `ret_str1`, `ret_str2`
  - String型(数値代入) `ret_num1`, `ret_num2`
  - String型(bool値代入) `ret_bool1`, `ret_bool2` 

## 数値のチェック

前JOBのリターンコードによって処理を分岐
※`$returnCode` はNumber型の変数として参照できます。

```text
$returnCode == 0
```

```text
$returnCode != 0
```

```text
$returnCode > 0
```

Order変数 `$num1` が1,2,3 の場合

```text
$num1 in [1,2,3]
```

## true/false

bool型の場合、小文字の`true`, `false` でチェックする

```text
$bool1 == true
```

bool値はそのまま判定に使用可能
Order変数によって処理を変えたい場合はこれでよい

```text
$bool1 
```

## 否定

`!` をつけることで、否定となる

```text
!( $bool2 == true)
```

## 二項演算

Order変数で`$num1` , `$num2` どちらも0ならはTrue

```text
( $num1 == 0 ) && ( $num2 == 0 )
```

Order変数で`$num1` , `$num2` いずれかでも0ならはTrue

```text
( $num1 == 0 ) || ( $num2 == 0 )
```

:::note
複数条件を扱う場合は ( ) で囲うことをお勧めします。
処理によっては ( ) で囲わないとうまくチェックできない場合があります。
:::

## 文字列

シェルジョブ定義の変数を使ったチェック
※値が文字列となるため注意

```text
ret_str1 == "success"
```

```text
( $ret_num1 == "0" ) && ( $ret_num2 == "0" )
```

```text
( $ret_bool1 == "true" ) || ( $ret_bool2 == "true" )
```

## 型変換

シェルジョブ定義変数は、すべてString型となるため、数値、bool値との比較はエラーとなります。
そのため型変換をしてから利用します。

```text
($ret_num1.toNumber in [0,1,2]) || ($ret_num2.toNumber >= 0)
```

```text
( $ret_bool1.toBoolean == false )
```

```text
$ret_bool1.toBoolean && $ret_bool2.toBoolean
```

### 【参考】型変換可能な値

型変換が可能な値は限られています。試した結果、下記のとおりでした。

- toNumber で変換できたもの
  - String型: `"0"`, `"1"`, `"01"`, `"-50"`, `"+40"`
  - bool型: `true : 1`, `false : 0`
- toNumber で変換できないもの
  - String型: `"abc"`, `"1+2"`, `"*5"`, `"true"`, `"false"`
- toBoolean で変換できたもの
  - String型: `"true"`, `"false"` (小文字のみ)
  - Number型: `1 : true` `0 : false`
- toBoolean 変換できなかったもの
  - String型: `"True"`,`"TRUE"` (大文字) 、`"yes"`, `"no"`, `"success"`, `"fail"`, `"0"`, `"1"`
  - Number型:  `-1`, `2`

:::note
型変換を行わず、条件式をすべてString型前提で書いてもよい
:::

```text
$ret_bool1 == "true"
$ret_num == "1"
```

---

## 正規表現

`$ret_str1` の値が `yyyy-mm-dd-xxxxxx` である場合

```text
$ret_str1 matches '^[0-9]{4}-[0-9]{2}-[0-9]{2}-\w+?$'
```

`$ret_str2` に `error` という文字が含まれる場合

```text
$ret_str2 matches ".*error.*"
```

## デフォルト値

変数にデフォルト値を定義することで、シェルジョブ定義変数の定義漏れに配慮することができる。

`$ret_str1` が空ではない場合

```text
variable("ret_str1", default = "" ) != ""
```

`$ret_num2`が5より大きい場合

```text
(variable("ret_num2", default = "0" )).toNumber > 5
```

## JOB指定で変数参照

`variable("変数名", job = ジョブ名 )` , `variable("変数名", label = ラベル名 )`で、指定JOBでの変数値を参照できる

`$ret_str1` の値がjob1以降で変更された場合

```text
variable("ret_str1", job = job1 ) != $ret_str1
```

`$ret_str2` の値がjob1とjob2で変わらない場合

```text
variable("ret_str2", label = job1 ) == variable("ret_str2", label = job2 )
```

## その他

計算や文字の加工の例
あまり意味がない内容ですが、このような条件式が書ける一例としてメモします。

```text
( $num1 + $num2 == $num3 )
```

```text
($num1 - $num2 ) * $num3 > 10
```

小数を扱う場合、条件式上に小数値は書けないが、小数を使った計算は可能。

`$num1 = 3141592653`  , `$num2 =  1000000000` → false
`$num1 = 31415926535` , `$num2 = 10000000000` → true

```text
( $num1 / $num2 ) > (3141592653 / 1000000000 )
```

文字列結合

```text
"hello " ++ $str1 == "hello world"
```

文字列を置換したうえで判定

```text
replaceAll( $str1, "a", "b") == "bbcde"
```

OrderID から、日付部分 `yyyy-mm-dd` を正規表現で抽出
※DailyPlanで実行の場合はTimeZoneの日付、手動Order実行の場合はUTC日付となる

```text
replaceAll( $js7OrderId, '^#([0-9]{4}-[0-9]{2}-[0-9]{2})#.*$', '$1' ) == "2022-04-30"
```

組み込み定数`$js7WorkflowPath`でWorkFlow名を参照

```text
$js7WorkflowPath == "check_if"
```

# 最後に

細かく条件式の例を取り上げてしまいましたが、実際に利用する場合は、bool型、number型の利用のみで、シンプルな条件で済ませたほうがよさそうです。
うまく条件指定ができれば、同一WorkFlow定義で、状況に応じた処理のスキップや、営業日／休日で処理を分けるなど、柔軟な処理を書けるようになりますので、是非マスターしてください。

# 参考

[JS7 - If Instruction](https://kb.sos-berlin.com/display/PKB/JS7+-+If+Instruction)

[JS7 - Expressions for Variables](https://kb.sos-berlin.com/display/PKB/JS7+-+Expressions+for+Variables)