PlantUML使い方メモ

長くなるので、図の書き方はクラス図とシーケンス図だけで。

その他の図については [続・PlantUML使い方メモ #PlantUML - Qiita](https://qiita.com/opengl-8080/items/26e1eee6365e5db9947c) を参照。

# PlantUML とは
- テキストで UML 図を記述できる DSL の一種（たぶん）
- 本体は Java で書かれていて、単一の jar ファイルを落としてきてコマンドラインから実行できる
    - [plantuml/plantuml: Generate UML diagram from textual description](https://github.com/plantuml/plantuml)
- ただし、実際に使うときは Visual Studio Code とかのプラグインを入れて実行することが多いと思う
- ライセンスは GPL v3
    - [plantuml/license.txt at master · plantuml/plantuml](https://github.com/plantuml/plantuml/blob/master/license.txt)

# 環境構築
OS は Windows10。

## Java
```
> java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)
```

インストール方法は割愛。

## PlantUML 本体
https://plantuml.com/ja/download

ここから `plantuml.jar` を落としてくる。
確認時点では `plantuml.1.2020.7.jar` だった。

## Graphviz
http://www.graphviz.org/download/

図の描画に使用しているソフトウェアっぽい。
[Graphviz - Wikipedia](https://ja.wikipedia.org/wiki/Graphviz)

シーケンス図とアクティビティ図 **以外** の図を生成したい場合は必要なので、事実上必須。

自分が落としたのは `2.38`。

### dot.exe の場所を指定する
PlantUML を実行するときに、 Graphviz に含まれている `dot.exe` の場所を指定する必要がある。
指定方法は次のいずれか（採用される優先度が高いモノ順に並べている）。

1. `-graphvizdot` オプションで指定する
2. システムプロパティ `GRAPHVIZ_DOT` で指定する
3. 環境変数 `GRAPHVIZ_DOT` に設定する

仮に、 Graphviz をインストールしたフォルダが `C:\Graphviz` だったとすると、次のような感じで指定する。


```text:-graphvizdotオプションで指定した場合
> java -jar plantuml.jar -graphvizdot C:\Graphviz\bin\dot.exe ...
```

```text:システムプロパティで指定した場合
> java -DGRAPHVIZ_DOT=C:\Graphviz\bin\dot.exe -jar plantuml.jar ...
```

```text:環境変数で指定した場合
> set GRAPHVIZ_DOT
GRAPHVIZ_DOT=C:\Graphviz\bin\dot.exe
```

## VSCode
以下のプラグインを使う場合は、 VSCode を実行する前に環境変数 `GRAPHVIZ_DOT` を設定しておく。

### PlantUML
[PlantUML - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml)

- VSCode で PlantUML を書くためのプラグイン
- `Alt` + `d` でプレビューが表示される
- 複数の `@startuml...@enduml` がある場合は、現在カーソルが存在する場所の図がプレビューされる

![plantuml.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/8ba173c9-6ce9-ca12-637b-069765dafca4.jpeg)

### Markdown Preview Enhanced
[Markdown Preview Enhanced - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)

- Markdown 中の PlantUML をプレビューできるようにするプラグイン
- `Ctrl` + `k`, `v` でプレビューが表示される

![plantuml.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/a67b49c0-94b1-b3ff-e1e1-5c9cf889e3a2.jpeg)

**2024-03-29 追記**

なんか、 jar を手動で追加しないといけなくなった？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/df604f77-9bed-41fe-3037-fe5a5d6a75c9.png)

https://plantuml.com/ja/download から `Compiled jar` をダウンロードする。
ライセンスごとに分かれているので、自分の用途に影響しないやつを選んでダウンロードする感じか？（とりあえずMIT選んでおけば事故らない？）

jar を入手したら、 VSCode に設定する。
[File] > [Preferences] > [Settings] を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/e2741f38-93ff-9b3d-02de-4df584011516.png)

フィルターに `markdown-preview-enhanced.plantumlJarPath` と入力して、出てきた項目にダウンロードした jar のパスを入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/bc9654c4-834f-5f43-3aec-d3aa8221f559.png)

これでプレビューが表示されるようになるはず。


# Hello World
```text:hello.pu
@startuml
Hello <|-- World
@enduml
```

- テキストファイルを作って、中身を↑のように記述する
- ファイルの拡張子は `pu` が慣例？

```text:実行
> java -jar plantuml.jar hello.pu
```

- 引数に作成したテキストファイルを指定して実行する
- すると、引数で指定したファイルと同じ場所に `hello.png` というファイルが出力される

**hello.png**

![hello.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/9cc05219-83f1-7252-3968-0d792abec5f5.png)

# コマンドラインからの実行方法
## ファイル指定
```
> dir /b
fuga.pu
hoge.pu
piyo.pu

> java -jar plantuml.jar hoge.pu fuga.pu piyo.pu

> dir /b
fuga.png
fuga.pu
hoge.png
hoge.pu
piyo.png
piyo.pu
```

- ファイルのパスを引数に指定して実行できる
- ファイルは複数指定可能
- ファイル名と同じ名前の png ファイルが、ファイルと同じ場所に生成される

## ディレクトリ指定
```text:フォルダ構成
`-hoge/
  |-plantuml.pu
  |-markdown.md
  |-JavaSource.java
  `-fuga/
    `-fuga.pu
```

- `hoge` ディレクトリの直下に、３つのファイルを配置している
- それぞれ、中身は次のようになっている

**plantuml.pu**

```text
@startuml
class PlantUml
@enduml
```

**markdown.md**

    ```
    @startuml
    class Markdown
    @enduml
    ```

**JavaSource.java**

```java
/**
 * @startuml
 * class JavaSource {
 *   - String message
 * }
 * @enduml
 */
public class JavaSource {}
```

- `hoge` フォルダの下には `fuga` ディレクトリがあり、その下には `fuga.pu` ファイルを配置している

**fuga.pu**

```
@startuml
class Fuga
@enduml
```

### 実行
```
> java -jar plantuml.jar hoge
```

```text:実行後
`-hoge/
  |-plantuml.pu
  |-plantuml.png
  |-markdown.md
  |-JavaSource.java
  |-JavaSource.png
  `-fuga/
    `-fuga.pu
```

- `plantuml.png` と `JavaSource.png` が生成されている

**plantuml.png**

![plantuml.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/ca98ecdb-edea-8f85-fa05-cc5280c4f019.png)

**JavaSource.png**

![JavaSource.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/d21468f0-fa38-4f57-c529-d50d5f7c6bdb.png)

- フォルダを指定して実行すると、そのフォルダ直下に存在するファイルが自動的に読み込まれる
- 次の拡張子に該当するファイルが、読み込みの対象となっている
    - `.c`
    - `.h`
    - `.cpp`
    - `.txt`
    - `.pu`
    - `.tex`
    - `.html`
    - `.htm`
    - `.java`
- これらのファイルの中に `@startuml` からはじまり `@enduml` で終わる部分を見つけると、その部分から画像を生成してくれる

## ワイルドカードで指定する
- ↑と同じ構成で、次は以下のようにコマンドを実行する

```
> java -jar plantuml.jar "hoge/**"
```

- フォルダを指定した部分を、 `"hoge/**"` としている

```text:実行結果
`-hoge/
  |-plantuml.pu
  |-plantuml.png
  |-markdown.md
  |-markdown.png
  |-JavaSource.java
  |-JavaSource.png
  `-fuga/
    |-fuga.pu
    `-fuga.png
```

- `markdown.png` や `fuga.png` も生成されている

**markdown.png**

![mardown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/4a59312f-aab4-e9fb-bc4b-7b74288af33b.png)

**fuga.png**

![fuga.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/ff382f16-d246-1b73-0d8f-fdfb90a600df.png)

- 対象の指定には、次のワイルドカードが使用できる
    - `*` 任意の文字列
    - `?` 任意の１文字
    - `**` 任意のサブディレクトリ

### 除外対象を指定する
```
> java -jar plantuml -x "**/*.pu" "hoge/**"
```

```text:実行結果
`-hoge/
  |-plantuml.pu
  |-markdown.md
  |-markdown.png
  |-JavaSource.java
  |-JavaSource.png
  `-fuga/
    `-fuga.pu
```

- 拡張子が `pu` のファイルだけ png ファイルが生成されていない
- `-x` オプションで除外対象を指定できる

## 文字コードの指定
```
> java -jar plantuml.jar -charset UTF-8 hello.pu
```

- 文字コードは `-charset` オプションで指定する

## 標準入力から読み込む
```
> type plantuml | java -jar plantuml.jar -pipe > result.png
```

- `-pipe` オプションを指定すると標準入力から読み込むので、パイプが可能になる
- 結果は標準出力に書き出されるので、適当なファイルにリダイレクトしてあげればいい

## 複数の図の記述が存在した場合
```text:hoge.pu
@startuml
class Hoge
@enduml

@startuml
class Fuga
@enduml

@startuml
class Piyo
@enduml
```

- １つのファイル内に複数の `@startuml...@enduml` の記述が存在した場合

```text:実行
> java -jar plantuml.jar hoge.pu
```

```text:実行結果
> dir /b
hoge.png
hoge.pu
hoge_001.png
hoge_002.png
```

**hoge.png**

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/448e5b70-78a2-c938-d548-6814ebecab15.png)

