# 機能設計書 35-ビュー管理

## 概要

本ドキュメントは、Jenkinsにおけるビュー管理機能の設計を記載したものである。ビュー管理機能は、ジョブの表示とグルーピングを担当し、Jenkinsのユーザーインターフェースの中核を構成する。

### 本機能の処理概要

本機能は、Jenkinsのジョブを論理的にグループ化し、ユーザーに見やすい形で表示するための仕組みを提供する。

**業務上の目的・背景**：大規模なJenkins環境では数百〜数千のジョブが存在することがあり、全てのジョブを一覧表示すると非効率である。ビュー機能により、プロジェクト、チーム、環境（本番/ステージング）などの観点でジョブをグループ化し、関連するジョブのみを表示できる。これにより、ユーザーは自分に関係するジョブを素早く見つけ、効率的に作業できる。

**機能の利用シーン**：
- プロジェクトチームごとに専用のビューを作成
- 本番環境と開発環境のジョブを分けて表示
- 失敗中のジョブのみをフィルタリングして表示
- ユーザー個人用のカスタムビューを作成
- 正規表現でジョブを動的にフィルタリング

**主要な処理内容**：
1. ビューの作成・編集・削除
2. ビューへのジョブの追加・削除
3. ビュー内のジョブ一覧の取得と表示
4. ビューのXMLによるインポート/エクスポート
5. ビューのプロパティ管理

**関連システム・外部連携**：ViewGroupインターフェースを通じてJenkins本体やフォルダプラグインと連携。REST APIを通じて外部システムからのビュー操作が可能。

**権限による制御**：View.CREATE、View.READ、View.CONFIGURE、View.DELETEの各権限で操作を制御。ACLはViewGroupから継承される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | 新しいビューの作成 | 主画面 | ビューの新規作成 |

## 機能種別

UI管理 / ジョブ整理 / グループ化機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | ビュー名 | Jenkins.checkGoodName()で検証 |
| mode | String | Yes（作成時） | ビュータイプ（list、all、myView等） | 有効なViewDescriptor名 |
| description | String | No | ビューの説明 | HTMLを含む場合あり |
| filterExecutors | boolean | No | 関連するエグゼキュータのみ表示 | - |
| filterQueue | boolean | No | 関連するキューアイテムのみ表示 | - |

### 入力データソース

- HTTPリクエスト: StaplerRequest2からフォームデータを取得
- XML: config.xmlからのインポート
- REST API: JSON形式でのビュー定義

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| View | View | ビューオブジェクト |
| items | Collection<TopLevelItem> | ビューに含まれるジョブ一覧 |
| url | String | ビューのURL |
| actions | List<Action> | ビューに関連するアクション |

### 出力先

- HTMLレスポンス: ビュー画面の表示
- JSON/XML: REST APIレスポンス
- 設定ファイル: $JENKINS_HOME/config.xml（トップレベルビューの場合）

## 処理フロー

### 処理シーケンス

```
1. ビュー作成要求受信
   └─ View.create()がPOSTリクエストで呼び出される
2. 名前検証
   └─ Jenkins.checkGoodName()で名前の妥当性を確認
3. 重複チェック
   └─ 同名のビューが存在しないことを確認
4. ビュータイプ解決
   └─ ViewDescriptorからビュータイプを特定
5. ビューインスタンス生成
   └─ descriptor.newInstance()でビューを生成
6. 所有者への登録
   └─ ViewGroupにビューを追加
7. 設定画面へリダイレクト
   └─ 新規ビューの設定ページへ遷移
```

### フローチャート

