QQQ-21 add safelyGetPage; add stepType

This commit is contained in:
2022-07-11 09:04:41 -05:00
parent 0afa88bd0c
commit b9ef76da13
6 changed files with 215 additions and 6 deletions

View File

@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback; import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
import com.kingsrook.qqq.backend.core.interfaces.BackendStep; import com.kingsrook.qqq.backend.core.interfaces.BackendStep;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult;
@ -128,14 +129,18 @@ public class RunBackendStepAction
QProcessCallback callback = runBackendStepRequest.getCallback(); QProcessCallback callback = runBackendStepRequest.getCallback();
if(callback == null) if(callback == null)
{ {
throw (new QException("Function is missing values for fields, but no callback was present to request fields from a user")); throw (new QUserFacingException("Missing values for one or more fields",
new QException("Function is missing values for fields, but no callback was present to request fields from a user")));
} }
Map<String, Serializable> fieldValues = callback.getFieldValues(fieldsToGet); Map<String, Serializable> fieldValues = callback.getFieldValues(fieldsToGet);
for(Map.Entry<String, Serializable> entry : fieldValues.entrySet()) if(fieldValues != null)
{ {
runBackendStepRequest.addValue(entry.getKey(), entry.getValue()); for(Map.Entry<String, Serializable> entry : fieldValues.entrySet())
// todo - check to make sure got values back? {
runBackendStepRequest.addValue(entry.getKey(), entry.getValue());
// todo - check to make sure got values back?
}
} }
} }
} }
@ -164,7 +169,8 @@ public class RunBackendStepAction
QProcessCallback callback = runBackendStepRequest.getCallback(); QProcessCallback callback = runBackendStepRequest.getCallback();
if(callback == null) if(callback == null)
{ {
throw (new QException("Function is missing input records, but no callback was present to get a query filter from a user")); throw (new QUserFacingException("Missing input records.",
new QException("Function is missing input records, but no callback was present to request fields from a user")));
} }
queryRequest.setFilter(callback.getQueryFilter()); queryRequest.setFilter(callback.getQueryFilter());

View File

@ -42,6 +42,16 @@ public class QBackendStepMetaData extends QStepMetaData
/*******************************************************************************
**
*******************************************************************************/
public QBackendStepMetaData()
{
setStepType("backend");
}
/******************************************************************************* /*******************************************************************************
** Setter for label ** Setter for label
** **

View File

@ -40,6 +40,16 @@ public class QFrontendStepMetaData extends QStepMetaData
/*******************************************************************************
**
*******************************************************************************/
public QFrontendStepMetaData()
{
setStepType("frontend");
}
/******************************************************************************* /*******************************************************************************
** Getter for formFields ** Getter for formFields
** **

View File

@ -25,17 +25,21 @@ package com.kingsrook.qqq.backend.core.model.metadata.processes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.serialization.QStepMetaDataDeserializer;
/******************************************************************************* /*******************************************************************************
** Meta-Data to define a step in a process in a QQQ instance. ** Meta-Data to define a step in a process in a QQQ instance.
** **
*******************************************************************************/ *******************************************************************************/
@JsonDeserialize(using = QStepMetaDataDeserializer.class)
public class QStepMetaData public class QStepMetaData
{ {
private String name; private String name;
private String label; private String label;
private String stepType;
@ -127,4 +131,25 @@ public class QStepMetaData
return (new ArrayList<>()); return (new ArrayList<>());
} }
/*******************************************************************************
** Getter for stepType
**
*******************************************************************************/
public String getStepType()
{
return stepType;
}
/*******************************************************************************
** Setter for stepType
**
*******************************************************************************/
public void setStepType(String stepType)
{
this.stepType = stepType;
}
} }

View File

@ -22,6 +22,7 @@
package com.kingsrook.qqq.backend.core.utils; package com.kingsrook.qqq.backend.core.utils;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -332,4 +333,77 @@ public class CollectionUtils
return (rs.toString()); return (rs.toString());
} }
/*******************************************************************************
** Get a sub-list, safely - i.e., w/o worrying if your indexes are too big.
*******************************************************************************/
public static <T> List<T> safelyGetPage(List<T> list, Integer skip, Integer limit)
{
//////////////////////////////////////////////////////////
// throw if the user requested a negative skip or limit //
//////////////////////////////////////////////////////////
if(skip != null && skip < 0)
{
throw (new IllegalArgumentException("Skip may not be negative (was " + skip + ")"));
}
if(limit != null && limit < 0)
{
throw (new IllegalArgumentException("Limit may not be negative (was " + limit + ")"));
}
///////////////////////////////////
// null input list = null output //
///////////////////////////////////
if(list == null)
{
return (null);
}
int startAt;
if(skip == null)
{
///////////////////////////////////////////
// treat null skip is the same as 0 skip //
///////////////////////////////////////////
startAt = 0;
}
else if(skip > list.size())
{
////////////////////////////////////////
// if skip is too large, return empty //
////////////////////////////////////////
return (new ArrayList<>());
}
else
{
startAt = skip;
}
int endAt;
if(limit == null)
{
////////////////////////////////////////////////////////
// treat null limit as request for all after the skip //
////////////////////////////////////////////////////////
endAt = list.size();
}
else if(limit == 0)
{
/////////////////////////////////////////////
// treat limit of zero as request for none //
/////////////////////////////////////////////
return (new ArrayList<>());
}
else
{
endAt = startAt + limit;
if (endAt > list.size())
{
endAt = list.size();
}
}
return list.subList(startAt, endAt);
}
} }