**hoge_001.png**

![hoge_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/18508397-f170-4644-53a8-fa5f3a291b77.png)

**hoge_002.png**

![hoge_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/c5a12ab2-2ad1-cd18-4aef-e296093d9ec9.png)


- 最初の図が `ファイル名.png` で生成される
- 残りの図は、 `ファイル名_XXX.png` の連番で生成される
    - 1000個以上あったらどうなるのかは試していない

### 図ごとにファイル名を指定する
```text:hoge.pu
@startuml hoge
class Hoge
@enduml

@startuml fuga
class Fuga
@enduml

@startuml piyo
class Piyo
@enduml
```

- 各 `@startuml` の後ろに名前を記述している

```text:実行
> java -jar plantuml.jar hoge.pu
```

```text:実行結果
> dir /b
fuga.png
hoge.png
hoge.pu
piyo.png
```

**hoge.png**

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/4148343e-8e57-5ef0-35bf-8aac60ae6cb1.png)

**fuga.png**

![fuga.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/7b2cf4fa-7899-c9a1-73d4-dc262f4b64d3.png)

**pioy.png**

![piyo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/aa03b5d9-6f9b-1c14-07af-83a8ebddb571.png)

- `@startuml 名前` とすることで、図ごとのファイル名を指定できる

## ヘルプの表示
```
> java -jar plantuml.jar -h
```

- ヘルプは、 `-h` または `-help` で表示できる

# 共通
## コメント
```
@startuml no-scale
' これはコメント
Hello <|-- World
@enduml
```

- シングルクォーテーション (`'`) から後ろはコメント扱いになる

## タイトル
```
@startuml
title Hello Title
Hello <|-- World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/dea0e74d-788d-d466-c684-4e770fa1b0d9.png)

- `title タイトル` と記述することで、図のタイトルを設定できる

### 複数行のタイトル
```
@startuml
title
Hello
Title
end title
Hello <|-- World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/81039cab-d6f7-a989-fa0e-c4db8a98dd17.png)

- `title` と `end title` で囲うことで、複数行のタイトルが記述できる

### マークアップ言語で書く
```
@startuml
title
* __Hello__
* **World**
end title
Hello <|-- World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/adda6f28-414e-dca8-c2c4-03549b3b11c6.png)

- Creole というマークアップ言語を使用できる
- [Creole の記述例はこちら](#creole)

## キャプション
```
@startuml
caption 図１
Hello <|-- World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/360539c3-2b41-7741-624e-26eb7078d110.png)

- `caption キャプション` で、図のキャプションを設定できる

## ヘッダー・フッター
```
@startuml
header Hello
Hello <|-- World
footer World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/cb088145-8b1f-5c19-9e47-97ae2d24139b.png)

- `header ヘッダーコメント`, `footer フッターコメント` で、ヘッダーとフッターを指定できる
- デフォルトだと、ヘッダーは右寄せ、フッターはセンタリングになる
- [Creole で記述できる](#creole)

### 位置を指定する
```
@startuml
left header Hello
Hello <|-- World
right footer World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/96315a4c-8d91-6cf1-865e-528049e7cb5a.png)

- `left`, `center`, `right` を `header`, `footer` の前に記述することで、位置を調整できる

### 複数行で書く
```
@startuml
header
Hello
Header
end header

Hello <|-- World

footer
World
Footer
end footer
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/32c1f2de-1b59-c27b-f31e-1e9d9c8b708a.png)

- `header ... end header`, `footer ... end footer` で囲むことで、複数行で記述できる

## 凡例
```
@startuml
legend
Hello World
end legend

Hello <|-- World
class FizzBuzz
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/61472cc6-07f2-9d59-295d-8756c8a415f4.png)

- `legend ... end legend` で、凡例を挿入できる
- デフォルトでは、中央下に配置される

### 位置を指定する
- `legend` の後ろに上下の位置 (`top`, `bottom`) と左右の位置 (`left`, `center`, `right`) を指定できる

```
@startuml right
legend right
Right
end legend

Hello <|-- World
class FizzBuzz
@enduml
```

![right.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/f33a12ff-1393-becd-baff-35dc8e701c8b.png)

- 左右の位置だけ指定した場合、上下の位置はデフォルトの `bottom` になる

```
@startuml top
legend top
Top
end legend

Hello <|-- World
class FizzBuzz
@enduml
```

![top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/a11796d8-c207-843a-3967-d38c5f999182.png)

- 上下の位置だけ指定した場合、左右の位置はデフォルトの `center` になる

```
@startuml top-left
legend top left
Top Left
end legend

Hello <|-- World
class FizzBuzz
@enduml
```

![top-left.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/431869bd-b5f8-b08e-f526-ab5f3ad7c8ca.png)

- 両方とも指定した場合は、指定された位置に表示される
- このとき、 `legend left top` のように上下と左右の位置指定を逆にするとエラーになる
    - 必ず、上下の位置→左右の位置の順番で指定する必要がある

## 拡大率
```
@startuml no-scale
Hello <|-- World
@enduml

@startuml scale-1.5
scale 1.5
Hello <|-- World
@enduml

@startuml scale-0.5
scale 0.5
Hello <|-- World
@enduml
```

![plantuml.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/e51c1711-ece5-b430-4fa8-fca3d5511d0c.jpeg)

- `scale 拡大率` と記述することで、その図の拡大率を指定できる

## Creole
- wiki 記述言語の１つ
- タイトルやノートで、この記法が使用できる

```
@startuml
note left
  --見出し--
  = 見出し１
  == 見出し２
  === 見出し３
  
  --番号なしリスト--
  * リスト１
  * リスト２
  ** リスト２－１
  * リスト３

  --番号付き--
  # 番号付きリスト１
  # 番号付きリスト２
  ## 番号付きリスト２－１
  # 番号付きリスト３

  --装飾--
  * **太字**
  * //イタリック//
  * ""等幅フォント(monospace)""
  * --取り消し線--
  * __下線__

  --テーブル--
  |= |= Column1 |= Column2 |
  |1 |Value1-1  |Value1-2  |
  |2 |Value2-1  |Value2-2  |

  --HTML--
  * <color:red>色名指定</color>
  * <color:#00FF00>カラーコード指定</color>
  * <back:skyblue>背景色</back>
  * <size:18>フォントサイズ</size>
  * <b>太字</b>

  --木構造--
  |_build.gradle
  |_src
    |_main
      |_java
        |_**bold**
        |_--strike--
        |_//itaric//
        |___underline__
        |_""monospace""
    |_test

  --Unicode--
  * <U+20BB7>

  --Escape--
  * **これは太字になる**
  * ~**これは太字にならない**

  --水平線--
  --タイトルを挟める--
  ----
  ==タイトルを挟める==
  ====
  ..タイトルを挟める..
  ....
end note
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/4bc3d5bd-de55-3643-1c53-84989b83a336.png)


## フォントを指定する
```
@startuml
skinparam DefaultFontName メイリオ
おはよう <|-- 世界
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/72650ce2-198f-5cbc-c7b6-86d0b0478c80.png)

