Add method buildCrossProduct to help build cross products

This commit is contained in:
2025-07-14 16:04:34 -05:00
parent ec697d7f0f
commit fc197efd74
2 changed files with 66 additions and 2 deletions

View File

@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.model.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -257,4 +258,39 @@ public class QRecordWithJoinedRecords extends QRecord
return (this);
}
/***************************************************************************
* Given an object of this type (`this`), add a list of join-records to it,
* producing a new list, which is `this` × joinRecordList.
* One may want to use this in a loop to build a larger cross product - more
* to come here in that spirit.
* @param joinTable name of the join table (e.g., to prefix the join fields)
* @param joinRecordList list of join records. may not be null. may be 0+ size.
* @return list of new QRecordWithJoinedRecords, based on `this` with each
* joinRecord added (e.g., output list is same size as joinRecordList).
* Note that does imply an 'inner' style join - where - if the joinRecordList
* is empty, you'll get back an empty list!
***************************************************************************/
public List<QRecordWithJoinedRecords> buildCrossProduct(String joinTable, List<QRecord> joinRecordList)
{
List<QRecordWithJoinedRecords> rs = new ArrayList<>();
for(QRecord joinRecord : joinRecordList)
{
/////////////////////////////////////////////////////////////
// essentially clone the existing QRecordWithJoinedRecords //
/////////////////////////////////////////////////////////////
QRecordWithJoinedRecords newRecord = new QRecordWithJoinedRecords(mainRecord);
components.forEach((k, v) -> newRecord.addJoinedRecordValues(k, v));
///////////////////////////////////////////
// now add the new join record to it too //
///////////////////////////////////////////
newRecord.addJoinedRecordValues(joinTable, joinRecord);
rs.add(newRecord);
}
return (rs);
}
}

View File

@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.data;
import java.time.LocalDate;
import java.time.Month;
import java.util.List;
import com.kingsrook.qqq.backend.core.BaseTest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -41,8 +42,8 @@ class QRecordWithJoinedRecordsTest extends BaseTest
@Test
void test()
{
QRecord order = new QRecord().withValue("id", 1).withValue("orderNo", "101").withValue("orderDate", LocalDate.of(2025, Month.JANUARY, 1));
QRecord lineItem = new QRecord().withValue("id", 2).withValue("sku", "ABC").withValue("quantity", 47);
QRecord order = new QRecord().withValue("id", 1).withValue("orderNo", "101").withValue("orderDate", LocalDate.of(2025, Month.JANUARY, 1));
QRecord lineItem = new QRecord().withValue("id", 2).withValue("sku", "ABC").withValue("quantity", 47);
QRecord extrinsic = new QRecord().withValue("id", 3).withValue("key", "MyKey").withValue("value", "MyValue");
QRecordWithJoinedRecords joinedRecords = new QRecordWithJoinedRecords(order);
@ -73,4 +74,31 @@ class QRecordWithJoinedRecordsTest extends BaseTest
assertEquals("St. Louis", order.getValue("shipToCity"));
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testBuildCrossProduct()
{
QRecord order = new QRecord().withValue("id", 1).withValue("orderNo", "101").withValue("orderDate", LocalDate.of(2025, Month.JANUARY, 1));
List<QRecord> lineItems = List.of(
new QRecord().withValue("id", 2).withValue("sku", "ABC").withValue("quantity", 47),
new QRecord().withValue("id", 3).withValue("sku", "DEF").withValue("quantity", 42),
new QRecord().withValue("id", 4).withValue("sku", "XYZ").withValue("quantity", 1024)
);
QRecordWithJoinedRecords joinedRecords = new QRecordWithJoinedRecords(order);
List<QRecordWithJoinedRecords> crossProduct = joinedRecords.buildCrossProduct("lineItem", lineItems);
assertEquals(3, crossProduct.size());
assertEquals("101", crossProduct.get(0).getValue("orderNo"));
assertEquals("ABC", crossProduct.get(0).getValue("lineItem.sku"));
assertEquals("101", crossProduct.get(1).getValue("orderNo"));
assertEquals("DEF", crossProduct.get(1).getValue("lineItem.sku"));
assertEquals("101", crossProduct.get(2).getValue("orderNo"));
assertEquals("XYZ", crossProduct.get(2).getValue("lineItem.sku"));
}
}