mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
QQQ-21 add safelyGetPage; add stepType
This commit is contained in:
@ -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());
|
||||||
|
@ -42,6 +42,16 @@ public class QBackendStepMetaData extends QStepMetaData
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendStepMetaData()
|
||||||
|
{
|
||||||
|
setStepType("backend");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Setter for label
|
** Setter for label
|
||||||
**
|
**
|
||||||
|
@ -40,6 +40,16 @@ public class QFrontendStepMetaData extends QStepMetaData
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFrontendStepMetaData()
|
||||||
|
{
|
||||||
|
setStepType("frontend");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for formFields
|
** Getter for formFields
|
||||||
**
|
**
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user