- `skinparam DefaultFontName フォント名` と記述することで、デフォルトのフォントを指定できる
- `skinparam` は、 `skinparam <key> <value>` という書式で様々なスキン設定を指定できる
- `DefaultFontName` はデフォルトのフォントを指定するキー
- `CaptionFontName` や `ClassFontName` のように、特定の要素ごとにフォントを指定することも可能
- `<key>` に指定できる値の一覧は、次のコマンドで確認できる

```
> java -jar plantuml.jar -language
...
;skinparameter
;536
ActivityBackgroundColor
ActivityBarColor
ActivityBorderColor
ActivityBorderThickness
ActivityDiamondBackgroundColor
ActivityDiamondBorderColor
ActivityDiamondFontColor
...
```

# クラス図
## クラスを宣言する
```
@startuml
class Hello
class World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/4f6dce55-a8a5-2115-a193-5cb1b4dfe532.png)

- `class <型名>` と記述することで、クラスを宣言できる

## インターフェースを宣言する
```
@startuml
interface Hello
interface World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/81f46bb2-dc57-1374-a875-a35a9b4910c8.png)

- `interface <型名>` と記述することで、インターフェースを宣言できる

## 抽象クラスを宣言する
```
@startuml
abstract class Hello
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/90792023-a12b-39ea-3d52-44a72ec01459.png)

- `abstract class <型名>` とすることで、抽象クラスを宣言できる

## enum を宣言する
```
@startuml
enum HelloWorld {
    ONE
    TWO
    THREE
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/566da043-5018-a5e5-f95e-95591eb400f1.png)

- `enum <型名>` で、 enum を宣言できる
- 続けて波括弧 `{...}` を書き、そのなかで定数を宣言できる

## 型間の関連を記述する
### 関連（リンク）
```
@startuml
Hello -- World
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/5d926bc1-c8ff-0823-42a9-9a751af3763b.png)

- `<型名> <関連を表す線> <型名>` と記述することで、型間の関連を記述できる
- `--` は、単純な関連だけを記述できる
- `class <型名>` で宣言していない型でも使用可能
    - 宣言と合わせて記述することも可能

### 誘導可能性の表現
```
@startuml
class One
One --> Two
Three <-- Four
Five <--> Six
Seven x-- Eight
Nine --x Ten
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/bf609106-9cd3-04a9-a770-046196dd9e0a.png)

- `<`, `>`, `x` で、誘導可能性を表現できる

### 依存
```
@startuml
One ..> Two
Three <.. Four
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/4cad33da-1ead-56c6-8d06-4939ceec0860.png)

- `..>`, `<..` で、依存を表現できる

### 汎化
```
@startuml
One --|> Two
Three <|-- Four
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/6258c962-c0bb-2d8a-806a-b413ed94dc46.png)

- `<|--`, `--|>` で、汎化を表現できる

### 実現
```
@startuml
One ..|> Two
Three <|.. Four
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/ab0e9002-58d6-2774-2843-60b26d809dce.png)

- `..|>`, `<|..` で、実現を表現できる

### 集約
```
@startuml
One --o Two
Three o-- Four
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/fe134c78-e91d-251f-8672-e04918af1f21.png)

- `--o`, `o--` で、集約を表現できる

### コンポジション
```
@startuml
One --* Two
Three *-- Four
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/3528c6b4-f493-7665-1acb-6874a61ef55f.png)

- `--*`, `*--` で、コンポジションを表現できる

### 関連名
```
@startuml
One -- Two : Hoge
Three -- Four : Fuga >
Five -- Six : < Piyo
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/a5706ce7-7158-a46e-66a8-d201e0bb6fe7.png)

- 関連を記述した後ろに `:` を入れると、そのさらに後ろに関連名を記述できる
- 関連名の前後に `<`, `>` を入れることで、関連の方向性を表現できる

### ロール名と多重度
```
@startuml
One "Foo" -- Two 
Three -- "Bar" Four
Five "1" -- "1..*" Six
Seven "1 Fizz" -- "~* Buzz" Eight
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/1d0b5a0f-4a2a-a495-a557-b4597f5b81d0.png)

- 型名と関連の線の間にダブルクォーテーション (`"`) で囲った文字列を記述することで、ロール名または多重度を記述できる
- ロール名用・多重度用に記述が分かれておらず、この記法をうまく利用して両方を記述しなければならないっぽい
    - [multiplicity and role name for both ends of an association - PlantUML Q&A](https://forum.plantuml.net/4953/multiplicity-and-role-name-for-both-ends-of-an-association)
- なお、 `* Buzz` のようにアスタリスク (`*`) で始めてしまうと Creole 記法のリスト扱いになってしまうので、 `~` でエスケープする必要がある

## フィールド・メソッドの定義
```
@startuml
class Hello {
    one: String
    three(param1: String, param2: int): boolean
    String two
    int four(List<String> param)
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/941a24ee-3004-c4cf-49a4-eb230b218e88.png)

- `class <型名>` の後に波括弧 (`{...}`) で囲った中で、フィールドやメソッドを宣言できる
- UML として正式な記述 (`フィールド名: 型名`) だけでなく、 Java 的な書き方 (`型名 フィールド名`) でも書ける
    - 結構なんでも書けるっぽいが、 UML の正式な記法にしておくのが無難だとは思う
- フィールドとメソッドは自動的に判定されて、よしなにクラス図のそれぞれの部分に描画される
    - こちらも、あえて混在させる必要はなく、キレイに分けて書いておいたほうが無難

### 可視性
```
@startuml
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/c3436302-f4f4-8f3e-bf76-345a88326c95.png)

