001package Torello.Browser; 002 003import java.util.*; 004import javax.json.*; 005import javax.json.stream.*; 006import java.io.*; 007 008import java.lang.reflect.Method; 009import java.lang.reflect.Parameter; 010import java.util.function.Function; 011 012import Torello.Java.Additional.*; 013import Torello.Java.JSON.*; 014 015import static Torello.Java.JSON.JFlag.*; 016 017import Torello.Java.StrCmpr; 018import Torello.JavaDoc.StaticFunctional; 019import Torello.JavaDoc.JDHeaderBackgroundImg; 020import Torello.JavaDoc.Excuse; 021 022/** 023 * <SPAN CLASS=COPIEDJDK><B>Defines events for background web platform features.</B></SPAN> 024 * 025 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE> 026 */ 027@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION}) 028@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE") 029public class BackgroundService 030{ 031 // ******************************************************************************************** 032 // ******************************************************************************************** 033 // Class Header Stuff 034 // ******************************************************************************************** 035 // ******************************************************************************************** 036 037 038 // No Pubic Constructors 039 private BackgroundService () { } 040 041 // These two Vector's are used by all the "Methods" exported by this class. java.lang.reflect 042 // is used to generate the JSON String's. It saves thousands of lines of Auto-Generated Code. 043 private static final Map<String, Vector<String>> parameterNames = new HashMap<>(); 044 private static final Map<String, Vector<Class<?>>> parameterTypes = new HashMap<>(); 045 046 // Some Methods do not take any parameters - for instance all the "enable()" and "disable()" 047 // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now, 048 // offically, two empty-vectors. One for String's, and the other for Classes. 049 050 private static final Vector<String> EMPTY_VEC_STR = new Vector<>(); 051 private static final Vector<Class<?>> EMPTY_VEC_CLASS = new Vector<>(); 052 053 static 054 { 055 for (Method m : BackgroundService.class.getMethods()) 056 { 057 // This doesn't work! The parameter names are all "arg0" ... "argN" 058 // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter! 059 // 060 // Vector<String> parameterNamesList = new Vector<>(); -- NOPE! 061 062 Vector<Class<?>> parameterTypesList = new Vector<>(); 063 064 for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType()); 065 066 parameterTypes.put( 067 m.getName(), 068 (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS 069 ); 070 } 071 } 072 073 static 074 { 075 Vector<String> v = null; 076 077 v = new Vector<String>(1); 078 parameterNames.put("startObserving", v); 079 Collections.addAll(v, new String[] 080 { "service", }); 081 082 v = new Vector<String>(1); 083 parameterNames.put("stopObserving", v); 084 Collections.addAll(v, new String[] 085 { "service", }); 086 087 v = new Vector<String>(2); 088 parameterNames.put("setRecording", v); 089 Collections.addAll(v, new String[] 090 { "shouldRecord", "service", }); 091 092 v = new Vector<String>(1); 093 parameterNames.put("clearEvents", v); 094 Collections.addAll(v, new String[] 095 { "service", }); 096 } 097 098 099 // ******************************************************************************************** 100 // ******************************************************************************************** 101 // Types - Static Inner Classes 102 // ******************************************************************************************** 103 // ******************************************************************************************** 104 105 /** 106 * The Background Service that will be associated with the commands/events. 107 * Every Background Service operates independently, but they share the same 108 * API. 109 */ 110 public static final String[] ServiceName = 111 { 112 "backgroundFetch", "backgroundSync", "pushMessaging", "notifications", "paymentHandler", 113 "periodicBackgroundSync", 114 }; 115 116 /** A key-value pair for additional event information to pass along. */ 117 public static class EventMetadata 118 extends BaseType 119 implements java.io.Serializable 120 { 121 /** For Object Serialization. java.io.Serializable */ 122 protected static final long serialVersionUID = 1; 123 124 public boolean[] optionals() 125 { return new boolean[] { false, false, }; } 126 127 /** <CODE>[No Description Provided by Google]</CODE> */ 128 public final String key; 129 130 /** <CODE>[No Description Provided by Google]</CODE> */ 131 public final String value; 132 133 /** 134 * Constructor 135 * 136 * @param key - 137 * 138 * @param value - 139 */ 140 public EventMetadata(String key, String value) 141 { 142 // Exception-Check(s) to ensure that if any parameters which are not declared as 143 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 144 145 if (key == null) THROWS.throwNPE("key"); 146 if (value == null) THROWS.throwNPE("value"); 147 148 this.key = key; 149 this.value = value; 150 } 151 152 /** 153 * JSON Object Constructor 154 * @param jo A Json-Object having data about an instance of {@code 'EventMetadata'}. 155 */ 156 public EventMetadata (JsonObject jo) 157 { 158 this.key = ReadJSON.getString(jo, "key", false, true); 159 this.value = ReadJSON.getString(jo, "value", false, true); 160 } 161 162 163 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 164 public boolean equals(Object other) 165 { 166 if (this == other) return true; 167 if (other == null) return false; 168 if (other.getClass() != this.getClass()) return false; 169 170 EventMetadata o = (EventMetadata) other; 171 172 return 173 Objects.equals(this.key, o.key) 174 && Objects.equals(this.value, o.value); 175 } 176 177 /** Generates a Hash-Code for {@code 'this'} instance */ 178 public int hashCode() 179 { 180 return 181 Objects.hashCode(this.key) 182 + Objects.hashCode(this.value); 183 } 184 } 185 186 /** <CODE>[No Description Provided by Google]</CODE> */ 187 public static class BackgroundServiceEvent 188 extends BaseType 189 implements java.io.Serializable 190 { 191 /** For Object Serialization. java.io.Serializable */ 192 protected static final long serialVersionUID = 1; 193 194 public boolean[] optionals() 195 { return new boolean[] { false, false, false, false, false, false, false, }; } 196 197 /** Timestamp of the event (in seconds). */ 198 public final Number timestamp; 199 200 /** The origin this event belongs to. */ 201 public final String origin; 202 203 /** The Service Worker ID that initiated the event. */ 204 public final String serviceWorkerRegistrationId; 205 206 /** The Background Service this event belongs to. */ 207 public final String service; 208 209 /** A description of the event. */ 210 public final String eventName; 211 212 /** An identifier that groups related events together. */ 213 public final String instanceId; 214 215 /** A list of event-specific information. */ 216 public final BackgroundService.EventMetadata[] eventMetadata; 217 218 /** 219 * Constructor 220 * 221 * @param timestamp Timestamp of the event (in seconds). 222 * 223 * @param origin The origin this event belongs to. 224 * 225 * @param serviceWorkerRegistrationId The Service Worker ID that initiated the event. 226 * 227 * @param service The Background Service this event belongs to. 228 * 229 * @param eventName A description of the event. 230 * 231 * @param instanceId An identifier that groups related events together. 232 * 233 * @param eventMetadata A list of event-specific information. 234 */ 235 public BackgroundServiceEvent( 236 Number timestamp, String origin, String serviceWorkerRegistrationId, String service, 237 String eventName, String instanceId, BackgroundService.EventMetadata[] eventMetadata 238 ) 239 { 240 // Exception-Check(s) to ensure that if any parameters which are not declared as 241 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 242 243 if (timestamp == null) THROWS.throwNPE("timestamp"); 244 if (origin == null) THROWS.throwNPE("origin"); 245 if (serviceWorkerRegistrationId == null) THROWS.throwNPE("serviceWorkerRegistrationId"); 246 if (service == null) THROWS.throwNPE("service"); 247 if (eventName == null) THROWS.throwNPE("eventName"); 248 if (instanceId == null) THROWS.throwNPE("instanceId"); 249 if (eventMetadata == null) THROWS.throwNPE("eventMetadata"); 250 251 // Exception-Check(s) to ensure that if any parameters which must adhere to a 252 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 253 254 THROWS.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName); 255 256 this.timestamp = timestamp; 257 this.origin = origin; 258 this.serviceWorkerRegistrationId = serviceWorkerRegistrationId; 259 this.service = service; 260 this.eventName = eventName; 261 this.instanceId = instanceId; 262 this.eventMetadata = eventMetadata; 263 } 264 265 /** 266 * JSON Object Constructor 267 * @param jo A Json-Object having data about an instance of {@code 'BackgroundServiceEvent'}. 268 */ 269 public BackgroundServiceEvent (JsonObject jo) 270 { 271 this.timestamp = ReadNumberJSON.get(jo, "timestamp", false, true); 272 this.origin = ReadJSON.getString(jo, "origin", false, true); 273 this.serviceWorkerRegistrationId = ReadJSON.getString(jo, "serviceWorkerRegistrationId", false, true); 274 this.service = ReadJSON.getString(jo, "service", false, true); 275 this.eventName = ReadJSON.getString(jo, "eventName", false, true); 276 this.instanceId = ReadJSON.getString(jo, "instanceId", false, true); 277 this.eventMetadata = (jo.getJsonArray("eventMetadata") == null) 278 ? null 279 : RJArrIntoStream.objArr(jo.getJsonArray("eventMetadata"), null, 0, BackgroundService.EventMetadata.class).toArray(BackgroundService.EventMetadata[]::new); 280 281 } 282 283 284 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 285 public boolean equals(Object other) 286 { 287 if (this == other) return true; 288 if (other == null) return false; 289 if (other.getClass() != this.getClass()) return false; 290 291 BackgroundServiceEvent o = (BackgroundServiceEvent) other; 292 293 return 294 Objects.equals(this.timestamp, o.timestamp) 295 && Objects.equals(this.origin, o.origin) 296 && Objects.equals(this.serviceWorkerRegistrationId, o.serviceWorkerRegistrationId) 297 && Objects.equals(this.service, o.service) 298 && Objects.equals(this.eventName, o.eventName) 299 && Objects.equals(this.instanceId, o.instanceId) 300 && Arrays.deepEquals(this.eventMetadata, o.eventMetadata); 301 } 302 303 /** Generates a Hash-Code for {@code 'this'} instance */ 304 public int hashCode() 305 { 306 return 307 Objects.hashCode(this.timestamp) 308 + Objects.hashCode(this.origin) 309 + Objects.hashCode(this.serviceWorkerRegistrationId) 310 + Objects.hashCode(this.service) 311 + Objects.hashCode(this.eventName) 312 + Objects.hashCode(this.instanceId) 313 + Arrays.deepHashCode(this.eventMetadata); 314 } 315 } 316 317 /** Called when the recording state for the service has been updated. */ 318 public static class recordingStateChanged 319 extends BrowserEvent 320 implements java.io.Serializable 321 { 322 /** For Object Serialization. java.io.Serializable */ 323 protected static final long serialVersionUID = 1; 324 325 public boolean[] optionals() 326 { return new boolean[] { false, false, }; } 327 328 /** <CODE>[No Description Provided by Google]</CODE> */ 329 public final boolean isRecording; 330 331 /** <CODE>[No Description Provided by Google]</CODE> */ 332 public final String service; 333 334 /** 335 * Constructor 336 * 337 * @param isRecording - 338 * 339 * @param service - 340 */ 341 public recordingStateChanged(boolean isRecording, String service) 342 { 343 super("BackgroundService", "recordingStateChanged", 2); 344 345 // Exception-Check(s) to ensure that if any parameters which are not declared as 346 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 347 348 if (service == null) THROWS.throwNPE("service"); 349 350 // Exception-Check(s) to ensure that if any parameters which must adhere to a 351 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 352 353 THROWS.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName); 354 355 this.isRecording = isRecording; 356 this.service = service; 357 } 358 359 /** 360 * JSON Object Constructor 361 * @param jo A Json-Object having data about an instance of {@code 'recordingStateChanged'}. 362 */ 363 public recordingStateChanged (JsonObject jo) 364 { 365 super("BackgroundService", "recordingStateChanged", 2); 366 367 this.isRecording = ReadPrimJSON.getBoolean(jo, "isRecording"); 368 this.service = ReadJSON.getString(jo, "service", false, true); 369 } 370 371 372 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 373 public boolean equals(Object other) 374 { 375 if (this == other) return true; 376 if (other == null) return false; 377 if (other.getClass() != this.getClass()) return false; 378 379 recordingStateChanged o = (recordingStateChanged) other; 380 381 return 382 (this.isRecording == o.isRecording) 383 && Objects.equals(this.service, o.service); 384 } 385 386 /** Generates a Hash-Code for {@code 'this'} instance */ 387 public int hashCode() 388 { 389 return 390 (this.isRecording ? 1 : 0) 391 + Objects.hashCode(this.service); 392 } 393 } 394 395 /** 396 * Called with all existing backgroundServiceEvents when enabled, and all new 397 * events afterwards if enabled and recording. 398 */ 399 public static class backgroundServiceEventReceived 400 extends BrowserEvent 401 implements java.io.Serializable 402 { 403 /** For Object Serialization. java.io.Serializable */ 404 protected static final long serialVersionUID = 1; 405 406 public boolean[] optionals() 407 { return new boolean[] { false, }; } 408 409 /** <CODE>[No Description Provided by Google]</CODE> */ 410 public final BackgroundService.BackgroundServiceEvent backgroundServiceEvent; 411 412 /** 413 * Constructor 414 * 415 * @param backgroundServiceEvent - 416 */ 417 public backgroundServiceEventReceived 418 (BackgroundService.BackgroundServiceEvent backgroundServiceEvent) 419 { 420 super("BackgroundService", "backgroundServiceEventReceived", 1); 421 422 // Exception-Check(s) to ensure that if any parameters which are not declared as 423 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 424 425 if (backgroundServiceEvent == null) THROWS.throwNPE("backgroundServiceEvent"); 426 427 this.backgroundServiceEvent = backgroundServiceEvent; 428 } 429 430 /** 431 * JSON Object Constructor 432 * @param jo A Json-Object having data about an instance of {@code 'backgroundServiceEventReceived'}. 433 */ 434 public backgroundServiceEventReceived (JsonObject jo) 435 { 436 super("BackgroundService", "backgroundServiceEventReceived", 1); 437 438 this.backgroundServiceEvent = ReadJSON.getObject(jo, "backgroundServiceEvent", BackgroundService.BackgroundServiceEvent.class, false, true); 439 } 440 441 442 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 443 public boolean equals(Object other) 444 { 445 if (this == other) return true; 446 if (other == null) return false; 447 if (other.getClass() != this.getClass()) return false; 448 449 backgroundServiceEventReceived o = (backgroundServiceEventReceived) other; 450 451 return 452 Objects.equals(this.backgroundServiceEvent, o.backgroundServiceEvent); 453 } 454 455 /** Generates a Hash-Code for {@code 'this'} instance */ 456 public int hashCode() 457 { 458 return 459 this.backgroundServiceEvent.hashCode(); 460 } 461 } 462 463 464 // Counter for keeping the WebSocket Request ID's distinct. 465 private static int counter = 1; 466 467 /** 468 * Enables event updates for the service. 469 * 470 * @param service - 471 * 472 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 473 * {@link Ret0}></CODE> 474 * 475 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 476 * browser receives the invocation-request. 477 * 478 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 479 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 480 * {@code >} to ensure the Browser Function has run to completion. 481 */ 482 public static Script<String, JsonObject, Ret0> startObserving(String service) 483 { 484 // Exception-Check(s) to ensure that if any parameters which are not declared as 485 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 486 487 if (service == null) THROWS.throwNPE("service"); 488 489 // Exception-Check(s) to ensure that if any parameters which must adhere to a 490 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 491 492 THROWS.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName); 493 494 final int webSocketID = 10000000 + counter++; 495 final boolean[] optionals = { false, }; 496 497 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 498 String requestJSON = WriteJSON.get( 499 parameterTypes.get("startObserving"), 500 parameterNames.get("startObserving"), 501 optionals, webSocketID, 502 "BackgroundService.startObserving", 503 service 504 ); 505 506 // This Remote Command does not have a Return-Value. 507 return new Script<> 508 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 509 } 510 511 /** 512 * Disables event updates for the service. 513 * 514 * @param service - 515 * 516 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 517 * {@link Ret0}></CODE> 518 * 519 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 520 * browser receives the invocation-request. 521 * 522 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 523 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 524 * {@code >} to ensure the Browser Function has run to completion. 525 */ 526 public static Script<String, JsonObject, Ret0> stopObserving(String service) 527 { 528 // Exception-Check(s) to ensure that if any parameters which are not declared as 529 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 530 531 if (service == null) THROWS.throwNPE("service"); 532 533 // Exception-Check(s) to ensure that if any parameters which must adhere to a 534 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 535 536 THROWS.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName); 537 538 final int webSocketID = 10001000 + counter++; 539 final boolean[] optionals = { false, }; 540 541 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 542 String requestJSON = WriteJSON.get( 543 parameterTypes.get("stopObserving"), 544 parameterNames.get("stopObserving"), 545 optionals, webSocketID, 546 "BackgroundService.stopObserving", 547 service 548 ); 549 550 // This Remote Command does not have a Return-Value. 551 return new Script<> 552 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 553 } 554 555 /** 556 * Set the recording state for the service. 557 * 558 * @param shouldRecord - 559 * 560 * @param service - 561 * 562 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 563 * {@link Ret0}></CODE> 564 * 565 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 566 * browser receives the invocation-request. 567 * 568 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 569 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 570 * {@code >} to ensure the Browser Function has run to completion. 571 */ 572 public static Script<String, JsonObject, Ret0> setRecording 573 (boolean shouldRecord, String service) 574 { 575 // Exception-Check(s) to ensure that if any parameters which are not declared as 576 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 577 578 if (service == null) THROWS.throwNPE("service"); 579 580 // Exception-Check(s) to ensure that if any parameters which must adhere to a 581 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 582 583 THROWS.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName); 584 585 final int webSocketID = 10002000 + counter++; 586 final boolean[] optionals = { false, false, }; 587 588 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 589 String requestJSON = WriteJSON.get( 590 parameterTypes.get("setRecording"), 591 parameterNames.get("setRecording"), 592 optionals, webSocketID, 593 "BackgroundService.setRecording", 594 shouldRecord, service 595 ); 596 597 // This Remote Command does not have a Return-Value. 598 return new Script<> 599 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 600 } 601 602 /** 603 * Clears all stored data for the service. 604 * 605 * @param service - 606 * 607 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 608 * {@link Ret0}></CODE> 609 * 610 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 611 * browser receives the invocation-request. 612 * 613 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 614 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 615 * {@code >} to ensure the Browser Function has run to completion. 616 */ 617 public static Script<String, JsonObject, Ret0> clearEvents(String service) 618 { 619 // Exception-Check(s) to ensure that if any parameters which are not declared as 620 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 621 622 if (service == null) THROWS.throwNPE("service"); 623 624 // Exception-Check(s) to ensure that if any parameters which must adhere to a 625 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 626 627 THROWS.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName); 628 629 final int webSocketID = 10003000 + counter++; 630 final boolean[] optionals = { false, }; 631 632 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 633 String requestJSON = WriteJSON.get( 634 parameterTypes.get("clearEvents"), 635 parameterNames.get("clearEvents"), 636 optionals, webSocketID, 637 "BackgroundService.clearEvents", 638 service 639 ); 640 641 // This Remote Command does not have a Return-Value. 642 return new Script<> 643 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 644 } 645 646}