mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +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 ->
|
case SKIP ->
|
||||||
{
|
{
|
||||||
LOG.info("Skipping frontend step [" + step.getName() + "] in process [" + process.getName() + "] (as requested by caller)");
|
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... //
|
// 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);
|
Optional<ProcessState> optionalProcessState = loadState(stateKey);
|
||||||
if(optionalProcessState.isEmpty())
|
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
|
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.setStepName(backendStep.getName());
|
||||||
runBackendStepRequest.setSession(runProcessRequest.getSession());
|
runBackendStepRequest.setSession(runProcessRequest.getSession());
|
||||||
runBackendStepRequest.setCallback(runProcessRequest.getCallback());
|
runBackendStepRequest.setCallback(runProcessRequest.getCallback());
|
||||||
|
runBackendStepRequest.setAsyncJobCallback(runProcessRequest.getAsyncJobCallback());
|
||||||
RunBackendStepResult lastFunctionResult = new RunBackendStepAction().execute(runBackendStepRequest);
|
RunBackendStepResult lastFunctionResult = new RunBackendStepAction().execute(runBackendStepRequest);
|
||||||
storeState(stateKey, lastFunctionResult.getProcessState());
|
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
|
** 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);
|
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
|
** Load an instance of the appropriate state provider
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
protected static StateProviderInterface getStateProvider()
|
static StateProviderInterface getStateProvider()
|
||||||
{
|
{
|
||||||
// TODO - read this from somewhere in meta data eh?
|
// TODO - read this from somewhere in meta data eh?
|
||||||
return InMemoryStateProvider.getInstance();
|
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
|
** 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
|
public class JobGoingAsyncException extends Exception
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,9 @@ package com.kingsrook.qqq.backend.core.model.actions.processes;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.callbacks.QProcessCallback;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractQRequest;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractQRequest;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
@ -43,6 +46,7 @@ public class RunBackendStepRequest extends AbstractQRequest
|
|||||||
private String processName;
|
private String processName;
|
||||||
private String stepName;
|
private String stepName;
|
||||||
private QProcessCallback callback;
|
private QProcessCallback callback;
|
||||||
|
private AsyncJobCallback asyncJobCallback;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -312,4 +316,31 @@ public class RunBackendStepRequest extends AbstractQRequest
|
|||||||
{
|
{
|
||||||
return processState;
|
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.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
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)
|
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)
|
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)
|
public LocalDate getValueDate(String fieldName)
|
||||||
{
|
{
|
||||||
|
// todo - rewrite using ValueUtils...
|
||||||
return ((LocalDate) values.get(fieldName));
|
return ((LocalDate) values.get(fieldName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,6 +333,7 @@ public class QRecord implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Get one backendDetail from this record as a String
|
** Get one backendDetail from this record as a String
|
||||||
**
|
**
|
||||||
|
@ -35,7 +35,7 @@ public class QFieldMetaData
|
|||||||
private String label;
|
private String label;
|
||||||
private String backendName;
|
private String backendName;
|
||||||
private QFieldType type;
|
private QFieldType type;
|
||||||
private boolean isRequired;
|
private boolean isRequired = false;
|
||||||
|
|
||||||
private Serializable defaultValue;
|
private Serializable defaultValue;
|
||||||
private String possibleValueSourceName;
|
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
|
** 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
|
@Override
|
||||||
public List<QFieldMetaData> getInputFields()
|
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
|
** 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
|
@Override
|
||||||
public List<QFieldMetaData> getOutputFields()
|
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)
|
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.
|
** 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)
|
@JsonDeserialize(using = QStepMetaDataDeserializer.class)
|
||||||
public class QStepMetaData
|
public abstract class QStepMetaData
|
||||||
{
|
{
|
||||||
private String name;
|
private String name;
|
||||||
private String label;
|
private String label;
|
||||||
|
@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.TreeNode;
|
|||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
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.QBackendStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
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)
|
Class<? extends QStepMetaData> targetClass = switch(stepType)
|
||||||
{
|
{
|
||||||
case "backend" -> QBackendStepMetaData.class;
|
case "backend" -> QBackendStepMetaData.class;
|
||||||
case "frontend" -> QBackendStepMetaData.class;
|
case "frontend" -> QFrontendStepMetaData.class;
|
||||||
default -> throw new IllegalArgumentException("Unsupported StepType " + stepType + " for deserialization");
|
default -> throw new IllegalArgumentException("Unsupported StepType " + stepType + " for deserialization");
|
||||||
};
|
};
|
||||||
return (DeserializerUtils.reflectivelyDeserialize(targetClass, treeNode));
|
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
|
public enum StateType
|
||||||
{
|
{
|
||||||
|
@ -35,7 +35,7 @@ public class ExceptionUtils
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Find a specific exception class in an exception's caused-by chain. Returns
|
** 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)
|
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
|
public static Integer getValueAsInteger(Object value) throws QValueException
|
||||||
{
|
{
|
||||||
@ -53,7 +105,7 @@ public class ValueUtils
|
|||||||
}
|
}
|
||||||
else if(value instanceof Float f)
|
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."));
|
throw (new QValueException(f + " does not have an exact integer representation."));
|
||||||
}
|
}
|
||||||
@ -61,7 +113,7 @@ public class ValueUtils
|
|||||||
}
|
}
|
||||||
else if(value instanceof Double d)
|
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."));
|
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.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.ProcessMetaDataRequest;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataResult;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataResult;
|
||||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
@ -67,7 +67,7 @@ class ProcessMetaDataActionTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_notFound()
|
public void test_notFound()
|
||||||
{
|
{
|
||||||
assertThrows(QUserFacingException.class, () -> {
|
assertThrows(QNotFoundException.class, () -> {
|
||||||
ProcessMetaDataRequest request = new ProcessMetaDataRequest(TestUtils.defineInstance());
|
ProcessMetaDataRequest request = new ProcessMetaDataRequest(TestUtils.defineInstance());
|
||||||
request.setSession(TestUtils.getMockSession());
|
request.setSession(TestUtils.getMockSession());
|
||||||
request.setProcessName("willNotBeFound");
|
request.setProcessName("willNotBeFound");
|
||||||
|
@ -27,21 +27,27 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
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.interfaces.mock.MockBackendStep;
|
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.RunProcessRequest;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessResult;
|
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.actions.query.QQueryFilter;
|
||||||
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.QInstance;
|
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.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 com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
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.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
@ -99,6 +105,7 @@ public class RunProcessTest
|
|||||||
Optional<String> breakingAtStep0 = result0.getProcessState().getNextStepName();
|
Optional<String> breakingAtStep0 = result0.getProcessState().getNextStepName();
|
||||||
assertTrue(breakingAtStep0.isPresent());
|
assertTrue(breakingAtStep0.isPresent());
|
||||||
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep0.get()));
|
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep0.get()));
|
||||||
|
assertNull(result0.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
// now run again, proceeding from this step //
|
// now run again, proceeding from this step //
|
||||||
@ -113,6 +120,7 @@ public class RunProcessTest
|
|||||||
assertTrue(breakingAtStep1.isPresent());
|
assertTrue(breakingAtStep1.isPresent());
|
||||||
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep1.get()));
|
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep1.get()));
|
||||||
assertNotEquals(breakingAtStep0.get(), 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);
|
RunProcessResult runProcessResult = new RunProcessAction().execute(request);
|
||||||
assertTrue(runProcessResult.getException().isEmpty());
|
assertTrue(runProcessResult.getException().isEmpty());
|
||||||
assertEquals(MockBackendStep.MOCK_VALUE, runProcessResult.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
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, () ->
|
assertThrows(JobGoingAsyncException.class, () ->
|
||||||
{
|
{
|
||||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||||
Integer answer = asyncJobManager.startJob(1, TimeUnit.MICROSECONDS, (callback) ->
|
asyncJobManager.startJob(1, TimeUnit.MICROSECONDS, (callback) ->
|
||||||
{
|
{
|
||||||
Thread.sleep(1_000);
|
Thread.sleep(1_000);
|
||||||
return (ANSWER);
|
return (ANSWER);
|
||||||
@ -108,6 +109,7 @@ class AsyncJobManagerTest
|
|||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
throw (new IllegalArgumentException(message));
|
throw (new IllegalArgumentException(message));
|
||||||
});
|
});
|
||||||
|
fail("We should catch a JobGoingAsyncException");
|
||||||
}
|
}
|
||||||
catch(JobGoingAsyncException jgae)
|
catch(JobGoingAsyncException jgae)
|
||||||
{
|
{
|
||||||
@ -140,6 +142,7 @@ class AsyncJobManagerTest
|
|||||||
callback.updateStatus(postMessage, 1, 1);
|
callback.updateStatus(postMessage, 1, 1);
|
||||||
return (ANSWER);
|
return (ANSWER);
|
||||||
});
|
});
|
||||||
|
fail("We should catch a JobGoingAsyncException");
|
||||||
}
|
}
|
||||||
catch(JobGoingAsyncException jgae)
|
catch(JobGoingAsyncException jgae)
|
||||||
{
|
{
|
||||||
@ -152,6 +155,7 @@ class AsyncJobManagerTest
|
|||||||
assertEquals(1, jobStatus.get().getTotal());
|
assertEquals(1, jobStatus.get().getTotal());
|
||||||
|
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
|
jobStatus = asyncJobManager.getJobStatus(jgae.getJobUUID());
|
||||||
assertEquals(AsyncJobState.COMPLETE, jobStatus.get().getState());
|
assertEquals(AsyncJobState.COMPLETE, jobStatus.get().getState());
|
||||||
assertEquals(postMessage, jobStatus.get().getMessage());
|
assertEquals(postMessage, jobStatus.get().getMessage());
|
||||||
assertEquals(1, jobStatus.get().getCurrent());
|
assertEquals(1, jobStatus.get().getCurrent());
|
||||||
|
@ -56,6 +56,7 @@ class BasicETLProcessTest
|
|||||||
RunProcessResult result = new RunProcessAction().execute(request);
|
RunProcessResult result = new RunProcessAction().execute(request);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process");
|
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);
|
RunProcessResult result = new RunProcessAction().execute(request);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process");
|
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
|
@Test
|
||||||
void test_safelyGetPage()
|
void test_safelyGetPage()
|
||||||
{
|
{
|
||||||
@ -494,4 +497,5 @@ class CollectionUtilsTest
|
|||||||
assertEquals(4, pageCount);
|
assertEquals(4, pageCount);
|
||||||
assertEquals(list, accumulator);
|
assertEquals(list, accumulator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.utils;
|
|||||||
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.MathContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
@ -34,6 +35,51 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
class ValueUtilsTest
|
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));
|
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