All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.javonet.sdk.InvocationContext Maven / Gradle / Ivy

Go to download

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/

There is a newer version: 2.4.5
Show newest version
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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy