mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
QQQ-21 feedback from code review; add more types to ValueUtils
This commit is contained in:
@ -106,7 +106,6 @@ public class RunProcessAction
|
||||
case SKIP ->
|
||||
{
|
||||
LOG.info("Skipping frontend step [" + step.getName() + "] in process [" + process.getName() + "] (as requested by caller)");
|
||||
processState.setNextStepName(step.getName());
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// much less error prone in case this code changes in the future... //
|
||||
@ -166,9 +165,10 @@ public class RunProcessAction
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** When we start running a process (or resuming it), get data in the RunProcessRequest
|
||||
** either from the state provider (if they're found, for a resume).
|
||||
*******************************************************************************/
|
||||
private ProcessState primeProcessState(RunProcessRequest runProcessRequest, UUIDAndTypeStateKey stateKey) throws QException
|
||||
ProcessState primeProcessState(RunProcessRequest runProcessRequest, UUIDAndTypeStateKey stateKey) throws QException
|
||||
{
|
||||
Optional<ProcessState> optionalProcessState = loadState(stateKey);
|
||||
if(optionalProcessState.isEmpty())
|
||||
@ -222,7 +222,7 @@ public class RunProcessAction
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** return true if 'ok', false if error (and time to break loop)
|
||||
** Run a single backend step.
|
||||
*******************************************************************************/
|
||||
private void runBackendStep(RunProcessRequest runProcessRequest, QProcessMetaData process, RunProcessResult runProcessResult, UUIDAndTypeStateKey stateKey, QBackendStepMetaData backendStep, ProcessState processState) throws Exception
|
||||
{
|
||||
@ -231,6 +231,7 @@ public class RunProcessAction
|
||||
runBackendStepRequest.setStepName(backendStep.getName());
|
||||
runBackendStepRequest.setSession(runProcessRequest.getSession());
|
||||
runBackendStepRequest.setCallback(runProcessRequest.getCallback());
|
||||
runBackendStepRequest.setAsyncJobCallback(runProcessRequest.getAsyncJobCallback());
|
||||
RunBackendStepResult lastFunctionResult = new RunBackendStepAction().execute(runBackendStepRequest);
|
||||
storeState(stateKey, lastFunctionResult.getProcessState());
|
||||
|
||||
@ -296,6 +297,16 @@ public class RunProcessAction
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** public method to get a process state just by UUID.
|
||||
*******************************************************************************/
|
||||
public static Optional<ProcessState> getState(String processUUID)
|
||||
{
|
||||
return (getStateProvider().get(ProcessState.class, new UUIDAndTypeStateKey(UUID.fromString(processUUID), StateType.PROCESS_STATUS)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Store the process state from a function result to the state provider
|
||||
**
|
||||
|
@ -90,7 +90,7 @@ public class AsyncJobCallback
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void storeUpdatedStatus()
|
||||
protected void storeUpdatedStatus()
|
||||
{
|
||||
AsyncJobManager.getStateProvider().put(new UUIDAndTypeStateKey(jobUUID, StateType.ASYNC_JOB_STATUS), asyncJobStatus);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public class AsyncJobManager
|
||||
** Load an instance of the appropriate state provider
|
||||
**
|
||||
*******************************************************************************/
|
||||
protected static StateProviderInterface getStateProvider()
|
||||
static StateProviderInterface getStateProvider()
|
||||
{
|
||||
// TODO - read this from somewhere in meta data eh?
|
||||
return InMemoryStateProvider.getInstance();
|
||||
|
@ -39,6 +39,23 @@ public class AsyncJobStatus implements Serializable
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "AsyncJobStatus{"
|
||||
+ "state=" + state
|
||||
+ ", message='" + message + '\''
|
||||
+ ", current=" + current
|
||||
+ ", total=" + total
|
||||
+ ", caughtException=" + caughtException
|
||||
+ '}';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for state
|
||||
**
|
||||
|
@ -23,7 +23,10 @@ package com.kingsrook.qqq.backend.core.actions.async;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Exception thrown by AsyncJobManager, not to indicate an error, per se, but
|
||||
** rather to indicate that a job has taken too long, as is now "going async".
|
||||
**
|
||||
** So, this exception contains the jobUUID.
|
||||
*******************************************************************************/
|
||||
public class JobGoingAsyncException extends Exception
|
||||
{
|
||||
|
@ -25,6 +25,9 @@ package com.kingsrook.qqq.backend.core.model.actions.processes;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobCallback;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobStatus;
|
||||
import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractQRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
@ -43,6 +46,7 @@ public class RunBackendStepRequest extends AbstractQRequest
|
||||
private String processName;
|
||||
private String stepName;
|
||||
private QProcessCallback callback;
|
||||
private AsyncJobCallback asyncJobCallback;
|
||||
|
||||
|
||||
|
||||
@ -312,4 +316,31 @@ public class RunBackendStepRequest extends AbstractQRequest
|
||||
{
|
||||
return processState;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setAsyncJobCallback(AsyncJobCallback asyncJobCallback)
|
||||
{
|
||||
this.asyncJobCallback = asyncJobCallback;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public AsyncJobCallback getAsyncJobCallback()
|
||||
{
|
||||
if (asyncJobCallback == null)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// avoid NPE in case we didn't have one of these! create a new one... //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
asyncJobCallback = new AsyncJobCallback(UUID.randomUUID(), new AsyncJobStatus());
|
||||
}
|
||||
return (asyncJobCallback);
|
||||
}
|
||||
}
|
@ -23,9 +23,11 @@ package com.kingsrook.qqq.backend.core.model.data;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -227,7 +229,7 @@ public class QRecord implements Serializable
|
||||
*******************************************************************************/
|
||||
public String getValueString(String fieldName)
|
||||
{
|
||||
return ((String) values.get(fieldName));
|
||||
return (ValueUtils.getValueAsString(values.get(fieldName)));
|
||||
}
|
||||
|
||||
|
||||
@ -238,7 +240,28 @@ public class QRecord implements Serializable
|
||||
*******************************************************************************/
|
||||
public Integer getValueInteger(String fieldName)
|
||||
{
|
||||
return ((Integer) values.get(fieldName));
|
||||
return (ValueUtils.getValueAsInteger(values.get(fieldName)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public BigDecimal getValueBigDecimal(String fieldName)
|
||||
{
|
||||
return (ValueUtils.getValueAsBigDecimal(values.get(fieldName)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Boolean getValueBoolean(String fieldName)
|
||||
{
|
||||
return (ValueUtils.getValueAsBoolean(values.get(fieldName)));
|
||||
}
|
||||
|
||||
|
||||
@ -249,6 +272,7 @@ public class QRecord implements Serializable
|
||||
*******************************************************************************/
|
||||
public LocalDate getValueDate(String fieldName)
|
||||
{
|
||||
// todo - rewrite using ValueUtils...
|
||||
return ((LocalDate) values.get(fieldName));
|
||||
}
|
||||
|
||||
@ -309,6 +333,7 @@ public class QRecord implements Serializable
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Get one backendDetail from this record as a String
|
||||
**
|
||||
|
@ -35,7 +35,7 @@ public class QFieldMetaData
|
||||
private String label;
|
||||
private String backendName;
|
||||
private QFieldType type;
|
||||
private boolean isRequired;
|
||||
private boolean isRequired = false;
|
||||
|
||||
private Serializable defaultValue;
|
||||
private String possibleValueSourceName;
|
||||
|
@ -170,7 +170,7 @@ public class QBackendStepMetaData extends QStepMetaData
|
||||
/*******************************************************************************
|
||||
** Get a list of all of the input fields used by this function
|
||||
*******************************************************************************/
|
||||
@JsonIgnore
|
||||
@JsonIgnore // because this is a computed property - we don't want it in our json.
|
||||
@Override
|
||||
public List<QFieldMetaData> getInputFields()
|
||||
{
|
||||
@ -187,7 +187,7 @@ public class QBackendStepMetaData extends QStepMetaData
|
||||
/*******************************************************************************
|
||||
** Get a list of all of the output fields used by this function
|
||||
*******************************************************************************/
|
||||
@JsonIgnore
|
||||
@JsonIgnore // because this is a computed property - we don't want it in our json.
|
||||
@Override
|
||||
public List<QFieldMetaData> getOutputFields()
|
||||
{
|
||||
|
@ -212,7 +212,7 @@ public class QProcessMetaData
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Wrapper to getStep, that internally casts t0 BackendStepMetaData
|
||||
** Wrapper to getStep, that internally casts to BackendStepMetaData
|
||||
*******************************************************************************/
|
||||
public QBackendStepMetaData getBackendStep(String name)
|
||||
{
|
||||
|
@ -33,9 +33,11 @@ import com.kingsrook.qqq.backend.core.model.metadata.serialization.QStepMetaData
|
||||
/*******************************************************************************
|
||||
** Meta-Data to define a step in a process in a QQQ instance.
|
||||
**
|
||||
** Specifically, this is a base-class for QFrontendStepMetaData and QBackendStepMetaData.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@JsonDeserialize(using = QStepMetaDataDeserializer.class)
|
||||
public class QStepMetaData
|
||||
public abstract class QStepMetaData
|
||||
{
|
||||
private String name;
|
||||
private String label;
|
||||
|
@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.TreeNode;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||
|
||||
|
||||
@ -47,7 +48,7 @@ public class QStepMetaDataDeserializer extends JsonDeserializer<QStepMetaData>
|
||||
Class<? extends QStepMetaData> targetClass = switch(stepType)
|
||||
{
|
||||
case "backend" -> QBackendStepMetaData.class;
|
||||
case "frontend" -> QBackendStepMetaData.class;
|
||||
case "frontend" -> QFrontendStepMetaData.class;
|
||||
default -> throw new IllegalArgumentException("Unsupported StepType " + stepType + " for deserialization");
|
||||
};
|
||||
return (DeserializerUtils.reflectivelyDeserialize(targetClass, treeNode));
|
||||
|
@ -23,7 +23,10 @@ package com.kingsrook.qqq.backend.core.state;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Possible types of states to be stored.
|
||||
**
|
||||
** Idea: could these have the corresponding Classes that they support?
|
||||
** ala PROCESS_STATUS(ProcessStatus.class) ?
|
||||
*******************************************************************************/
|
||||
public enum StateType
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ public class ExceptionUtils
|
||||
|
||||
/*******************************************************************************
|
||||
** Find a specific exception class in an exception's caused-by chain. Returns
|
||||
** null if not found. Be aware, uses class.isInstaance (so sub-classes get found).
|
||||
** null if not found. Be aware, uses class.isInstance (so sub-classes get found).
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static <T extends Throwable> T findClassInRootChain(Throwable e, Class<T> targetClass)
|
||||
|
@ -33,7 +33,59 @@ public class ValueUtils
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Type-safely make a String from any Object.
|
||||
*******************************************************************************/
|
||||
public static String getValueAsString(Object value)
|
||||
{
|
||||
if(value == null)
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
else if(value instanceof String s)
|
||||
{
|
||||
return (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (String.valueOf(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Returns null for null input;
|
||||
** Returns the input object for Boolean-typed inputs.
|
||||
** Then, follows Boolean.parseBoolean, returning true iff value is a case-insensitive
|
||||
** match for "true", for String.valueOf the input
|
||||
*******************************************************************************/
|
||||
public static Boolean getValueAsBoolean(Object value)
|
||||
{
|
||||
if(value == null)
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
else if(value instanceof Boolean b)
|
||||
{
|
||||
return (b);
|
||||
}
|
||||
else if(value instanceof String s)
|
||||
{
|
||||
return (Boolean.parseBoolean(s));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Boolean.parseBoolean(String.valueOf(value)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Type-safely make an Integer from any Object.
|
||||
** null and empty-string inputs return null.
|
||||
** We try to strip away commas and decimals (as long as they are exactly equal to the int value)
|
||||
** We may throw if the input can't be converted to an integer.
|
||||
*******************************************************************************/
|
||||
public static Integer getValueAsInteger(Object value) throws QValueException
|
||||
{
|
||||
@ -53,7 +105,7 @@ public class ValueUtils
|
||||
}
|
||||
else if(value instanceof Float f)
|
||||
{
|
||||
if (f.intValue() != f)
|
||||
if(f.intValue() != f)
|
||||
{
|
||||
throw (new QValueException(f + " does not have an exact integer representation."));
|
||||
}
|
||||
@ -61,7 +113,7 @@ public class ValueUtils
|
||||
}
|
||||
else if(value instanceof Double d)
|
||||
{
|
||||
if (d.intValue() != d)
|
||||
if(d.intValue() != d)
|
||||
{
|
||||
throw (new QValueException(d + " does not have an exact integer representation."));
|
||||
}
|
||||
@ -122,4 +174,78 @@ public class ValueUtils
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Type-safely make a BigDecimal from any Object.
|
||||
** null and empty-string inputs return null.
|
||||
** We may throw if the input can't be converted to a BigDecimal
|
||||
*******************************************************************************/
|
||||
public static BigDecimal getValueAsBigDecimal(Object value) throws QValueException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(value == null)
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
else if(value instanceof BigDecimal bd)
|
||||
{
|
||||
return (bd);
|
||||
}
|
||||
else if(value instanceof Integer i)
|
||||
{
|
||||
return new BigDecimal(i);
|
||||
}
|
||||
else if(value instanceof Long l)
|
||||
{
|
||||
return new BigDecimal(l);
|
||||
}
|
||||
else if(value instanceof Float f)
|
||||
{
|
||||
return new BigDecimal(f);
|
||||
}
|
||||
else if(value instanceof Double d)
|
||||
{
|
||||
return new BigDecimal(d);
|
||||
}
|
||||
else if(value instanceof String s)
|
||||
{
|
||||
if(!StringUtils.hasContent(s))
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return (new BigDecimal(s));
|
||||
}
|
||||
catch(NumberFormatException nfe)
|
||||
{
|
||||
if(s.contains(","))
|
||||
{
|
||||
String sWithoutCommas = s.replaceAll(",", "");
|
||||
try
|
||||
{
|
||||
return (getValueAsBigDecimal(sWithoutCommas));
|
||||
}
|
||||
catch(Exception ignore)
|
||||
{
|
||||
throw (nfe);
|
||||
}
|
||||
}
|
||||
throw (nfe);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (new IllegalArgumentException("Unsupported class " + value.getClass().getName() + " for converting to BigDecimal."));
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw (new QValueException("Value [" + value + "] could not be converted to an BigDecimal.", e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ package com.kingsrook.qqq.backend.core.actions;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataResult;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
@ -67,7 +67,7 @@ class ProcessMetaDataActionTest
|
||||
@Test
|
||||
public void test_notFound()
|
||||
{
|
||||
assertThrows(QUserFacingException.class, () -> {
|
||||
assertThrows(QNotFoundException.class, () -> {
|
||||
ProcessMetaDataRequest request = new ProcessMetaDataRequest(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName("willNotBeFound");
|
||||
|
@ -27,21 +27,27 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.interfaces.mock.MockBackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessState;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessResult;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@ -99,6 +105,7 @@ public class RunProcessTest
|
||||
Optional<String> breakingAtStep0 = result0.getProcessState().getNextStepName();
|
||||
assertTrue(breakingAtStep0.isPresent());
|
||||
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep0.get()));
|
||||
assertNull(result0.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// now run again, proceeding from this step //
|
||||
@ -113,6 +120,7 @@ public class RunProcessTest
|
||||
assertTrue(breakingAtStep1.isPresent());
|
||||
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep1.get()));
|
||||
assertNotEquals(breakingAtStep0.get(), breakingAtStep1.get());
|
||||
assertEquals(MockBackendStep.MOCK_VALUE, result1.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
}
|
||||
|
||||
|
||||
@ -136,6 +144,7 @@ public class RunProcessTest
|
||||
RunProcessResult runProcessResult = new RunProcessAction().execute(request);
|
||||
assertTrue(runProcessResult.getException().isEmpty());
|
||||
assertEquals(MockBackendStep.MOCK_VALUE, runProcessResult.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
assertTrue(runProcessResult.getProcessState().getNextStepName().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
@ -169,6 +178,79 @@ public class RunProcessTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPrimeProcessRequestNewProcess() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// this is a flow where it's a new process - so, we should create a new state //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
RunProcessRequest runProcessRequest = new RunProcessRequest();
|
||||
UUIDAndTypeStateKey stateKey = new UUIDAndTypeStateKey(UUID.randomUUID(), StateType.PROCESS_STATUS);
|
||||
ProcessState processState = new RunProcessAction().primeProcessState(runProcessRequest, stateKey);
|
||||
assertNotNull(processState);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPrimeProcessRequestAttemptToContinueButStateNotFound() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this is a flow where it's a continue, but we don't have a state stored, so it should throw //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RunProcessRequest runProcessRequest = new RunProcessRequest();
|
||||
runProcessRequest.setStartAfterStep("setupStep");
|
||||
UUIDAndTypeStateKey stateKey = new UUIDAndTypeStateKey(UUID.randomUUID(), StateType.PROCESS_STATUS);
|
||||
|
||||
assertThrows(QException.class, () ->
|
||||
{
|
||||
new RunProcessAction().primeProcessState(runProcessRequest, stateKey);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPrimeProcessRequestAttemptToContinueAndStateIsFound() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this is a flow where it's a continue, but we don't have a state stored, so it should throw //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RunProcessRequest runProcessRequest = new RunProcessRequest();
|
||||
runProcessRequest.setStartAfterStep("setupStep");
|
||||
runProcessRequest.addValue("foo", "bar");
|
||||
runProcessRequest.addValue("alpha", "beta");
|
||||
UUIDAndTypeStateKey stateKey = new UUIDAndTypeStateKey(UUID.randomUUID(), StateType.PROCESS_STATUS);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// simulate the state being previously stored //
|
||||
////////////////////////////////////////////////
|
||||
ProcessState oldProcessState = new ProcessState();
|
||||
oldProcessState.getValues().put("key", "myValue");
|
||||
oldProcessState.getValues().put("foo", "fubu");
|
||||
RunProcessAction.getStateProvider().put(stateKey, oldProcessState);
|
||||
|
||||
ProcessState primedProcessState = new RunProcessAction().primeProcessState(runProcessRequest, stateKey);
|
||||
assertEquals("myValue", primedProcessState.getValues().get("key"));
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// make sure values that were in the original request trump values that had been in state. //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
assertEquals("bar", primedProcessState.getValues().get("foo"));
|
||||
assertEquals("beta", primedProcessState.getValues().get("alpha"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -29,6 +29,7 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -65,7 +66,7 @@ class AsyncJobManagerTest
|
||||
assertThrows(JobGoingAsyncException.class, () ->
|
||||
{
|
||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||
Integer answer = asyncJobManager.startJob(1, TimeUnit.MICROSECONDS, (callback) ->
|
||||
asyncJobManager.startJob(1, TimeUnit.MICROSECONDS, (callback) ->
|
||||
{
|
||||
Thread.sleep(1_000);
|
||||
return (ANSWER);
|
||||
@ -108,6 +109,7 @@ class AsyncJobManagerTest
|
||||
Thread.sleep(50);
|
||||
throw (new IllegalArgumentException(message));
|
||||
});
|
||||
fail("We should catch a JobGoingAsyncException");
|
||||
}
|
||||
catch(JobGoingAsyncException jgae)
|
||||
{
|
||||
@ -140,6 +142,7 @@ class AsyncJobManagerTest
|
||||
callback.updateStatus(postMessage, 1, 1);
|
||||
return (ANSWER);
|
||||
});
|
||||
fail("We should catch a JobGoingAsyncException");
|
||||
}
|
||||
catch(JobGoingAsyncException jgae)
|
||||
{
|
||||
@ -152,6 +155,7 @@ class AsyncJobManagerTest
|
||||
assertEquals(1, jobStatus.get().getTotal());
|
||||
|
||||
Thread.sleep(200);
|
||||
jobStatus = asyncJobManager.getJobStatus(jgae.getJobUUID());
|
||||
assertEquals(AsyncJobState.COMPLETE, jobStatus.get().getState());
|
||||
assertEquals(postMessage, jobStatus.get().getMessage());
|
||||
assertEquals(1, jobStatus.get().getCurrent());
|
||||
|
@ -56,6 +56,7 @@ class BasicETLProcessTest
|
||||
RunProcessResult result = new RunProcessAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process");
|
||||
assertTrue(result.getException().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +83,7 @@ class BasicETLProcessTest
|
||||
RunProcessResult result = new RunProcessAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process");
|
||||
assertTrue(result.getException().isEmpty());
|
||||
}
|
||||
|
||||
}
|
@ -415,6 +415,9 @@ class CollectionUtilsTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_safelyGetPage()
|
||||
{
|
||||
@ -494,4 +497,5 @@ class CollectionUtilsTest
|
||||
assertEquals(4, pageCount);
|
||||
assertEquals(list, accumulator);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.utils;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
@ -34,6 +35,51 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class ValueUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsString() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsString(null));
|
||||
assertEquals("", ValueUtils.getValueAsString(""));
|
||||
assertEquals(" ", ValueUtils.getValueAsString(" "));
|
||||
assertEquals("A", ValueUtils.getValueAsString("A"));
|
||||
assertEquals("1", ValueUtils.getValueAsString("1"));
|
||||
assertEquals("1", ValueUtils.getValueAsString(1));
|
||||
assertEquals("1", ValueUtils.getValueAsString(1));
|
||||
assertEquals("1.10", ValueUtils.getValueAsString(new BigDecimal("1.10")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsBoolean() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsBoolean(null));
|
||||
assertTrue(ValueUtils.getValueAsBoolean("true"));
|
||||
assertTrue(ValueUtils.getValueAsBoolean("True"));
|
||||
assertTrue(ValueUtils.getValueAsBoolean("TRUE"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean("false"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean("yes"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean("t"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean(new Object()));
|
||||
assertFalse(ValueUtils.getValueAsBoolean(1));
|
||||
assertTrue(ValueUtils.getValueAsBoolean(new Object()
|
||||
{
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return ("true");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -63,4 +109,35 @@ class ValueUtilsTest
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger(1.1D));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsBigDecimal() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsBigDecimal(null));
|
||||
assertNull(ValueUtils.getValueAsBigDecimal(""));
|
||||
assertNull(ValueUtils.getValueAsBigDecimal(" "));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(1));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal("1"));
|
||||
assertEquals(new BigDecimal("1000"), ValueUtils.getValueAsBigDecimal("1,000"));
|
||||
assertEquals(new BigDecimal("1000000"), ValueUtils.getValueAsBigDecimal("1,000,000"));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(new BigDecimal(1)));
|
||||
assertEquals(new BigDecimal("1.00"), ValueUtils.getValueAsBigDecimal(new BigDecimal("1.00")));
|
||||
assertEquals(new BigDecimal("-1.00"), ValueUtils.getValueAsBigDecimal("-1.00"));
|
||||
assertEquals(new BigDecimal("1000.00"), ValueUtils.getValueAsBigDecimal("1,000.00"));
|
||||
assertEquals(new BigDecimal("1000"), ValueUtils.getValueAsBigDecimal(1000L));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(1.0F));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(1.0D));
|
||||
assertEquals(new BigDecimal("1000000000000"), ValueUtils.getValueAsBigDecimal(1_000_000_000_000L));
|
||||
assertEquals(0, new BigDecimal("1.1").compareTo(ValueUtils.getValueAsBigDecimal(1.1F).round(MathContext.DECIMAL32)));
|
||||
assertEquals(0, new BigDecimal("1.1").compareTo(ValueUtils.getValueAsBigDecimal(1.1D).round(MathContext.DECIMAL64)));
|
||||
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsBigDecimal("a"));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsBigDecimal("a,b"));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsBigDecimal(new Object()));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user