001package com.streamconverter.examples;
002
003import com.streamconverter.StreamConverter;
004import com.streamconverter.command.IStreamCommand;
005import com.streamconverter.command.impl.csv.CsvNavigateCommand;
006import com.streamconverter.command.impl.json.JsonNavigateCommand;
007import com.streamconverter.command.rule.DatabaseFetchRule;
008import com.streamconverter.path.CSVPath;
009import com.streamconverter.path.TreePath;
010import java.io.ByteArrayInputStream;
011import java.io.ByteArrayOutputStream;
012import java.sql.Connection;
013import java.sql.DriverManager;
014import java.sql.PreparedStatement;
015import java.sql.SQLException;
016
017/**
018 * DatabaseFetchRuleの実用的な使用例デモンストレーション
019 *
020 * <p>このデモでは以下の実用的なシナリオを示します: 1. 顧客IDを顧客名に変換 2. 商品コードを商品名と価格に変換 3. 部署コードを部署名に変換 4.
021 * エラーハンドリング(存在しないIDの処理)
022 */
023public class DatabaseRuleDemo {
024
025  private static final String DB_URL = "jdbc:h2:mem:demo;DB_CLOSE_DELAY=-1";
026
027  public static void main(String[] args) {
028    try {
029      // デモ用データベースの初期化
030      setupDemoDatabase();
031
032      System.out.println("=== DatabaseFetchRule実用例デモ ===\n");
033
034      // シナリオ1: JSON内の顧客IDを顧客名に変換
035      demonstrateCustomerIdConversion();
036
037      // シナリオ2: CSV内の商品コードを商品名に変換
038      demonstrateProductCodeConversion();
039
040      // シナリオ3: 複数のIDを含むJSONの一括変換
041      demonstrateBatchProcessing();
042
043      // シナリオ4: StreamConverterと組み合わせた複雑な処理
044      demonstrateComplexPipeline();
045
046      // シナリオ5: エラーハンドリングの例
047      demonstrateErrorHandling();
048
049    } catch (Exception e) {
050      System.err.println("デモ実行中にエラーが発生しました: " + e.getMessage());
051      e.printStackTrace();
052    }
053  }
054
055  /** デモ用のデータベースセットアップ */
056  private static void setupDemoDatabase() throws SQLException {
057    try (Connection conn = DriverManager.getConnection(DB_URL)) {
058      // テーブル作成
059      conn.prepareStatement(
060              """
061                CREATE TABLE customers (
062                    id INTEGER PRIMARY KEY,
063                    name VARCHAR(100),
064                    email VARCHAR(100),
065                    phone VARCHAR(20)
066                )
067                """)
068          .execute();
069
070      conn.prepareStatement(
071              """
072                CREATE TABLE products (
073                    code VARCHAR(20) PRIMARY KEY,
074                    name VARCHAR(100),
075                    price DECIMAL(10,2),
076                    category VARCHAR(50)
077                )
078                """)
079          .execute();
080
081      conn.prepareStatement(
082              """
083                CREATE TABLE departments (
084                    code VARCHAR(10) PRIMARY KEY,
085                    name VARCHAR(50),
086                    manager VARCHAR(50)
087                )
088                """)
089          .execute();
090
091      // テストデータ挿入
092      insertDemoData(conn);
093
094      System.out.println("✅ デモ用データベースを初期化しました");
095    }
096  }
097
098  private static void insertDemoData(Connection conn) throws SQLException {
099    // 顧客データ
100    PreparedStatement customerStmt =
101        conn.prepareStatement("INSERT INTO customers (id, name, email, phone) VALUES (?, ?, ?, ?)");
102
103    customerStmt.setInt(1, 1001);
104    customerStmt.setString(2, "田中太郎");
105    customerStmt.setString(3, "tanaka@example.com");
106    customerStmt.setString(4, "090-1234-5678");
107    customerStmt.execute();
108
109    customerStmt.setInt(1, 1002);
110    customerStmt.setString(2, "佐藤花子");
111    customerStmt.setString(3, "sato@example.com");
112    customerStmt.setString(4, "090-9876-5432");
113    customerStmt.execute();
114
115    customerStmt.setInt(1, 1003);
116    customerStmt.setString(2, "鈴木一郎");
117    customerStmt.setString(3, "suzuki@example.com");
118    customerStmt.setString(4, "090-5555-7777");
119    customerStmt.execute();
120
121    // 商品データ
122    PreparedStatement productStmt =
123        conn.prepareStatement(
124            "INSERT INTO products (code, name, price, category) VALUES (?, ?, ?, ?)");
125
126    productStmt.setString(1, "LAPTOP001");
127    productStmt.setString(2, "高性能ビジネスノートPC");
128    productStmt.setBigDecimal(3, new java.math.BigDecimal("98000.00"));
129    productStmt.setString(4, "PC");
130    productStmt.execute();
131
132    productStmt.setString(1, "MOUSE001");
133    productStmt.setString(2, "無線光学マウス");
134    productStmt.setBigDecimal(3, new java.math.BigDecimal("2980.00"));
135    productStmt.setString(4, "周辺機器");
136    productStmt.execute();
137
138    productStmt.setString(1, "MONITOR001");
139    productStmt.setString(2, "24インチ液晶ディスプレイ");
140    productStmt.setBigDecimal(3, new java.math.BigDecimal("24800.00"));
141    productStmt.setString(4, "モニター");
142    productStmt.execute();
143
144    // 部署データ
145    PreparedStatement deptStmt =
146        conn.prepareStatement("INSERT INTO departments (code, name, manager) VALUES (?, ?, ?)");
147
148    deptStmt.setString(1, "DEV");
149    deptStmt.setString(2, "開発部");
150    deptStmt.setString(3, "山田部長");
151    deptStmt.execute();
152
153    deptStmt.setString(1, "SALES");
154    deptStmt.setString(2, "営業部");
155    deptStmt.setString(3, "田村部長");
156    deptStmt.execute();
157
158    deptStmt.setString(1, "HR");
159    deptStmt.setString(2, "人事部");
160    deptStmt.setString(3, "川上部長");
161    deptStmt.execute();
162  }
163
164  /** シナリオ1: JSON内の顧客IDを顧客名に変換 */
165  private static void demonstrateCustomerIdConversion() throws Exception {
166    System.out.println("--- シナリオ1: 顧客IDを顧客名に変換 ---");
167
168    // DatabaseFetchRuleの作成
169    DatabaseFetchRule customerRule =
170        new DatabaseFetchRule(DB_URL, "SELECT name FROM customers WHERE id = ?");
171
172    // JsonNavigateCommandの作成
173    JsonNavigateCommand command =
174        new JsonNavigateCommand(TreePath.fromJson("$.customerId"), customerRule);
175
176    // 変換前のJSON
177    String inputJson =
178        """
179            {
180                "orderId": "ORD-2024-001",
181                "customerId": "1001",
182                "orderDate": "2024-01-15",
183                "items": [
184                    {"productCode": "LAPTOP001", "quantity": 1}
185                ],
186                "totalAmount": 98000
187            }
188            """;
189
190    System.out.println("📄 変換前のJSON:");
191    System.out.println(inputJson);
192
193    // 変換実行
194    ByteArrayInputStream input = new ByteArrayInputStream(inputJson.getBytes());
195    ByteArrayOutputStream output = new ByteArrayOutputStream();
196
197    command.execute(input, output);
198
199    System.out.println("✨ 変換後のJSON:");
200    System.out.println(output.toString());
201    System.out.println();
202  }
203
204  /** シナリオ2: CSV内の商品コードを商品名に変換 */
205  private static void demonstrateProductCodeConversion() throws Exception {
206    System.out.println("--- シナリオ2: 商品コードを商品名に変換 ---");
207
208    // DatabaseFetchRuleの作成
209    DatabaseFetchRule productRule =
210        new DatabaseFetchRule(DB_URL, "SELECT name FROM products WHERE code = ?");
211
212    // CsvNavigateCommandの作成
213    CsvNavigateCommand command = new CsvNavigateCommand(new CSVPath("product_code"), productRule);
214
215    // 変換前のCSV
216    String inputCsv =
217        """
218            order_id,customer_id,product_code,quantity,unit_price
219            ORD-001,1001,LAPTOP001,1,98000
220            ORD-002,1002,MOUSE001,2,2980
221            ORD-003,1003,MONITOR001,1,24800
222            """;
223
224    System.out.println("📊 変換前のCSV:");
225    System.out.println(inputCsv);
226
227    // 変換実行
228    ByteArrayInputStream input = new ByteArrayInputStream(inputCsv.getBytes());
229    ByteArrayOutputStream output = new ByteArrayOutputStream();
230
231    command.execute(input, output);
232
233    System.out.println("✨ 変換後のCSV:");
234    System.out.println(output.toString());
235    System.out.println();
236  }
237
238  /** シナリオ3: 複数のIDを含むJSONの一括変換 */
239  private static void demonstrateBatchProcessing() throws Exception {
240    System.out.println("--- シナリオ3: 複数顧客IDの一括変換 ---");
241
242    // DatabaseFetchRuleの作成
243    DatabaseFetchRule customerRule =
244        new DatabaseFetchRule(DB_URL, "SELECT name FROM customers WHERE id = ?");
245
246    // JsonNavigateCommandの作成
247    JsonNavigateCommand command =
248        new JsonNavigateCommand(TreePath.fromJson("$.customerId"), customerRule);
249
250    // 複数の注文を含むJSON
251    String inputJson =
252        """
253            [
254                {
255                    "orderId": "ORD-001",
256                    "customerId": "1001",
257                    "amount": 98000
258                },
259                {
260                    "orderId": "ORD-002",
261                    "customerId": "1002",
262                    "amount": 5960
263                },
264                {
265                    "orderId": "ORD-003",
266                    "customerId": "1003",
267                    "amount": 24800
268                }
269            ]
270            """;
271
272    System.out.println("📄 変換前のJSON配列:");
273    System.out.println(inputJson);
274
275    // 変換実行
276    ByteArrayInputStream input = new ByteArrayInputStream(inputJson.getBytes());
277    ByteArrayOutputStream output = new ByteArrayOutputStream();
278
279    command.execute(input, output);
280
281    System.out.println("✨ 変換後のJSON配列:");
282    System.out.println(output.toString());
283    System.out.println();
284  }
285
286  /** シナリオ4: StreamConverterと組み合わせた複雑な処理 */
287  private static void demonstrateComplexPipeline() throws Exception {
288    System.out.println("--- シナリオ4: 複雑なパイプライン処理 ---");
289
290    // 顧客ID変換ルール
291    DatabaseFetchRule customerRule =
292        new DatabaseFetchRule(DB_URL, "SELECT name FROM customers WHERE id = ?");
293
294    // 部署コード変換ルール
295    DatabaseFetchRule deptRule =
296        new DatabaseFetchRule(DB_URL, "SELECT name FROM departments WHERE code = ?");
297
298    // 複数段階の変換を組み合わせる
299    JsonNavigateCommand customerCommand =
300        new JsonNavigateCommand(TreePath.fromJson("$.customerId"), customerRule);
301    JsonNavigateCommand deptCommand =
302        new JsonNavigateCommand(TreePath.fromJson("$.deptCode"), deptRule);
303
304    // StreamConverterで複数のコマンドを組み合わせ
305    StreamConverter converter =
306        new StreamConverter(new IStreamCommand[] {customerCommand, deptCommand});
307
308    // 変換前のJSON
309    String inputJson =
310        """
311            {
312                "employeeId": "EMP-001",
313                "customerId": "1001",
314                "deptCode": "DEV",
315                "projectName": "新システム開発",
316                "status": "進行中"
317            }
318            """;
319
320    System.out.println("📄 変換前のJSON:");
321    System.out.println(inputJson);
322
323    // パイプライン実行
324    ByteArrayInputStream input = new ByteArrayInputStream(inputJson.getBytes());
325    ByteArrayOutputStream output = new ByteArrayOutputStream();
326
327    converter.run(input, output);
328
329    System.out.println("✨ パイプライン変換後のJSON:");
330    System.out.println(output.toString());
331    System.out.println();
332  }
333
334  /** シナリオ5: エラーハンドリングの例 */
335  private static void demonstrateErrorHandling() throws Exception {
336    System.out.println("--- シナリオ5: エラーハンドリング ---");
337
338    // DatabaseFetchRuleの作成
339    DatabaseFetchRule customerRule =
340        new DatabaseFetchRule(DB_URL, "SELECT name FROM customers WHERE id = ?");
341
342    // JsonNavigateCommandの作成
343    JsonNavigateCommand command =
344        new JsonNavigateCommand(TreePath.fromJson("$.customerId"), customerRule);
345
346    // 存在しない顧客IDを含むJSON
347    String inputJson =
348        """
349            {
350                "orderId": "ORD-9999",
351                "customerId": "9999",
352                "amount": 50000,
353                "note": "存在しない顧客IDのテスト"
354            }
355            """;
356
357    System.out.println("📄 存在しない顧客IDを含むJSON:");
358    System.out.println(inputJson);
359
360    // 変換実行
361    ByteArrayInputStream input = new ByteArrayInputStream(inputJson.getBytes());
362    ByteArrayOutputStream output = new ByteArrayOutputStream();
363
364    command.execute(input, output);
365
366    System.out.println("✨ 変換結果(存在しないIDは空文字列になる):");
367    System.out.println(output.toString());
368
369    System.out.println("💡 DatabaseFetchRuleは存在しないIDに対して空文字列を返し、");
370    System.out.println("   システム全体の安定性を保ちます。");
371    System.out.println();
372  }
373}