View File

@ -160,7 +160,7 @@ class CollectionUtilsTest
@Test @Test
void test_addAllToMap() void test_addAllToMap()
{ {
Map<String, Integer> to = new HashMap<>(); Map<String, Integer> to = new HashMap<>();
Map<String, Integer> from = new HashMap<>(); Map<String, Integer> from = new HashMap<>();
assertThrows(NullPointerException.class, () -> CollectionUtils.addAllToMap(null, null)); assertThrows(NullPointerException.class, () -> CollectionUtils.addAllToMap(null, null));
@ -361,6 +361,8 @@ class CollectionUtilsTest
return s -> s.substring(0, 1); return s -> s.substring(0, 1);
} }
/******************************************************************************* /*******************************************************************************
** helper method to get second char of string (unsafely) ** helper method to get second char of string (unsafely)
*******************************************************************************/ *******************************************************************************/
@ -410,4 +412,86 @@ class CollectionUtilsTest
assertEquals("?", CollectionUtils.getQuestionMarks(List.of(1))); assertEquals("?", CollectionUtils.getQuestionMarks(List.of(1)));
assertEquals("?,?,?", CollectionUtils.getQuestionMarks(List.of(1, 2, 3))); assertEquals("?,?,?", CollectionUtils.getQuestionMarks(List.of(1, 2, 3)));
} }
@Test
void test_safelyGetPage()
{
List<Integer> empty = Collections.emptyList();
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
/////////////////////
// null list input //
/////////////////////
assertNull(CollectionUtils.safelyGetPage(null, null, null));
assertNull(CollectionUtils.safelyGetPage(null, 1, 1));
assertNull(CollectionUtils.safelyGetPage(null, null, 1));
assertNull(CollectionUtils.safelyGetPage(null, 1, null));
//////////////////////
// empty list input //
//////////////////////
assertEquals(empty, CollectionUtils.safelyGetPage(empty, null, null));
assertEquals(empty, CollectionUtils.safelyGetPage(empty, 1, 1));
assertEquals(empty, CollectionUtils.safelyGetPage(empty, null, 1));
assertEquals(empty, CollectionUtils.safelyGetPage(empty, 1, null));
////////////////////////////////////////
// cases that give back the full list //
////////////////////////////////////////
assertEquals(list, CollectionUtils.safelyGetPage(list, null, null));
assertEquals(list, CollectionUtils.safelyGetPage(list, 0, null));
///////////////////
// empty outputs //
///////////////////
assertEquals(empty, CollectionUtils.safelyGetPage(list, 0, 0));
assertEquals(empty, CollectionUtils.safelyGetPage(list, 10, 1));
assertEquals(empty, CollectionUtils.safelyGetPage(list, 20, 10));
///////////////////////
// illegal arguments //
///////////////////////
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(list, -1, 1));
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(list, 1, -1));
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(list, -1, -1));
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(null, -1, -1));
/////////////////////////////
// normal kinds of outputs //
/////////////////////////////
assertEquals(List.of(1), CollectionUtils.safelyGetPage(list, null, 1));
assertEquals(List.of(1), CollectionUtils.safelyGetPage(list, 0, 1));
assertEquals(List.of(2), CollectionUtils.safelyGetPage(list, 1, 1));
assertEquals(List.of(2, 3), CollectionUtils.safelyGetPage(list, 1, 2));
assertEquals(List.of(2, 3, 4), CollectionUtils.safelyGetPage(list, 1, 3));
assertEquals(List.of(9), CollectionUtils.safelyGetPage(list, 8, 1));
assertEquals(List.of(9, 10), CollectionUtils.safelyGetPage(list, 8, 2));
assertEquals(List.of(9, 10), CollectionUtils.safelyGetPage(list, 8, 10));
assertEquals(List.of(10), CollectionUtils.safelyGetPage(list, 9, 1));
assertEquals(List.of(10), CollectionUtils.safelyGetPage(list, 9, 2));
assertEquals(List.of(10), CollectionUtils.safelyGetPage(list, 9, 10));
/////////////////////////////////////////////////////////
// make sure scrolling through pages works as expected //
/////////////////////////////////////////////////////////
int skip = 0;
int limit = 3;
int pageCount = 0;
List<Integer> accumulator = new ArrayList<>();
while (true)
{
List<Integer> nextPage = CollectionUtils.safelyGetPage(list, skip, limit);
if (nextPage.isEmpty())
{
break;
}
accumulator.addAll(nextPage);
skip += limit;
pageCount++;
}
assertEquals(4, pageCount);
assertEquals(list, accumulator);
}
} }