001package Torello.Browser;
002
003import Torello.Java.Additional.Ret0;
004import Torello.Java.Additional.RetN;// Needed for @link
005
006import java.util.Objects;
007import java.util.function.Function;
008import javax.json.JsonObject; 
009
010/**
011 * The class script simply sends an asynchronous request, and returns an instance of {@link Promise}
012 * which may be awaited.
013 * 
014 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=SCRIPT>
015 * 
016 * @param <RESULT>
017 * <a id=typeParam-RESULT></a>
018 * <EMBED CLASS='external-html' DATA-FILE-ID=RESULT>
019 */
020public class Script<RESULT> implements java.io.Serializable
021{
022    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
023    protected static final long serialVersionUID = 1;
024
025    /** The Browser or Java-Script Domain which maintains the external browser command. */
026    public final Domains domain;
027
028    /** The Name of the Web-Browser Command that is being executed by this {@code Script}. */
029    public final String commandName;
030
031    /** The request-{@code String} that will be sent over the Web-Socket */
032    public final String requestJSONString;
033
034    /**
035     * This function pointer performs the <I><B STYLE='color: red;'>Json-Binding</B></I> needed to
036     * convert a browser-generated {@link JsonObject} into a Java POJO (ultimately having type
037     * {@code 'RESULT'}).
038     */
039    public final Function<JsonObject, RESULT> receiver;
040
041    /**
042     * The Java-{@code Class} / Type of the post-processed object which is ultimately returned by
043     * this browser command.  This {@code public, final} field is nothing more than a "reified"
044     * Java Generic Type-Parameter for this class'
045     * <B><A HREF='#typeParam-RESULT'>{@code <RESULT>}</A></B> generic type.
046     */
047    public final Class<RESULT> resultClass;
048
049    /**
050     * 
051     * @param domain The domain in which this command is defined
052     * @param commandName The name of the command, as per the Google CDP API
053     * @param requestJSONString The command, formulated a a JSON request
054     * 
055     * @param receiver This is a function pointer which "translates" the browser's JSON response
056     * into a Java {@link RetN} POJO.
057     * 
058     * @param resultClass This is used solely to facilate {@code javac's} type parameter "capture"
059     * logic.
060     */
061    @SuppressWarnings("unchecked")
062    public Script(
063            final Domains                       domain,
064            final String                        commandName,
065            final String                        requestJSONString,
066            final Function<JsonObject, RESULT>  receiver,
067            final Class<?>                      resultClass
068        )
069    {
070        this.requestJSONString  = requestJSONString;
071        this.receiver           = receiver;
072        this.domain             = domain;
073        this.commandName        = commandName;
074
075        // This may seem silly, and it is, but occasionally, that happens
076        this.resultClass = (Class<RESULT>) resultClass;
077    }
078
079    /**
080     * This is a pre-defined, and repeatedly used, CDP browser response translator function.  This
081     * is defined solely for use with the static builder method named {@link #NO_RET}.
082     * @see #NO_RET(Domains, String, String)
083     */
084    public static final Function<JsonObject, Void> NO_RETURN_VALUES = (JsonObject jo) -> null;
085
086    /**
087     * This is used as an alternative to a constructor, since the type parameter
088     * <A HREF='#type-parameter-RESULT'><CODE>RESULT</CODE></A> is restricted to the class
089     * {@link Ret0}.
090     * 
091     * @param domain The domain in which this command is defined
092     * @param commandName The name of the command, as per the Google CDP API
093     * @param requestJSONString The command, formulated a a JSON request
094     * 
095     * @see #NO_RETURN_VALUES
096     */
097    public static Script<Void> NO_RET(
098            final Domains   domain,
099            final String    commandName,
100            final String    requestJSONString
101        )
102    { return new Script<>(domain, commandName, requestJSONString, NO_RETURN_VALUES, Void.class); }
103
104
105    /**
106     * If there are reasons to use a different sender - <I>because certain configurations need to
107     * change</I> - then using this {@code exec} method allows a user to change senders.
108     * 
109     * @param wss The {@link WebSocketSender} Instance to use when executing this {@link Script}
110     * object-instance.  
111     * 
112     * <BR /><BR />In the Browser Remote Debug Package (Headless Chrome), the {@code 'Script'} 
113     * instances which are generated expect the user to provide their own constructed
114     * {@code WebSocketSender} instances to facilitate:
115     * 
116     * <BR /><BR /><UL CLASS=JDUL>
117     * <LI>Pre-Compiling Scripts ahead of time for future use, using future Browser-Connections</LI>
118     * <LI>Utilizing alternate &amp; various Page-Connections, for different Open-Pages</LI>
119     * <LI>Re-using Pre-Compiled Script Components</LI>
120     * </UL>
121     * 
122     * @return <EMBED CLASS='external-html' DATA-FILE-ID=SCRIPTRET>
123     */
124    public Promise<RESULT> exec(final WebSocketSender wss)
125    {
126        final Promise<RESULT> promise = new Promise<>(this);
127        wss.send(this, promise);
128        return promise;
129    }
130}