# 画面設計書 50-ユーザー実験的機能設定

## 概要

本ドキュメントは、Jenkinsのユーザー実験的機能設定画面（Experiments）の画面設計書です。ユーザーの実験的機能に関連するプロパティを設定するカテゴリ別設定画面について記述します。

### 本画面の処理概要

この画面では、ユーザーの実験的機能に関連するプロパティを一括で設定します。UserPropertyのうち、Experimentalカテゴリに分類されるプロパティがこの画面で設定可能です。ベータ機能やプレビュー機能の有効化などが典型的な設定項目です。

**業務上の目的・背景**：Jenkins 2.468以降、ユーザー設定はカテゴリ別に分離されました。実験的機能を専用画面に集約することで、安定版機能と実験的機能を明確に区別し、ユーザーが意識的に実験的機能を有効化できるようにしています。これにより、予期しない動作変更のリスクを軽減しつつ、新機能のテスト参加が容易になります。

**画面へのアクセス方法**：ユーザー詳細画面のサイドパネルから「Experiments」リンクをクリック、または `/user/{userId}/experiments` にURL直接アクセスします。ADMINISTER権限がない場合、サイドパネルにリンクが表示されません。

**主要な操作・処理内容**：
1. Experimentalカテゴリのプロパティ表示
2. 各プロパティの設定値の編集
3. 設定の保存

**画面遷移**：
- 遷移元：ユーザー詳細画面（/user/{userId}/）、サイドパネル
- 遷移先：ユーザー詳細画面（/user/{userId}/）（保存後）

**権限による表示制御**：ADMINISTER権限を持つユーザーのみがこの画面にアクセスできます。権限がない場合、サイドパネルにリンクが表示されません（getIconFileName()がnullを返す）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | ユーザー管理 | 主機能 | ユーザー実験的機能プロパティの設定 |

## 画面種別

設定

## URL/ルーティング

- **URL**: `/user/{userId}/experiments`
- **Jellyテンプレート**: `core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.jelly`
- **権限**: `Jenkins.ADMINISTER`

## 入出力項目

### 動的プロパティセクション

入力項目は`UserProperty.allByCategoryClass(UserPropertyCategory.Experimental.class)`で取得されるディスクリプターに依存します。

## 表示項目

### ヘッダー部分

| 項目名 | 説明 |
|--------|------|
| タイトル | 「Experiments」（Messages.UserPropertyCategoryExperimentalAction_DisplayName()から取得） |

### プロパティ設定フォーム

| 項目名 | 説明 |
|--------|------|
| 各UserPropertyのconfig.jelly | Experimentalカテゴリの各UserPropertyが提供する設定フォーム |

## イベント仕様

### 1-画面表示

1. 画面アクセス時にADMINISTER権限をチェック
2. getMyCategoryDescriptors()でExperimentalカテゴリのプロパティディスクリプターを取得
3. 各プロパティのconfig.jellyを描画

### 2-設定保存（doConfigSubmit）

1. 「Save」ボタンをクリック
2. POSTリクエストがdoConfigSubmitアクションに送信される
3. 各プロパティの入力値を取得し、reconfigure()またはnewInstance()を呼び出す
4. User.addProperties()で一括更新
5. User.save()で永続化
6. ユーザー詳細画面にリダイレクト（FormApply.success("..")）

## データベース更新仕様

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

| 操作（イベント） | 対象ファイル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 設定保存 | users/{userId}/config.xml | UPDATE | UserPropertyの更新 |

### ファイル別更新項目詳細

#### users/{userId}/config.xml

| 操作 | 要素 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| UPDATE | properties/*/（Experimentalカテゴリ） | フォーム入力値 | 各プロパティのシリアライズ形式に依存 |

## メッセージ仕様

| 種別 | メッセージ | 発生条件 |
|------|----------|----------|
| タイトル | Experiments | 画面タイトル（Messagesから取得） |

## 例外処理

| 状態 | 処理 |
|------|------|
| 権限不足 | サイドパネルにリンク非表示、直接アクセス時は403エラー |
| バリデーションエラー | エラーメッセージを表示し、フォームを再表示 |

## 備考

- このアクションクラスはExtension(ordinal = 100)で登録されており、サイドパネルでの表示順序は100です（最も低い順序）
- シンボル名は`@Symbol("experimental")`で「experimental」です
- アイコンは`symbol-flask`が使用されます
- 共通の基底クラス`UserPropertyCategoryAction`がフォーム処理を提供します
- 実験的機能は将来のバージョンで変更または削除される可能性があります

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

ユーザープロパティとカテゴリの関係を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | UserProperty.java | `core/src/main/java/hudson/model/UserProperty.java` | UserPropertyの基本構造 |
| 1-2 | UserPropertyCategory.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java` | カテゴリ分類の仕組み |

**読解のコツ**: `UserPropertyCategory.Experimental`クラスがExperimentalカテゴリを定義し、各`UserPropertyDescriptor`がカテゴリに属します。

#### Step 2: エントリーポイントを理解する

アクションクラスの構造を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | UserPropertyCategoryAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java` | 基底クラス、doConfigSubmit実装 |
| 2-2 | UserPropertyCategoryExperimentalAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java` | Experimentalカテゴリ固有実装 |
| 2-3 | index.jelly | `core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.jelly` | 画面テンプレート |

**主要処理フロー**:
1. **getMyCategoryDescriptors()**: `UserProperty.allByCategoryClass(UserPropertyCategory.Experimental.class)`でカテゴリフィルタ
2. **doConfigSubmit()**: 基底クラスで共通処理
3. **getUrlName()**: "experiments"を返す

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

```
ブラウザ (index.jelly)
    |
    +-- getMyCategoryDescriptors()
    |      |
    |      +-- UserProperty.allByCategoryClass(Experimental.class)
    |
    +-- [POST] doConfigSubmit()
           |
           +-- UserPropertyCategoryAction.doConfigSubmit()
                  |
                  +-- foreach descriptor:
                  |      +-- user.getProperty(descriptor.clazz)
                  |      +-- property.reconfigure() または descriptor.newInstance()
                  |
                  +-- user.addProperties(props)
                  +-- user.save()
                  +-- FormApply.success("..")
```

### データフロー図

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

フォーム入力値 ──────> doConfigSubmit() ───────────────> config.xml更新
                              |
                              +-- プロパティ再構成
                              +-- user.addProperties()
                              +-- user.save()
                              |
                              +────────────────────────> リダイレクト（..）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| UserPropertyCategoryExperimentalAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java` | ソース | 実験的機能カテゴリアクション |
| UserPropertyCategoryAction.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java` | ソース | カテゴリアクション基底クラス |
| index.jelly | `core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.jelly` | テンプレート | 画面表示 |
| UserProperty.java | `core/src/main/java/hudson/model/UserProperty.java` | ソース | ユーザープロパティ基底クラス |
| UserPropertyCategory.java | `core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java` | ソース | カテゴリ定義 |
