com.javonet.sdk.InvocationContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javonet-java-sdk Show documentation
Show all versions of javonet-java-sdk Show documentation
Javonet allows you to reference and use modules or packages written in (Java/Kotlin/Groovy/Clojure, C#/VB.NET, Ruby, Perl, Python, JavaScript/TypeScript) like they were created in your technology.
It works on Linux/Windows and MacOS for applications created in JVM, CLR/Netcore, Perl, Python, Ruby, NodeJS, C++ or GoLang and gives you unparalleled freedom and flexibility with native performance in building your mixed-technologies products.
Let it be accessing best AI or cryptography libraries, devices SDKs, legacy client modules, internal custom packages or anything from public repositories available on NPM, Nuget, PyPI, Maven/Gradle, RubyGems or GitHub. Get free from programming languages barriers today!
For more information check out our guides at https://www.javonet.com/guides/v2/
package com.javonet.sdk;
import com.javonet.core.generator.IOptimizedTransmitter;
import com.javonet.core.generator.TransmitterOptimizer;
import com.javonet.core.handler.Handler;
import com.javonet.core.interpreter.Interpreter;
import com.javonet.sdk.internal.*;
import com.javonet.utils.*;
import com.javonet.utils.exceptions.ExceptionThrower;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Iterator;
/**
* InvocationContext is a class that represents a context for invoking commands.
* It implements several interfaces for different types of interactions.
* This class is used to construct chains of invocations, representing expressions of interaction that have not yet been executed.
*/
public class InvocationContext implements AbstractInvocationContext, AbstractInstanceContext, AbstractStaticContext, AbstractArrayContext, AbstractEnumContext, Iterable {
private final Interpreter interpreter;
private final RuntimeName runtimeName;
private final ConnectionType connectionType;
private Command currentCommand;
/**
* Returns the current command of the InvocationContext.
*
* @return the current command.
*/
protected Command getCurrentCommand() {
return currentCommand;
}
;
private Command responseCommand;
private boolean isExecuted;
private TcpConnectionData tcpConnectionData;
private Object resultValue;
protected InvocationContext(RuntimeName runtime,
ConnectionType connectionType,
TcpConnectionData tcpConnectionData,
Command command) {
this.runtimeName = runtime;
this.connectionType = connectionType;
this.tcpConnectionData = tcpConnectionData;
this.currentCommand = command;
this.responseCommand = null;
this.isExecuted = false;
interpreter = new Interpreter();
}
/**
* Constructs an InvocationContext with the specified runtime, connection type, TCP address, command, and execution status.
*
* @param runtime the runtime name.
* @param connectionType the connection type.
* @param tcpConnectionData the TCP address.
* @param command the command.
* @param isExecuted the execution status.
*/
public InvocationContext(RuntimeName runtime,
ConnectionType connectionType,
TcpConnectionData tcpConnectionData,
Command command, boolean isExecuted) {
this.runtimeName = runtime;
this.connectionType = connectionType;
this.tcpConnectionData = tcpConnectionData;
this.currentCommand = command;
this.responseCommand = null;
this.isExecuted = isExecuted;
interpreter = new Interpreter();
}
// @Override
// protected void finalize() {
// if (this.currentCommand.getCommandType() == JvmCommandType.REFERENCE && this.isExecuted == true) {
// this.currentCommand = new JvmCommand(this.runtimeLib, JvmCommandType.DESTRUCT_REFERENCE, this.currentCommand.getPayload());
// execute();
// }
// }
@NotNull
@Override
public Iterator iterator() {
if (this.currentCommand.getCommandType() != CommandType.REFERENCE) {
throw new RuntimeException("Object is not iterable");
}
return new InvocationContextIterator(this);
}
public Command getCommand() {
return currentCommand;
}
/**
* Executes the current command.
* Because invocation context is building the intent of executing particular expression on target environment, we call the initial state of invocation context as non-materialized.
* The non-materialized context wraps either single command or chain of recursively nested commands.
* Commands are becoming nested through each invocation of methods on Invocation Context.
* Each invocation triggers the creation of new Invocation Context instance wrapping the current command with new parent command valid for invoked method.
* Developer can decide on any moment of the materialization for the context taking full control of the chunks of the expression being transferred and processed on target runtime.
* If toOptimize is true, it optimizes the current command before executing it. Currently, optimization is not supported.
*
* @param toOptimize whether to optimize the current command before executing it.
* @return the InvocationContext after executing the command.
* @see Article on Javonet Guides
*/
public InvocationContext execute(boolean toOptimize) {
if (toOptimize) {
Handler handler = new Handler();
Integer commandHashCode = this.currentCommand.hashCode();
if (!IOptimizedTransmitter.optimizedClasses.containsKey(commandHashCode)) {
TransmitterOptimizer.optimize(this.currentCommand, handler, interpreter, connectionType, tcpConnectionData);
}
Object[] arg = ((Command) (this.currentCommand.getPayload()[2])).getPayload();
this.resultValue = ((IOptimizedTransmitter) IOptimizedTransmitter.optimizedClasses.get(commandHashCode)).execute(arg);
this.isExecuted = true;
return this;
} else {
return execute();
}
}
/**
* Executes the current command without optimization.
* Because invocation context is building the intent of executing particular expression on target environment, we call the initial state of invocation context as non-materialized.
* The non-materialized context wraps either single command or chain of recursively nested commands.
* Commands are becoming nested through each invocation of methods on Invocation Context.
* Each invocation triggers the creation of new Invocation Context instance wrapping the current command with new parent command valid for invoked method.
* Developer can decide on any moment of the materialization for the context taking full control of the chunks of the expression being transferred and processed on target runtime.
*
* @return the InvocationContext after executing the command.
* @see Article on Javonet Guides
*/
public InvocationContext execute() {
this.responseCommand = this.interpreter.execute(this.currentCommand, this.connectionType, this.tcpConnectionData);
if (this.responseCommand.getCommandType() == CommandType.EXCEPTION) {
ExceptionThrower.throwException(this.responseCommand);
}
if (this.responseCommand.getCommandType() == CommandType.CREATE_INSTANCE) {
this.currentCommand = this.responseCommand;
this.isExecuted = true;
return this;
}
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, this.responseCommand, true);
}
/**
* Invokes a static method on the target runtime.
*
* @param methodName the name of the static method to invoke.
* @param arguments the arguments to pass to the static method.
* @return a new InvocationContext instance that wraps the command to invoke the static method.
* @see Javonet Guides
*/
@Override
public InvocationContext invokeStaticMethod(String methodName, Object... arguments) {
Command localCommand = new Command(this.runtimeName, CommandType.INVOKE_STATIC_METHOD, createArgsArray(methodName, arguments));
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the value of an instance field from the target runtime.
*
* @param fieldName the name of the instance field to retrieve.
* @return a new InvocationContext instance that wraps the command to get the instance field.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getInstanceField(String fieldName) {
Command localCommand = new Command(this.runtimeName, CommandType.GET_INSTANCE_FIELD, fieldName);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Sets the value of an instance field in the target runtime.
*
* @param fieldName the name of the instance field to set.
* @param value the new value to set the instance field to.
* @return a new InvocationContext instance that wraps the command to set the instance field.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext setInstanceField(String fieldName, Object value) {
Command localCommand = new Command(this.runtimeName, CommandType.SET_INSTANCE_FIELD, fieldName, value);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Invokes an instance method on the target runtime.
*
* @param methodName the name of the instance method to invoke.
* @param arguments the arguments to pass to the instance method.
* @return a new InvocationContext instance that wraps the command to invoke the instance method.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext invokeInstanceMethod(String methodName, Object... arguments) {
Command localCommand = new Command(this.runtimeName, CommandType.INVOKE_INSTANCE_METHOD, createArgsArray(methodName, arguments));
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Invokes a constructor on the target runtime.
*
* @param arguments the arguments to pass to the constructor.
* @return a new InvocationContext instance that wraps the command to invoke the constructor.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext createInstance(Object... arguments) {
Command localCommand = new Command(this.runtimeName, CommandType.CREATE_INSTANCE, arguments);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Gets the value of a static field from the target runtime.
*
* @param fieldName the name of the static field to get.
* @return a new InvocationContext instance that wraps the command to get the static field.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getStaticField(String fieldName) {
Command localCommand = new Command(this.runtimeName, CommandType.GET_STATIC_FIELD, fieldName);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Sets the value of a static field in the target runtime.
*
* @param fieldName the name of the static field to set.
* @param value the new value to set the static field to.
* @return a new InvocationContext instance that wraps the command to set the static field.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext setStaticField(String fieldName, Object value) {
Command localCommand = new Command(this.runtimeName, CommandType.SET_STATIC_FIELD, fieldName, value);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the value at a specified index in an array from the target runtime.
*
* @param indexes the indexes to get the value at.
* @return a new InvocationContext instance that wraps the command to get the array element.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getIndex(Object... indexes) {
Command localCommand = new Command(this.runtimeName, CommandType.ARRAY_GET_ITEM, indexes);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the size of an array from the target runtime.
*
* @return InvocationContext instance with the command to get the array size.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getSize() {
Command localCommand = new Command(this.runtimeName, CommandType.ARRAY_GET_SIZE);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the rank (number of dimensions) of an array from the target runtime.
*
* @return InvocationContext instance with the command to get the array rank.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getRank() {
Command localCommand = new Command(this.runtimeName, CommandType.ARRAY_GET_RANK);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Sets the value at a specified index in an array on the target runtime.
*
* @param indexes Indexes to set the value at.
* @param value The new value to set the array element to.
* @return InvocationContext instance with the command to set the array element.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext setIndex(Object indexes, Object value) {
Command localCommand = new Command(this.runtimeName, CommandType.ARRAY_SET_ITEM, indexes, value);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Invokes a generic static method on the target runtime.
*
* @param methodName The name of the method to invoke.
* @param args The arguments to pass to the generic static method. Depends on called runtime technology.
* @return InvocationContext instance with the command to invoke the generic static method.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext invokeGenericStaticMethod(String methodName, Object... args) {
Command localCommand = new Command(this.runtimeName, CommandType.INVOKE_GENERIC_STATIC_METHOD, createArgsArray(methodName, args));
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Invokes a generic instance method on the target runtime.
*
* @param methodName The name of the method to invoke.
* @param args The arguments to pass to the generic static method. Depends on called runtime technology.
* @return InvocationContext instance with the command to invoke the generic instance method.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext invokeGenericMethod(String methodName, Object... args) {
Command localCommand = new Command(this.runtimeName, CommandType.INVOKE_GENERIC_METHOD, createArgsArray(methodName, args));
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the name of an enum value from the target runtime.
*
* @return InvocationContext instance that wraps the command to get the enum name.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getEnumName() {
Command localCommand = new Command(this.runtimeName, CommandType.GET_ENUM_NAME);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the value of an enum from the target runtime.
*
* @return InvocationContext instance that wraps the command to get the enum value.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getEnumValue() {
Command localCommand = new Command(this.runtimeName, CommandType.GET_ENUM_VALUE);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Retrieves the value of a reference type argument from the target runtime.
*
* @return InvocationContext instance with the command to get the reference value.
* @see Article on Javonet Guides
*/
@Override
public InvocationContext getRefValue() {
Command localCommand = new Command(this.runtimeName, CommandType.GET_REF_VALUE);
return new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
}
/**
* Returns the primitive value from the target runtime. This could be any primitive type in Java,
* such as int, boolean, byte, char, long, double, float, etc.
*
* @return the value from the target runtime.
*/
public Object getValue() {
resultValue = currentCommand.getPayload()[0];
return resultValue;
}
/**
* Retrieves an array from the target runtime.
*
* @param args the arguments for the retrieve array command.
* @return the retrieved array.
*/
public Object[] retrieveArray(Object... args) {
Command localCommand = new Command(this.runtimeName, CommandType.RETRIEVE_ARRAY, args);
InvocationContext localInvCtx = new InvocationContext(this.runtimeName, this.connectionType, this.tcpConnectionData, buildCommand(localCommand));
localInvCtx.execute();
Object[] responseArray = (Object[]) java.lang.reflect.Array.newInstance(localInvCtx.responseCommand.getPayload()[0].getClass(), localInvCtx.responseCommand.getPayload().length);
responseArray = localInvCtx.responseCommand.getPayload().clone();
return responseArray;
}
private Command buildCommand(Command command) {
for (int i = 0; i < command.getPayload().length; i++) {
command.setPayload(encapsulatePayloadItem(command.getPayload()[i]), i);
}
return command.prependArgumentToPayload(this.currentCommand);
}
private Command encapsulatePayloadItem(Object payloadItem) {
if (payloadItem instanceof Command) {
for (int i = 0; i < (((Command) payloadItem).getPayload()).length; i++) {
((Command) payloadItem).setPayload(encapsulatePayloadItem(((Command) payloadItem).getPayload()[i]), i);
}
return (Command) payloadItem;
} else if (payloadItem instanceof InvocationContext) {
return ((InvocationContext) payloadItem).getCurrentCommand();
} else if (payloadItem.getClass().isArray()) {
Object[] objectArray = new Object[((Object[]) payloadItem).length];
for (int i = 0; i < ((Object[]) payloadItem).length; i++) {
objectArray[i] = encapsulatePayloadItem(((Object[]) payloadItem)[i]);
}
return new Command(this.runtimeName, CommandType.ARRAY, objectArray);
} else {
return new Command(this.runtimeName, CommandType.VALUE, payloadItem);
}
}
private Object[] createArgsArray(Object arg1, Object... args) {
Object[] argsArray = Arrays.copyOf(new Object[]{arg1}, args.length + 1);
System.arraycopy(args, 0, argsArray, 1, args.length);
return argsArray;
}
}