- UML の記法で可視性を記述すると専用のアイコン表示になる
- 逆に分かりにくいって場合は、以下の様にしてアイコン表示をオフにすることもできる

```
@startuml
skinparam classAttributeIconSize 0
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/503025f7-f903-c7b2-8884-6a3eb22026ee.png)

- `skinparam classAttributeIconSize 0` を設定すると、可視性のアイコン表示は消える

### 抽象メンバー
```
@startuml
class Hello {
    {abstract} one: int
    {abstract} two(): int
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/8268a970-f20f-c3a8-411e-bd827ed63561.png)

- メンバーの先頭に `{abstract}` とつけることで、抽象メンバーにできる

### 静的メンバー
```
@startuml
class Hello {
    {static} ONE: int
    {static} two(): int
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/8e90c114-3b6a-59a0-9c16-851d46678079.png)

- メンバーの先頭に `{static}` とつけることで、静的メンバーにできる

## ステレオタイプ
```
@startuml
class Hello <<Hoge>>
class World <<Fuga>> {
    message: String
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/fe70ff53-f3df-7e06-a34c-419a3fe5243f.png)

- 型名の後ろに `<<ステレオタイプ>>` と記述することで、ステレオタイプを記述できる

## テンプレート
```
@startuml
class Hello<H>
class World<W> <<Hoge>>
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/3772f163-1566-9889-a40f-37ba5ffbd9e8.png)

- 型名の直後に `<名前>` と記述することで、テンプレートを表現できる
- ステレオタイプとの併用も可能

## 実現や汎化を Java コードっぽく書く
```java
@startuml
interface One
interface Two
interface Three extends Two
interface Four
class Five implements One, Three
class Six extends Five implements Four {
    field: String
    method(): void
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/bcb417b1-83e0-6e2b-d830-09cf21352f94.png)

- `extends` や `implements` を使って、まんま Java コードっぽく書ける
- これは捗る

## パッケージ
```
@startuml
package one.two {
    class Hello
}

package three.four {
    World -- Hello
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/4cbddca2-2a68-8d84-a06e-b06ea1f3b456.png)

- `package <名前> {...}` と記述することで、パッケージを表現できる
- 波括弧の中では、クラスや関連を記述できる

### 宣言の順序に注意
```text:パッケージ宣言の順序を逆転した場合
@startuml
package three.four {
    World -- Hello
}

package one.two {
    class Hello
}
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/c8476e4c-27e3-ff1b-9f2b-9596bf293d54.png)

- `Hello` クラスは `one.two` パッケージで宣言しているつもりだが、先に登場している `three.four` パッケージに含まれてしまっている
- どうやら、上から順番に見ていって最初に登場したパッケージ内で宣言したことになるっぽい

## ノート
```
@startuml
class Fizz
note left: fizz

class Buzz
note right: buzz

class Foo
note top: foo

class Bar
note bottom: bar
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/60c15d73-5b74-00f0-b309-2f09c6db9b08.png)

- クラスなどの宣言のうしろに `note <top|bottom|left|right>: <コメント>` と記述することで、直前の要素にたいしてノートを記述できる
- [Creole での記述も可能](#creole)

### ノートをつける要素を指定する
```
@startuml
Fizz -- Buzz
note left of Fizz: fizz
note right of Buzz: buzz
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/e57ec011-bb9a-fd2d-1e60-c95c73b561a1.png)

- `note <位置> of <対象>: <コメント>` と記述することで、 `<対象>` で指定した要素に対してノートをつけることができる

### 関連にノートをつける
```
@startuml
Fizz -- Buzz
note on link: fizz-buzz
note left: buzz
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/f05975a5-4ae4-1b54-fffc-45099bd86bcb.png)

- 型間の関連を記述したあとに `note on link: <コメント>` と記述することで、関連に対してノートをつけることができる

### ノートに名前をつける
```
@startuml
note "Hello World" as n1
Hello -- n1
World .. n1

note "Fizz Buzz" as n2
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/39465b22-0067-30dc-4cb1-218f9d67ebe7.png)

- `note "<コメント>" as <名前>` と記述することで、ノートに任意の名前を割り当てることができる
- 割り当てた名前を使って、好きな要素とノートを紐付けることができる
    - 型間の関連を書くのと同じような要領で線を引ける
- この記法なら、単独のノートを記述することもできる

### 複数行のノートを書く
```
@startuml
class Hello
note left
Hello
World
end note

Fizz -- Buzz
note on link
Fizz
Buzz
end note
note left of Fizz
fizz
buzz
end note

note as n1
Foo
Bar
end note
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/347dc4d8-e066-a696-3aac-7bf05849977f.png)

- 各ノートの記法は、 `end note` で終わらせることで複数行で書くことが可能

## 別名をつける
```text
@startuml
class "Hoge" as h {}
class "Fuga" as f {}

h --> f
@enduml
```

```plantuml
@startuml
class "Hoge" as h {}
class "Fuga" as f {}

h --> f
@enduml
```

- クラス名の後ろに `as 別名` と付けることで、クラス名に別名をつけられる
- この場合、クラス名はダブルクォーテーションで括る必要があるっぽい

## 背景色を設定する
```text
@startuml
class Hoge #skyblue {}
class Fuga #pink extends Hoge {}
class "ぴよ" as Piyo #FFFFFF {}
@enduml
```

```plantuml
@startuml
class Hoge #skyblue {}
class Fuga #pink extends Hoge {}
class "ぴよ" as Piyo #FFFFFF {}
@enduml
```

- クラス名のうしろに `#色` と指定することで、そのクラスの背景色を指定できる
- `色` には色名やカラーコードを指定できる
- `extends` や `implements` をしている場合は、その手前に記載する
- `as` で別名を指定している場合は、その後ろに記載する

