1 package guru.mikelue.jdut.datagrain;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.function.Consumer;
10 import java.util.function.Function;
11 import java.util.function.Supplier;
12 import java.util.stream.Collectors;
13 import java.util.stream.Stream;
14
15 import org.apache.commons.lang3.Validate;
16
17 import guru.mikelue.jdut.decorate.DataGrainDecorator;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 public class DataGrain {
59 private List<DataRow> rows;
60
61
62
63
64
65
66
67
68
69 public static DataGrain build(
70 Consumer<SchemaTable.Builder> tableBuilderConsumer,
71 Consumer<RowsBuilder> rowsBuilderConsumer
72 ) {
73 RowsBuilderImpl rowsBuilder = new RowsBuilderImpl(
74 SchemaTable.build(tableBuilderConsumer)
75 );
76
77 rowsBuilderConsumer.accept(rowsBuilder);
78 return new DataGrain(rowsBuilder.toDataRows());
79 }
80
81
82
83
84
85
86 public DataGrain(List<DataRow> rows)
87 {
88 this.rows = Collections.unmodifiableList(rows);
89 Validate.notNull(rows, "Need viable rows");
90 }
91
92
93
94
95
96
97
98
99
100
101 public DataRow getRow(int index)
102 {
103 Validate.inclusiveBetween(0, rows.size() - 1, index, "The index is invalid: [%d]", index);
104 return rows.get(index);
105 }
106
107
108
109
110
111
112
113
114 public int getNumberOfRows()
115 {
116 return rows.size();
117 }
118
119
120
121
122
123
124 public List<DataRow> getRows()
125 {
126 return rows;
127 }
128
129
130
131
132
133
134
135
136 public DataGrain decorate(final DataGrainDecorator decorator)
137 {
138 final List<DataRow> decoratedRows = new ArrayList<>(rows.size());
139 rows.forEach(
140 row -> decoratedRows.add(DataRow.build(
141 builder -> decorator.decorate(builder),
142 row
143 ))
144 );
145
146 return new DataGrain(decoratedRows);
147 }
148
149
150
151
152
153
154
155
156 public DataGrain../../../guru/mikelue/jdut/datagrain/DataGrain.html#DataGrain">DataGrain aggregate(DataGrain dataGrain)
157 {
158 List<DataRow> result = new ArrayList<>(getRows());
159 result.addAll(dataGrain.getRows());
160
161 return new DataGrain(result);
162 }
163
164
165
166
167
168
169 public DataGrain reverse()
170 {
171 List<DataRow> reversedRows = new ArrayList<>(rows);
172 Collections.reverse(reversedRows);
173
174 return new DataGrain(reversedRows);
175 }
176 }
177
178
179
180
181 class RowsBuilderImpl implements RowsBuilder {
182 private final SchemaTable tableSchema;
183 private final DataField.Factory fieldFactory;
184 private List<Map<String, DataField<?>>> rows = new ArrayList<>(CollectionUsage.LIST_SIZE_OF_ROWS);
185 private Map<String, SchemaColumn> columns = new HashMap<>(CollectionUsage.HASH_SPACE_OF_COLUMNS);
186 private Map<Integer, SchemaColumn> columnsOfIndexed;
187
188 RowsBuilderImpl(SchemaTable newTableSchema)
189 {
190 tableSchema = newTableSchema;
191 fieldFactory = new DataField.Factory(tableSchema);
192 }
193
194 @Override
195 public RowsBuilder implicitColumns(String... nameOfColumns)
196 {
197 columnsOfIndexed = new HashMap<>(CollectionUsage.HASH_SPACE_OF_COLUMNS);
198
199 Arrays.asList(nameOfColumns)
200 .forEach(new Consumer<String>() {
201 int index = 1;
202
203 @Override
204 public void accept(String columnName)
205 {
206 if (!columns.containsKey(columnName)) {
207 columns.put(
208 columnName,
209 SchemaColumn.build(builder -> builder.name(columnName))
210 );
211 }
212
213 columnsOfIndexed.put(index++, columns.get(columnName));
214 }
215 });
216
217 return this;
218 }
219
220 @Override
221 public RowsBuilder addValues(Object... valuesOfField)
222 {
223 return add(
224 Stream.of(valuesOfField)
225 .map(
226 new Function<Object, DataField<Object>>() {
227 int index = 1;
228
229 @Override
230 public DataField<Object> apply(Object value)
231 {
232 return fieldFactory.composeData(
233 columnsOfIndexed.get(index++), value
234 );
235 }
236 }
237 )
238 );
239 }
240 @Override
241 public RowsBuilder addFields(DataField<?>... dataFields)
242 {
243 return add(Stream.of(dataFields));
244 }
245 @Override
246 public <T> DataField<T> newField(String columnName, T fieldValue)
247 {
248 if (!columns.containsKey(columnName)) {
249 columns.put(columnName, SchemaColumn.build(builder -> builder.name(columnName)));
250 }
251
252 return fieldFactory.composeData(
253 columns.get(columnName), fieldValue
254 );
255 }
256 @Override
257 public <T> DataField<T> newField(String columnName, Supplier<T> fieldSupplier)
258 {
259 if (!columns.containsKey(columnName)) {
260 columns.put(columnName, SchemaColumn.build(builder -> builder.name(columnName)));
261 }
262
263 return fieldFactory.composeDataSupplier(
264 columns.get(columnName), fieldSupplier
265 );
266 }
267
268 private RowsBuilder add(Stream<DataField<?>> dataFields)
269 {
270 rows.add(
271 dataFields
272 .map(dataField -> dataField.asMapEntry())
273 .collect(Collectors.toMap(
274 entry -> entry.getKey(),
275 entry -> entry.getValue()
276 ))
277 );
278
279 return this;
280 }
281
282 List<DataRow> toDataRows()
283 {
284 final List<DataRow> result = new ArrayList<>(rows.size());
285 rows.forEach(
286 fieldMap -> result.add(
287 DataRow.build(builder -> builder
288 .tableSchema(tableSchema)
289 .data(fieldMap)
290 )
291 )
292 );
293
294 return result;
295 }
296 }