# 機能設計書 100-FileLoader

## 概要

本ドキュメントは、Three.jsライブラリにおける汎用ファイルローダー機能（FileLoader）の設計仕様を記述したものである。

### 本機能の処理概要

FileLoaderは、Fetch APIを使用した低レベルのファイル読み込み機能を提供する。ほとんどのローダーが内部で使用する基盤コンポーネントであり、任意のファイルタイプを読み込むことができる。キャッシング機能、重複リクエストの排除、進捗追跡、リクエスト中断をサポートする。

**業務上の目的・背景**：3Dアプリケーションでは様々な形式のファイル（JSON、バイナリ、テキスト、XML等）を読み込む必要がある。FileLoaderはこれらの基盤となる汎用読み込み機能を提供し、キャッシュによる効率化、重複リクエストの排除、読み込み進捗の追跡を実現する。

**機能の利用シーン**：
- JSONファイルの読み込み
- バイナリファイル（ArrayBuffer）の読み込み
- テキストファイルの読み込み
- XMLドキュメントの読み込み
- カスタムファイル形式の読み込み
- Data URIからのデータ取得

**主要な処理内容**：
1. URL解決とキャッシュチェック
2. 重複リクエストの検出と統合
3. Fetch APIによるHTTPリクエスト
4. ReadableStreamを使用した進捗追跡
5. レスポンスタイプに応じたデータ変換
6. キャッシュへの保存
7. コールバックの実行

**関連システム・外部連携**：LoadingManager、Cache、Fetch API

**権限による制御**：withCredentialsによる認証情報の送信制御

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | Menubar - File | 主機能 | プロジェクトファイルの読み込み |

## 機能種別

リソース読み込み / ファイルI/O

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | string | Yes | 読み込むファイルのURL/パス（Data URIも可） | 有効なURL文字列 |
| onLoad | Function | No | 読み込み完了時コールバック | 関数 |
| onProgress | Function | No | 進捗コールバック | 関数 |
| onError | Function | No | エラー時コールバック | 関数 |

### 入力データソース

HTTPサーバー、ローカルファイル、Data URI

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | any | 読み込んだデータ（responseTypeに応じて変換済み） |
| mimeType | string | レスポンスのMIMEタイプ |
| responseType | string | レスポンスタイプ（arraybuffer/blob/document/json/''） |

### 出力先

onLoadコールバック、またはloadAsync()のPromise解決値

## 処理フロー

### 処理シーケンス

