1. Project Clover database Wed Nov 12 2025 05:07:35 UTC
  2. Package guru.mikelue.foxglove.jdbc

File CartesianProductBuilder.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

10
41
8
1
143
91
13
0.32
5.12
8
1.62

Classes

Class Line # Actions
CartesianProductBuilder 10 41 0% 13 0
1.0100%
 

Contributing tests

This file is covered by 20 tests. .

Source view

1    package guru.mikelue.foxglove.jdbc;
2   
3    import java.util.*;
4    import java.util.function.Supplier;
5   
6    import guru.mikelue.foxglove.functional.RoundRobinValueSupplier;
7   
8    import static guru.mikelue.foxglove.functional.Suppliers.lazySupplier;
9   
 
10    class CartesianProductBuilder {
11    private Map<String, Supplier<List<?>>> domainProviders = new LinkedHashMap<>(2);
12    // As the suppliers for expanded values
13    private Map<String, List<?>> finalValues;
14    private int numberOfRows = -1;
15   
 
16  20 toggle CartesianProductBuilder() {}
17   
 
18  37 toggle <T> void putDomain(String columnName, Supplier<List<T>> supplierOfValues)
19    {
20  37 @SuppressWarnings("unchecked")
21    var newSupplier = (Supplier<List<?>>)(Supplier<?>)supplierOfValues;
22   
23  37 domainProviders.put(columnName, newSupplier);
24    }
25   
 
26  23 toggle int getNumberOfRows()
27    {
28  23 init();
29  23 return numberOfRows;
30    }
31   
 
32  30 toggle boolean isExisting(String columnName)
33    {
34  30 return domainProviders.containsKey(columnName);
35    }
36   
 
37  17 toggle List<String> getColumnNames()
38    {
39  17 return new ArrayList<>(domainProviders.keySet());
40    }
41   
 
42  32 toggle @SuppressWarnings("unchecked")
43    <T> Supplier<T> buildLazySupplier(String columnName)
44    {
45  32 return lazySupplier(() -> {
46  32 init();
47   
48  32 var values = (List<T>)finalValues.get(columnName);
49  32 return RoundRobinValueSupplier.of(values);
50    });
51    }
52   
 
53  55 toggle private void init()
54    {
55  55 if (finalValues != null) {
56  38 return;
57    }
58   
59  17 finalValues = new HashMap<>(domainProviders.size());
60   
61    /*
62    * Builds the source of domain values and calculate repeating times for each column.
63    */
64  17 Map<String, List<?>> sourceValues = new HashMap<>(domainProviders.size());
65  17 domainProviders.entrySet().stream()
66    .forEach(entry ->
67    sourceValues.put(
68    entry.getKey(),
69    entry.getValue().get()
70    )
71    );
72   
73  17 var expandedSizesOfRestColumns = new HashMap<String, Integer>(domainProviders.size());
74  17 numberOfRows = buildProductNumberOfRestColumns(sourceValues, expandedSizesOfRestColumns);
75    // :~)
76   
77  17 for (var columnName: domainProviders.keySet()) {
78  34 var sourceValuesOfCurrentColumn = sourceValues.get(columnName);
79  34 int repeatedTimes = expandedSizesOfRestColumns.get(columnName);;
80   
81  34 var expandedValuesOfCurrentColumn = new ArrayList<Object>(numberOfRows);
82   
83    /*
84    * Adds all of the values for current column
85    * by pre-calculating the number of repetitions.
86    */
87  111 for (int i = 0; i < numberOfRows;) {
88  77 for (var v: sourceValuesOfCurrentColumn) {
89    /*
90    * Adds the same number of supplierOfValues corresponding to
91    * Cartesian product of rest columns.
92    */
93  796 for (int t = 0; t < repeatedTimes; t++) {
94  499 expandedValuesOfCurrentColumn.add(v);
95    }
96    // :~)
97   
98  297 i += repeatedTimes;
99    }
100    }
101    // :~)
102   
103  34 finalValues.put(
104    columnName, expandedValuesOfCurrentColumn
105    );
106    }
107    }
108   
 
109  17 toggle private int buildProductNumberOfRestColumns(
110    Map<String, List<?>> sourceValues, Map<String, Integer> expandedSizes
111    ) {
112  17 var productNumberOfRows = 1;
113  17 var columnNames = new ArrayList<>(sourceValues.keySet());
114   
115    /*
116    * Caches the number of rows for Cartesian product for
117    * rest of columns on every column.
118    */
119  51 for (var i = sourceValues.size() - 1; i >= 0; i--) {
120  34 var currentColumnName = columnNames.get(i);
121  34 var sizeOfCurrentColumn = sourceValues.get(currentColumnName).size();
122  34 productNumberOfRows *= sizeOfCurrentColumn;
123   
124  34 if (i == sourceValues.size() - 1) {
125  17 expandedSizes.put(currentColumnName, 1);
126  17 continue;
127    }
128   
129  17 var nextColumnName = columnNames.get(i + 1);
130   
131    /*
132    * Calculates the number of rows for rest of columns.
133    *
134    * This is used to optimize the building of expanded supplierOfValues.
135    */
136  17 var productSizeOfCurrentColumn = expandedSizes.get(nextColumnName) * sourceValues.get(nextColumnName).size();
137  17 expandedSizes.put(currentColumnName, productSizeOfCurrentColumn);
138    // :~)
139    }
140   
141  17 return productNumberOfRows;
142    }
143    }