1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package Torello.Browser;

import Torello.Browser.WebSocketSender;
import Torello.Java.StorageWriter;
import Torello.Java.StrPrint;
import Torello.Java.Additional.Promise;
import Torello.Java.Additional.AppendableSafe;
import Torello.Java.Additional.AsynchronousException;

import java.io.StringReader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

import javax.json.JsonObject;
import javax.json.Json;

import static Torello.Java.C.BGREEN_BKGND;
import static Torello.Java.C.RESET;


// ************************************************************************************************
// ************************************************************************************************
// Chat-GPT wrote the summary below: July 20th, 2025 - VERY ACCURATE!
// ************************************************************************************************
// ************************************************************************************************
// 
// 
// Package-private class that serves as the main dispatcher for all incoming WebSocket messages
// received from the browser. It determines whether each message is a response to a prior command,
// a CDP event, or something else (like a malformed payload), and routes it appropriately.
//
// This class is the central entry point for JSON message handling logic. Depending on the shape of
// the incoming JSON, it will forward the object to either HandleScriptResponse, HandleEvent, or 
// log an error if the message is unrecognized.
// 
// 
// ************************************************************************************************
// ************************************************************************************************
// My Points (after reading the above computer generated explanation)
// ************************************************************************************************
// ************************************************************************************************
// 
// class WebSocketSender is used as the "Connection Class" to the NeoVisionaries WebSocket Driver
// Whenever NeoVisionaries has a "payload" or "message" to pass back to our code, it will be:
// 
//  * A "Command Response Message" with a "Response ID" that is tied to a previous Command
// 
//  * An "Event Message" that does not have a "Response ID" - but just (sort of) "Happened" inside
//    of the Web-Browser and is being returned to us.
// 
// For either type of Message, the NeoVisionaries.WebSocket will invoke our WebSocketSender class
// with a response message, and that class calls THIS CLASS to do analyze the Message, and decide
// whether to invoke:
// 
// * HandleScriptResponse.java
// * HandleEvent.java

class HandleDispatch 
{
    // Top-Level Handler
    // The Browser has sent a message about a particular Send-Request.  Report this response
    // to the promise.

    static void handle(
            final String                                                message,
            final WebSocketSender                                       THIS,
            final ConcurrentHashMap<Integer, Promise<JsonObject, ?>>    promises
        )
    {
        final AppendableSafe        app             = THIS.app();
        final AppendableSafe        err             = THIS.err();
        final Consumer<RDPError>    rdpErrorHandler = THIS.rdpErrorHandler;

        final JsonObject jo = Json
            .createReader(new StringReader(message))
            .readObject();

        final int       idReceived  = jo.getInt("id", -1);
        final String    method      = jo.getString("method", null);

        app
            .append(BGREEN_BKGND + " Received Browser Message: " + RESET + '\n')
            .append(PrintUtil.json(jo))
            .append('\n');


        // If the WebSocket Message had an ID, then that ID should map to one of the Promises
        // stored in the TreeMap.
        // 
        // The '-1' is the "Default Value" that is assigned, above, in the JsonObjet.getInt
        // Method.


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // CASE: Command-Response Message
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        if (idReceived != -1)
        {
            final Promise<JsonObject, ? extends Object> promise = promises.remove(idReceived);

            if (promise == null)
            {
                final String errMsg = 
                    "ID Received: [" + idReceived + "], is unknown, or already handled.\n" +
                    "There was no 'Promise' Instance matching this ID.";

                PrintUtil.ERR(THIS, errMsg, jo);
                rdpErrorHandler.accept(new RDPError(errMsg, jo));
                return;
            }

            else HandleScriptResponse.handle(idReceived, promise, jo, THIS);
        }


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // CASE: Browser-Event Message
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        else if (method != null) HandleEvent.handle(jo, method, THIS);


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // CASE: Ooops / Unknown - Neither a "Command Response" nor an "Event" Message
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        else
        {
            final String errMsg = "Unrecognized Browser Message Received";
            PrintUtil.ERR(THIS, errMsg, jo);
            rdpErrorHandler.accept(new RDPError(errMsg, jo));
            return;
        }
    }
}