```
1. load()呼び出し
   └─ URL解決（path連結、manager.resolveURL）
2. キャッシュチェック
   └─ キャッシュヒット時は即座にonLoadコールバック
3. 重複リクエストチェック
   └─ 重複時はコールバックを登録して終了
4. Fetch APIでリクエスト
   └─ RequestヘッダーとAbortSignalを設定
5. レスポンス処理
   └─ ステータスコードチェック
   └─ ReadableStreamで進捗追跡
6. データ変換
   └─ responseTypeに応じた変換
7. キャッシュ保存
8. コールバック実行
   └─ 重複リクエストのコールバックも実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始: load] --> B[URL解決]
    B --> C{キャッシュヒット?}
    C -->|Yes| D[キャッシュからonLoad]
    C -->|No| E{重複リクエスト?}
    E -->|Yes| F[コールバック登録]
    E -->|No| G[Fetch API リクエスト]
    G --> H{ステータス OK?}
    H -->|Yes| I[ReadableStream 処理]
    H -->|No| J[HttpError スロー]
    I --> K[進捗コールバック]
    K --> L[データ変換]
    L --> M[キャッシュ保存]
    M --> N[onLoad コールバック]
    J --> O[onError コールバック]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-100-01 | キャッシュ利用 | Cache.enabled = trueの場合のみキャッシュを使用 | 常時 |
| BR-100-02 | 重複排除 | 同一URLへの同時リクエストは統合 | 同時リクエスト時 |
| BR-100-03 | HTTPステータス | 200またはステータス0（file://等）を成功とみなす | 常時 |
| BR-100-04 | 進捗追跡 | Content-LengthまたはX-File-Sizeヘッダーで進捗計算 | 常時 |
| BR-100-05 | データ変換 | responseTypeに応じてarrayBuffer/blob/json/text等に変換 | 常時 |

### 計算ロジック

進捗率計算:
```javascript
const lengthComputable = total !== 0;
let loaded = 0;
// チャンク受信時
loaded += value.byteLength;
const event = new ProgressEvent('progress', { lengthComputable, loaded, total });
```

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| HttpError | HTTPエラー | レスポンスステータスが200/0以外 | URLとサーバー設定を確認 |
| AbortError | 中断 | abort()呼び出し | 意図的な中断 |
| TypeError | ネットワークエラー | 接続失敗 | ネットワーク状態を確認 |

### リトライ仕様

FileLoader自体はリトライ機能を持たない。必要に応じてアプリケーション側で実装。

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

該当なし

## パフォーマンス要件

- キャッシュ有効時は重複読み込みを排除
- ReadableStreamによる効率的なメモリ使用

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

- withCredentialsはクロスオリジン時の認証に影響
- AbortSignal.any()のブラウザサポートに注意

## 備考

- Cache.enabled = trueでキャッシング有効化
- responseTypeで読み込み形式を指定可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Cache.js | `src/loaders/Cache.js` | キャッシュの仕組みを理解 |
| 1-2 | Loader.js | `src/loaders/Loader.js` | 基底クラスのプロパティを確認 |
| 1-3 | LoadingManager.js | `src/loaders/LoadingManager.js` | 進捗管理の仕組みを理解 |

**読解のコツ**: FileLoaderはモジュールスコープの`loading`オブジェクトで重複リクエストを管理している点に注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FileLoader.js | `src/loaders/FileLoader.js` | load()メソッドの全体フローを確認 |

**主要処理フロー**:
1. **5行目**: `loading = {}`（モジュールスコープの重複管理オブジェクト）
2. **7-16行目**: HttpErrorクラス定義（カスタムエラー）
3. **33行目**: クラス定義開始 `class FileLoader extends Loader`
4. **50行目**: mimeType = ''（MIME タイプ設定）
5. **58行目**: responseType = ''（レスポンスタイプ設定）
6. **66行目**: _abortController（中断制御）
7. **79行目**: load()メソッド開始
8. **81-85行目**: URL解決（path連結、resolveURL）
9. **87-103行目**: キャッシュチェックと即時返却
10. **107-119行目**: 重複リクエスト検出とコールバック登録
11. **121-128行目**: コールバック配列初期化
12. **131-135行目**: Requestオブジェクト作成（ヘッダー、credentials、AbortSignal）
13. **142-225行目**: fetch()とレスポンス処理
14. **145-155行目**: ステータスコードチェック
15. **158-217行目**: ReadableStream処理と進捗追跡
16. **226-269行目**: responseTypeに応じたデータ変換
17. **272-286行目**: キャッシュ保存とonLoadコールバック
18. **289-314行目**: エラー処理とonErrorコールバック
19. **315-319行目**: finally処理（itemEnd）
20. **331-336行目**: setResponseType()メソッド
21. **344-349行目**: setMimeType()メソッド
22. **356-363行目**: abort()メソッド

#### Step 3: データ変換処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileLoader.js | `src/loaders/FileLoader.js` | 226-269行目のswitch文を確認 |

**データ変換処理**:
- `arraybuffer`: response.arrayBuffer()
- `blob`: response.blob()
- `document`: response.text() → DOMParser.parseFromString()
- `json`: response.json()
- デフォルト: response.text()（mimeType指定時はTextDecoderで変換）

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

```
FileLoader.load(url, onLoad, onProgress, onError)
    │
    ├─ URL解決
    │      ├─ this.path + url
    │      └─ manager.resolveURL()
    │
    ├─ Cache.get() [キャッシュチェック]
    │
    ├─ loading[url] [重複チェック]
    │
    ├─ fetch(Request)
    │      │
    │      ├─ Headers
    │      │
    │      ├─ credentials
    │      │
    │      └─ AbortSignal.any()
    │
    ├─ ReadableStream処理
    │      └─ onProgressコールバック
    │
    ├─ データ変換
    │      └─ responseTypeに応じた処理
    │
    ├─ Cache.add() [キャッシュ保存]
    │
    └─ onLoad/onError コールバック
```

### データフロー図

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

URL                  ───▶  FileLoader.load()         ───▶  変換済みデータ
                           │
                           ├─ キャッシュ確認
                           │      └─ Cache.get()
                           │
                           ├─ 重複リクエスト統合
                           │      └─ loading[url]
                           │
                           ├─ Fetch API
                           │      └─ ReadableStream
                           │             └─ onProgress
                           │
                           ├─ データ変換
                           │      └─ responseType
                           │
                           └─ キャッシュ保存
                                  └─ Cache.add()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FileLoader.js | `src/loaders/FileLoader.js` | ソース | 汎用ファイルローダー |
| Loader.js | `src/loaders/Loader.js` | ソース | ローダー基底クラス |
| LoadingManager.js | `src/loaders/LoadingManager.js` | ソース | 読み込み管理 |
| Cache.js | `src/loaders/Cache.js` | ソース | キャッシュ管理 |
| utils.js | `src/utils.js` | ソース | warn関数 |