```mermaid
flowchart TD
    A[ビュー作成要求] --> B[名前検証]
    B --> C{名前有効?}
    C -->|No| D[エラー: 無効な名前]
    C -->|Yes| E{同名ビュー存在?}
    E -->|Yes| F[エラー: 既に存在]
    E -->|No| G{コピー作成?}
    G -->|Yes| H[既存ビューをコピー]
    G -->|No| I{XML送信?}
    I -->|Yes| J[XMLからビュー生成]
    I -->|No| K[ViewDescriptorから生成]
    H --> L[ビューをViewGroupに追加]
    J --> L
    K --> L
    L --> M[設定画面へリダイレクト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | 名前一意性 | 同一ViewGroup内でビュー名は一意 | ビュー作成・リネーム時 |
| BR-35-02 | プライマリビュー | ViewGroupには1つのプライマリビューが必要 | 常時 |
| BR-35-03 | AllView制限 | AllViewは各ViewGroupに1つのみ | AllView作成時 |
| BR-35-04 | 編集不可ビュー | isEditable()=falseのビューは設定変更不可 | AllView等 |
| BR-35-05 | 削除制限 | プライマリビューは削除不可 | ビュー削除時 |

### 計算ロジック

ビューURL生成: `owner.getUrl() + "view/" + Util.rawEncode(viewName) + '/'`

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| ビュー作成 | config.xml | UPDATE | ViewGroup設定にビューを追加 |
| ビュー削除 | config.xml | UPDATE | ViewGroup設定からビューを削除 |
| ビュー更新 | config.xml | UPDATE | ビュー設定を更新 |

### 設定ファイル詳細

#### $JENKINS_HOME/config.xml

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|-----|-----------------|------|
| UPDATE | views | ビューのXML表現 | XStream2でシリアライズ |
| UPDATE | primaryView | プライマリビュー名 | デフォルトビューの指定 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Failure | ビュー名が無効 | 有効な名前を指定 |
| - | FormException | 同名のビューが存在 | 別の名前を使用 |
| - | AccessDeniedException | View.CREATE権限なし | 管理者に権限付与を依頼 |
| 400 | Bad Request | mode指定なし（XMLでもなく） | modeパラメータを指定 |

### リトライ仕様

ビュー操作は冪等ではないため、エラー時は状態を確認してから再試行する必要がある。

## トランザクション仕様

ViewGroup.save()により、所有者の設定全体がアトミックに保存される。ビュー操作の途中で失敗した場合、変更は保存されない。

## パフォーマンス要件

- getItems()は頻繁に呼び出されるため、効率的な実装が必要
- 大量のジョブがある場合もレスポンス時間を確保
- ビュープロパティの遅延初期化でメモリ効率を向上

## セキュリティ考慮事項

- ビュー操作には適切な権限（View.CREATE、View.CONFIGURE等）が必要
- descriptionはHTMLを含む可能性があるため、XSS対策が必要
- config.xmlのインポート時はXXE攻撃対策としてXMLUtils.safeTransformを使用

## 備考

- ViewはExtensionPointであり、プラグインで独自のビュータイプを追加可能
- ViewPropertyで追加のメタデータをビューに付与可能
- TransientViewActionFactoryでビューにアクションを動的に追加可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 基底クラスViewを理解する

ビューの抽象構造と基本的な機能を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | View.java | `core/src/main/java/hudson/model/View.java` | ビューの基本構造 |

**主要処理フロー**:
- **148行目**: Viewクラス定義（AbstractModelObject継承、AccessControlled実装）
- **154-175行目**: フィールド定義（owner, name, description, filterExecutors, filterQueue, properties）
- **194-218行目**: getItems()とgetAllItems() - ビューに含まれるジョブ取得（抽象メソッド）
- **237行目**: contains() - ジョブがビューに含まれるか判定（抽象メソッド）
- **246-261行目**: getViewName()とrename() - ビュー名管理
- **640-644行目**: getACL() - 権限チェック用ACL取得

**読解のコツ**: Viewは抽象クラスであり、具体的な実装はListView、AllView、MyView等のサブクラスで行われる。getItems()は各サブクラスで異なる実装を持つ。

#### Step 2: ビュー作成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | View.java | `core/src/main/java/hudson/model/View.java` | View.create()静的メソッド |

**主要処理フロー**:
- **1155-1205行目**: create() - ビュー作成のエントリーポイント
- **1168-1171行目**: 名前検証とビュー重複チェック
- **1173-1181行目**: XMLからのビュー作成
- **1185-1197行目**: ViewDescriptorからの通常作成
- **1220-1234行目**: copy() - 既存ビューのコピー
- **1241-1251行目**: createViewFromXML() - XMLからのビュー生成

#### Step 3: 権限モデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | View.java | `core/src/main/java/hudson/model/View.java` | 権限定義とACL取得 |

**主要処理フロー**:
- **1125-1132行目**: 権限定義（PERMISSIONS, CREATE, DELETE, CONFIGURE, READ）
- **640-644行目**: getACL() - AuthorizationStrategyからACLを取得

### プログラム呼び出し階層図

```
POST /createView または /view/newView
    │
    └─ View.create(StaplerRequest2, StaplerResponse2, ViewGroup)
           │
           ├─ Jenkins.checkGoodName(name) 名前検証
           │
           ├─ owner.getView(name) 重複チェック
           │
           ├─ [mode="copy"]
           │      └─ View.copy() 既存ビューをコピー
           │
           ├─ [XML送信]
           │      └─ createViewFromXML() XMLからビュー生成
           │
           └─ [通常作成]
                  │
                  ├─ ViewDescriptor.findByName(mode)
                  │
                  └─ descriptor.newInstance(req, json)
                         │
                         └─ ViewGroup.addView(view)
                                │
                                └─ ViewGroup.save()
```

### データフロー図

```
[入力]                      [処理]                           [出力]

name ─────────────────▶ View.create() ─────────────────▶ Viewオブジェクト
mode ─────────────────▶        │                              │
ViewGroup ────────────▶        │                              ▼
                               │                        設定画面へリダイレクト
                    ┌──────────┴──────────┐
                    ▼                     ▼
              名前検証              ViewDescriptor解決
                    │                     │
                    ▼                     ▼
             重複チェック          newInstance()
                    │                     │
                    └──────────┬──────────┘
                               ▼
                        owner.addView()
                               │
                               ▼
                        owner.save()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| View.java | `core/src/main/java/hudson/model/View.java` | ソース | ビューの基底クラス |
| ViewDescriptor.java | `core/src/main/java/hudson/model/ViewDescriptor.java` | ソース | ビュータイプのDescriptor |
| ViewGroup.java | `core/src/main/java/hudson/model/ViewGroup.java` | ソース | ビューのコンテナインターフェース |
| ViewProperty.java | `core/src/main/java/hudson/model/ViewProperty.java` | ソース | ビューの追加プロパティ |
| TransientViewActionFactory.java | `core/src/main/java/hudson/model/TransientViewActionFactory.java` | ソース | 動的アクション生成 |
| ListView.java | `core/src/main/java/hudson/model/ListView.java` | ソース | リストビュー実装 |
| AllView.java | `core/src/main/java/hudson/model/AllView.java` | ソース | 全ジョブ表示ビュー実装 |
| MyView.java | `core/src/main/java/hudson/model/MyView.java` | ソース | ユーザー個人ビュー実装 |
