Add convertJavaObject to QCodeExecutor

This commit is contained in:
2023-07-03 14:05:07 -05:00
parent 40d073bf54
commit 56b9738f15
4 changed files with 138 additions and 57 deletions

View File

@ -46,7 +46,17 @@ public interface QCodeExecutor
** e.g., a Nashorn ScriptObjectMirror will end up as a "primitive", or a List or Map of such
**
*******************************************************************************/
default Object convertObjectToJava(Object object)
default Object convertObjectToJava(Object object) throws QCodeException
{
return (object);
}
/*******************************************************************************
** Convert a native java object into one for the script's language/runtime.
** e.g., a java Instant to a Nashorn Date
**
*******************************************************************************/
default Object convertJavaObject(Object object, Object requestedTypeHint) throws QCodeException
{
return (object);
}

View File

@ -29,6 +29,7 @@ import javax.script.ScriptException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -74,7 +75,9 @@ public class QJavaScriptExecutor implements QCodeExecutor
**
*******************************************************************************/
@Override
public Object convertObjectToJava(Object object)
public Object convertObjectToJava(Object object) throws QCodeException
{
try
{
if(object == null || object instanceof String || object instanceof Boolean || object instanceof Integer || object instanceof Long || object instanceof BigDecimal)
{
@ -141,6 +144,40 @@ public class QJavaScriptExecutor implements QCodeExecutor
return QCodeExecutor.super.convertObjectToJava(object);
}
catch(Exception e)
{
throw (new QCodeException("Error converting java object", e));
}
}
/*******************************************************************************
** Convert a native java object into one for the script's language/runtime.
** e.g., a java Instant to a Nashorn Date
**
*******************************************************************************/
public Object convertJavaObject(Object object, Object requestedTypeHint) throws QCodeException
{
try
{
if("Date".equals(requestedTypeHint))
{
if(object instanceof Instant i)
{
long millis = (i.getEpochSecond() * 1000 + i.getLong(ChronoField.MILLI_OF_SECOND));
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
return engine.eval("new Date(" + millis + ")");
}
}
return (QCodeExecutor.super.convertJavaObject(object, requestedTypeHint));
}
catch(Exception e)
{
throw (new QCodeException("Error converting java object", e));
}
}

View File

@ -41,9 +41,11 @@ import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
import org.assertj.core.api.Assertions;
import org.assertj.core.data.Offset;
import org.junit.jupiter.api.Test;
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -284,6 +286,27 @@ class ExecuteCodeActionTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testConvertJavaObject() throws QException
{
TestQCodeExecutorAware converter = new TestQCodeExecutorAware();
Instant originalInstant = Instant.parse("2023-07-03T11:42:42Z");
testOne(1, """
converter.convertJavaObject("jsDate", instant, "Date");
converter.convertObject("backToInstant", converter.getConvertedObject("jsDate"));
""", MapBuilder.of("converter", converter, "instant", originalInstant));
assertThat(converter.getConvertedObject("jsDate")).isInstanceOf(ScriptObjectMirror.class);
assertEquals(originalInstant, converter.getConvertedObject("backToInstant"));
assertNotSame(originalInstant, converter.getConvertedObject("backToInstant"));
}
/*******************************************************************************
**
*******************************************************************************/
@ -355,13 +378,23 @@ class ExecuteCodeActionTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
public void convertObject(String name, Object inputObject)
public void convertObject(String name, Object inputObject) throws QCodeException
{
convertedObjectMap.put(name, qCodeExecutor.convertObjectToJava(inputObject));
}
/*******************************************************************************
**
*******************************************************************************/
public void convertJavaObject(String name, Object inputObject, Object hint) throws QCodeException
{
convertedObjectMap.put(name, qCodeExecutor.convertJavaObject(inputObject, hint));
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -36,6 +36,7 @@ import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
import com.kingsrook.qqq.backend.core.actions.scripts.QCodeExecutor;
import com.kingsrook.qqq.backend.core.actions.scripts.QCodeExecutorAware;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
@ -208,7 +209,7 @@ public class ApiScriptUtils implements QCodeExecutorAware, Serializable
** Take a "body" object, which maybe defined in the script's language/run-time,
** and try to process it into a JSON String (which is what the API Implementation wants)
*******************************************************************************/
private Object processBodyToJsonString(Object body)
private Object processBodyToJsonString(Object body) throws QCodeException
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the caller already supplied the object as a string, then return that string. //
@ -234,7 +235,7 @@ public class ApiScriptUtils implements QCodeExecutorAware, Serializable
** script's language into a (more) native java object.
** e.g., a Nashorn ScriptObjectMirror will end up as a "primitive", or a List or Map of such
*******************************************************************************/
private Object processInputObjectViaCodeExecutor(Object body)
private Object processInputObjectViaCodeExecutor(Object body) throws QCodeException
{
if(qCodeExecutor == null || body == null)
{