## ステレオタイプごとに背景色を指定する
```text
skinparam classBackgroundColor<<Foo>> lightgreen
skinparam classBackgroundColor<<Bar>> lightpink

class Hoge <<Foo>>
class Fuga <<Foo>>
class Piyo <<Bar>>
class Fizz
```

```plantuml
skinparam classBackgroundColor<<Foo>> lightgreen
skinparam classBackgroundColor<<Bar>> lightpink

class Hoge <<Foo>>
class Fuga <<Foo>>
class Piyo <<Bar>>
class Fizz
```

- `skinparam classBackgroundColor<<ステレオタイプ>> <色>` と指定することで、ステレオタイプごとに背景色を指定できる
- `skinparam` は以下のようにも書くことができる(結果は同じ)

```text
skinparam class {
  BackgroundColor<<Foo>> lightgreen
  BackgroundColor<<Bar>> lightpink
}

class Hoge <<Foo>>
class Fuga <<Foo>>
class Piyo <<Bar>>
class Fizz
```

## 横向きにする
```text
left to right direction

Hoge <-- Fuga
Fuga <-- Piyo
```

```plantuml
left to right direction

Hoge <-- Fuga
Fuga <-- Piyo
```

- `left to right direction` と指定すると、図を横向きにできる

## JSON でデータを記述する
```text
class Hoge {
    string: String
    number: int
}

class Fuga {
    bool: boolean
}

Hoge --> "fuga" Fuga

json hoge {
    "string": "text",
    "number": 10,
    "fuga": {
        "bool": false
    }
}
```

```plantuml
class Hoge {
    string: String
    number: int
}

class Fuga {
    bool: boolean
}

Hoge --> "fuga" Fuga

json hoge {
    "string": "text",
    "number": 10,
    "fuga": {
        "bool": false
    }
}
```

- `json <名前> {...}` と記述することで、 JSON データを記載できる
- 実際のオブジェクトの様子とかを書けるかも


# シーケンス図
## 同期メッセージ
```
@startuml
Alice -> Bob: Hi
Bob --> Alice: Hi

Alice -> Bob: Is this a pen?
Bob --> Alice: No! This is an apple!!
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/0742901c-a850-e511-f963-6c8af09c3830.png)

- シーケンス図は、基本的に `<要素> <メッセージ> <要素>: <メッセージ名>` と記述していく
- `<メッセージ>` は、 `->` で同期メッセージになる
- `-->` は線が点線になり、応答メッセージに使用できる

## 非同期メッセージ
```
@startuml
Alice ->> Bob: Hi
Alice ->> Bob: Is this a pen?
Alice ->> Bob: Is this a pen??
Alice ->> Bob: Is this a pen???
Alice ->> Bob: Is this a pen????

Bob -> Alice: This is an apple!!!
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/217392f0-97ca-b4ef-2753-8ab3fec46ed3.png)

- `->>` と記述することで、非同期メッセージを表現できる

## ライフラインの並び順を指定する
```
@startuml
participant Alice
participant Bob
participant Carol

Carol -> Bob: Is the tip included?
Bob -> Alice: いずれテッペン超えれる？
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/042b7911-465d-31b0-718d-222915b2c8dc.png)

- 何もしないと、ライフラインは上から現れた順番で、左から並べられる
- ライフラインの順序を指定したい場合は、 `paritcipant <ライフラインの名前>` という形で別途並びを定義しておく

## ライフラインにアイコンを使う
```
@startuml
actor Actor
boundary Boundary
control Control
entity Entity
database Database
collections Collections
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/c7d231af-4cf3-4c5d-181f-54641f2eb3e1.png)

- `participant` の代わりに特定のキーワードを指定することで、役割に合わせたアイコンを使用できる

## 自分自身へのメッセージ
```
@startuml
Aclie -> Aclie: 逃げちゃ駄目だ
Aclie -> Aclie: 逃げちゃ駄目だ
Aclie -> Aclie: 逃げちゃ駄目だ
Aclie -> Aclie: 逃げちゃ駄目だ
Aclie -> Aclie: 逃げちゃ駄目だ
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/42336826-6d7c-8bc1-5556-aef943025477.png)

- 自分自身にメッセージを送ることもできる

## メッセージに番号を振る
```
@startuml
Alice -> Bob: Hi
autonumber
Bob -> Carol: Hi
Carol -> Dave: Hi
Bob -> Dave: Hi
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/763d34e8-aecd-e78a-7b34-55a64cf34f6e.png)

- メッセージの前に `autonumber` と記述することで、その後のメッセージに自動的に番号を振ることができる

### 開始番号と増分を指定する
```
@startuml
autonumber 3
Alice -> Bob: Hi
Bob -> Carol: Hi
autonumber 2 3
Carol -> Dave: Hi
Bob -> Dave: Hi
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/52842aca-e2c8-e7cd-6af4-7ede0049940e.png)

- `autonumber <開始> <増分>` のようにして、開始番号と増分を指定できる

### 自動採番の一時停止・再開
```
@startuml
autonumber
Alice -> Bob: Hi
autonumber stop
Bob -> Carol: Hi
Carol -> Dave: Hi
autonumber resume
Bob -> Dave: Hi
Carol -> Dave: Hi
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/96d1b12a-e9c2-0650-9313-b1ff7df2859c.png)

