1 package org.dbunit.dataset;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.dbunit.dataset.datatype.DataType;
7
8 /**
9 * Fluent builder for creating {@link IDataSet} instances programmatically,
10 * reducing XML file dependencies in unit tests.
11 *
12 * <p>Single-table example:
13 * <pre>
14 * IDataSet ds = new DataSetBuilder()
15 * .table("FOO")
16 * .columns("ID", "NAME")
17 * .row(1, "Alice")
18 * .row(2, "Bob")
19 * .build();
20 * </pre>
21 *
22 * <p>Multi-table example:
23 * <pre>
24 * IDataSet ds = new DataSetBuilder()
25 * .table("FOO")
26 * .columns("ID", "NAME")
27 * .row(1, "Alice")
28 * .table("BAR")
29 * .columns("X")
30 * .row(42)
31 * .build();
32 * </pre>
33 *
34 * @since 3.2.0
35 */
36 public class DataSetBuilder
37 {
38 private final List<TableConfig> tableConfigs = new ArrayList<>();
39
40 /**
41 * Starts configuring a new table with the given name.
42 *
43 * @param name the table name
44 * @return a {@link TableBuilder} for configuring columns and rows
45 */
46 public TableBuilder table(final String name)
47 {
48 final TableConfig config = new TableConfig(name);
49 tableConfigs.add(config);
50 return new TableBuilder(config);
51 }
52
53 /**
54 * Builds and returns an {@link IDataSet} containing all configured tables.
55 *
56 * @return the dataset
57 * @throws DataSetException if any table configuration is invalid
58 */
59 public IDataSet build() throws DataSetException
60 {
61 final List<DefaultTable> tables = new ArrayList<>();
62 for (final TableConfig config : tableConfigs)
63 {
64 tables.add(config.buildTable());
65 }
66 return new DefaultDataSet(tables.toArray(new DefaultTable[0]));
67 }
68
69 /**
70 * Fluent builder for a single table within a {@link DataSetBuilder}.
71 */
72 public class TableBuilder
73 {
74 private final TableConfig config;
75
76 private TableBuilder(final TableConfig config)
77 {
78 this.config = config;
79 }
80
81 /**
82 * Sets the column names for this table. Column data types are set to
83 * {@link DataType#UNKNOWN} and resolved at runtime by DbUnit.
84 *
85 * @param names the column names in order
86 * @return this builder
87 */
88 public TableBuilder columns(final String... names)
89 {
90 config.setColumnNames(names);
91 return this;
92 }
93
94 /**
95 * Adds a row of values to this table. Values must be in the same order
96 * as the columns declared via {@link #columns(String...)}.
97 *
98 * @param values the row values
99 * @return this builder
100 */
101 public TableBuilder row(final Object... values)
102 {
103 config.addRow(values);
104 return this;
105 }
106
107 /**
108 * Starts configuring another table, finalizing this one.
109 *
110 * @param name the next table name
111 * @return a new {@link TableBuilder} for the next table
112 */
113 public TableBuilder table(final String name)
114 {
115 return DataSetBuilder.this.table(name);
116 }
117
118 /**
119 * Builds and returns an {@link IDataSet} containing all configured tables.
120 *
121 * @return the dataset
122 * @throws DataSetException if any table configuration is invalid
123 */
124 public IDataSet build() throws DataSetException
125 {
126 return DataSetBuilder.this.build();
127 }
128 }
129
130 private static class TableConfig
131 {
132 private final String name;
133 private String[] columnNames = new String[0];
134 private final List<Object[]> rows = new ArrayList<>();
135
136 TableConfig(final String name)
137 {
138 this.name = name;
139 }
140
141 void setColumnNames(final String[] names)
142 {
143 columnNames = names;
144 }
145
146 void addRow(final Object[] values)
147 {
148 rows.add(values);
149 }
150
151 DefaultTable buildTable() throws DataSetException
152 {
153 final Column[] columns = new Column[columnNames.length];
154 for (int i = 0; i < columnNames.length; i++)
155 {
156 columns[i] = new Column(columnNames[i], DataType.UNKNOWN);
157 }
158 final DefaultTable table = new DefaultTable(name, columns);
159 for (final Object[] row : rows)
160 {
161 table.addRow(row);
162 }
163 return table;
164 }
165 }
166 }