- `autonumber stop` で、自動採番を中断できる
- `autonumber resume` で、中断したところから自動採番を再開できる

## メッセージのグループ化
```
@startuml
Alice -> Bob: Is this a pen?
alt yes
    Alice <-- Bob: Yes! This is a pen!!
else no
    Alice <-- Bob: Noooooooo! This is an apple!!!!!
end
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/7545d32a-6b85-bf9e-ab6b-72f45acfac0c.png)

- 特定のキーワードを使うことでメッセージをグループ化できる
- 使用できる予約済みのキーワードは以下
    - `alt`/`else`
    - `opt`
    - `loop`
    - `par`
    - `break`
    - `critical`
- キーワードの後ろに任意の文字列を記述できる（分岐の条件などを記述できる）
- インデントは必要ないが、しておいたほうが見やすいと思う
- グループは次のように入れ子が可能

```text:入れ子にした場合
@startuml
Alice -> Bob: Is this a pen?
alt yes
    Alice <-- Bob: Yes! This is a pen!!
else no
    Alice <-- Bob: Noooooooo! This is an apple!!!!!
    loop ∞
        Alice -> Bob: Oh sorry! By the way, is this a pen?
        Alice <-- Bob: Noooooooooooooooooo!!!!
    end
end
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/66731c93-b311-1e5b-ce64-768dcebfe185.png)


### 任意の名前のグループを作る
```
@startuml
group コピペ
    Alice -> Bob: Is this a pen?
    Alice <-- Bob: No! This is an apple!!
end
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/31c58025-6fe0-5ba1-2fb1-54564e57d004.png)

- `group <名前>` とすることで、任意の名前のグループを書ける
- この場合、 `alt` などでかけたような条件に当たるところの記述はできない

## 実行仕様
```
@startuml
activate Alice
Alice -> Bob

activate Bob
Bob -> Carol

activate Carol
Bob <-- Carol

deactivate Carol
Alice <-- Bob

deactivate Bob
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/0c94f881-e580-2385-07a7-c14cfc5fb818.png)

- `activate <名前>` で、指定した名前のライフラインの実行仕様を表現できる
- `deactive <名前>` で明示的に非活性化させる必要がある

### 入れ子にする
```
@startuml
activate Alice
Alice -> Bob

activate Bob
Bob -> Bob
activate Bob
Bob -> Carol

activate Carol
Bob <-- Carol

deactivate Carol
Alice <-- Bob

deactivate Bob
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/af8d0f2c-b58a-b1cc-9825-b8469c902183.png)

- 実行仕様は入れ子にできる

## 実行仕様(ショートカット記法)
```
@startuml
Alice ++
Alice -> Bob ++

Bob -> Carol ++

Bob <-- Carol --

Alice <-- Bob --
Alice --
@enduml
```

```plantuml
@startuml
Alice ++
Alice -> Bob ++

Bob -> Carol ++

Bob <-- Carol --

Alice <-- Bob --
Alice --
@enduml
```

- `<名前> -> <名前> ++` のように、対象の分類子の直後に `++` を入れると、実行仕様を開始できる
- `<名前> <-- <Carol> --` のように、対象の分類子の直後に `--` を入れると、実行仕様を終了できる

## ライフラインの生成
```
@startuml
Alice -> Bob
create Carol
Bob -> Carol: new
Bob -> Carol
Bob <-- Carol
Alice <-- Bob
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/e3c4a291-9621-eb57-7d33-bd8b5067b18c.png)

- `create <名前>` と記述することで、指定した名前のライフラインを途中から生成できる



### ライフラインの生成(ショートカット記法)
```
@startuml
Alice -> Bob
Bob -> Carol ** : new
Bob -> Carol
Bob <-- Carol
Alice <-- Bob
@enduml
```

```plantuml
@startuml
Alice -> Bob
Bob -> Carol ** : new
Bob -> Carol
Bob <-- Carol
Alice <-- Bob
@enduml
```

- `<名前> -> <名前> ** : <メッセージ>` のように、対象の分類子の直後に `**` を入れると


## リファレンス
```
@startuml
Alice -> Bob
ref over Bob, Carol: あっちを参照
Alice <-- Bob
ref over Alice
そっちを
参照
end ref
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/dc3b320d-3e8a-5bc0-dba8-c6ef849ead6c.png)

- `ref over <リファレンスで囲う対象>: <説明>` と記述することで、リファレンスを記述できる
- リファレンスで囲う対象には、ライフラインの名前をカンマ区切りで複数指定できる
- `ref over ... end ref` とすることで複数行で記述することも可能

## 境界線
```
@startuml
== Foo ==
Alice -> Bob
Alice <-- Bob

== Bar ==
Bob -> Carol
Bob <-- Carol
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/49dec668-f1c9-765e-b5e0-edbc1a046614.png)

- `== <名前> ==` と書くことで、境界線を記述できる

## 外部からの（への）メッセージ
```
@startuml
[-> Alice: Hello
Alice ->]: Hello
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/479496e0-7ab2-97b4-10ea-ea79af497c4d.png)

- ライフラインの名前の代わりに `[`, `]` を使うことで、外部からの（への）メッセージを記述できる

## メッセージの間に間隔をあける
```
@startuml
Alice -> Bob
Alice <-- Bob

Alice -> Bob
Alice <-- Bob
|||
Alice -> Bob
Alice <-- Bob
||80||
Alice -> Bob
Alice <-- Bob
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/cd7dc4ea-1536-332d-e341-fa8b670d0ab9.png)

- メッセージの間に `|||` を挟むことで、少し間隔をあけることができる
- `||<ピクセル>||` とすれば、間隔の大きさをピクセルで指定できる

## ノート
```
@startuml
Alice -> Bob
note left: Hello
Alice <-- Bob
note right: World
Alice -> Alice
note left
Hello
World
end note
@enduml
```

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/d50c8296-1c65-02df-d108-e44a9e596987.png)

- メッセージの直後に `note left` または `note right` のいずれかでノートをつけることができる
    - `top`, `bottom` は使えない（使うとクラス図として解釈されてしまう）
- `note <left|right> ... end note` とすることで複数行で書くことも可能
- [Creole で記述可能](#creole)

# Java から使う
## Graphviz の指定
- コマンドラインから実行するときと同様で、 Graphviz の `dot.exe` の場所を指定しなければならない
- コマンドラインオプションはないので、システムプロパティか環境変数での設定になる

## 依存関係の指定
```gradle:build.gradle
plugins {
    id "application"
}

sourceCompatibility = 11
targetCompatibility = 11
compileJava.options.encoding = "UTF-8"

mainClassName = "sandbox.plantuml.Main"

repositories {
    mavenCentral()
}

dependencies {
    implementation "net.sourceforge.plantuml:plantuml:8059"
}
```

- [net.sourceforge.plantuml:plantuml](https://mvnrepository.com/artifact/net.sourceforge.plantuml/plantuml) を依存関係に追加する

## String ソースから読み込む
```java:Main.java
package sandbox.plantuml;

import net.sourceforge.plantuml.SourceStringReader;

import java.io.File;

public class Main {

    public static void main(String[] args) throws Exception {
        String source = "@startuml\n"
                      + "Foo <-- Bar\n"
                      + "@enduml";
        final SourceStringReader reader = new SourceStringReader(source);
        reader.generateImage(new File("result.png"));
    }
}
```

- `SourceStringReader` を使うと、 `String` のソースを読み込んで画像を生成できる
- `generateImage(File)` などのメソッドで、指定したファイルに結果を出力できる
    - 複数の `@startuml...@enduml` が存在する場合は、最初の画像だけが生成される

```text:実行結果
> gradle run
...
```

![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/36029dea-e1bc-cb52-f943-12d0320e4be2.png)

- コマンドラインから実行する場合と同じで、環境変数 `GRAPHVIZ_DOT` が設定されている必要がある点に注意

### 複数画像が定義されている場合
```java:Main.java
package sandbox.plantuml;

import net.sourceforge.plantuml.SourceStringReader;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) throws Exception {
        String source = "@startuml FooBar\n"
                      + "Foo <-- Bar\n"
                      + "@enduml\n"
                      + "\n"
                      + "@startuml FizzBuzz\n"
                      + "Fizz <-- Buzz\n"
                      + "@enduml";
        final SourceStringReader reader = new SourceStringReader(source);
        try (
            OutputStream fooBar = new FileOutputStream("foobar.png");
            OutputStream fizzBuzz = new FileOutputStream("fizzbuzz.png");
        ) {
            reader.generateImage(fooBar, 0);
            reader.generateImage(fizzBuzz, 1);
        }
    }
}
```

- `generateImage(OutputStream, int)` を使えば、指定した番号の画像を生成できる
- 画像の番号は 0 はじまりで上からの順番


## ソースファイルから読み込む
```text:フォルダ構成
|-source.pu
|-build.gradle
`-src/main/java/
  `-sandbox/plantuml/
    `-Main.java
```

- `source.pu` ファイルを追加

```text:source.pu
@startuml FooBar
Foo <-- Bar
@enduml

@startuml FizzBuzz
Fizz <-- Buzz
@enduml
```

- ２つの図を定義している

```java:Main.java
package sandbox.plantuml;

import net.sourceforge.plantuml.SourceFileReader;

import java.io.File;

public class Main {

    public static void main(String[] args) throws Exception {
        final SourceFileReader reader = new SourceFileReader(new File("source.pu"));
        reader.getGeneratedImages();
    }
}
```

- `SourceFileReader` でソースファイルを読み込んでいる
- `getGeneratedImages()` を実行すると、画像の生成が行われる

```text:実行結果
> gradle run
...
```

```text:フォルダ構成
|-source.pu
|-FooBar.png
|-FizzBuzz.png
|-build.gradle
`-src/main/java/
  `-sandbox/plantuml/
    `-Main.java
```

**FooBar.png**
![FooBar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/9e40c37f-88d3-ac37-3daa-39b0ca4ffaaa.png)

**FizzBuzz.png**
![FizzBuzz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28302/60a94359-684b-909b-1e92-e28c0883ef26.png)

- コマンドラインから実行したときと同じように、ソースファイルが存在するフォルダに画像が出力される
- `getGeneratedImage()` は、生成された画像ファイルを表す `File` オブジェクトの `List` が返される


# 参考
- [PlantUML - Wikipedia](https://ja.wikipedia.org/wiki/PlantUML)
- [シンプルなテキストファイルで UML が書ける、オープンソースのツール](https://plantuml.com/ja/)
- [General and common command to handle graphic layout in diagrams.](https://plantuml.com/ja/commons)
- [Which fonts are available ?](https://plantuml.com/ja/font)