You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractJavaScriptExtension.java 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal;
  5. import com.vaadin.shared.JavaScriptExtensionState;
  6. import com.vaadin.ui.JavaScriptCallback;
  7. /**
  8. * Base class for Extensions with all client-side logic implemented using
  9. * JavaScript.
  10. * <p>
  11. * When a new JavaScript extension is initialized in the browser, the framework
  12. * will look for a globally defined JavaScript function that will initialize the
  13. * extension. The name of the initialization function is formed by replacing .
  14. * with _ in the name of the server-side class. If no such function is defined,
  15. * each super class is used in turn until a match is found. The framework will
  16. * thus first attempt with <code>com_example_MyExtension</code> for the
  17. * server-side
  18. * <code>com.example.MyExtension extends AbstractJavaScriptExtension</code>
  19. * class. If MyExtension instead extends <code>com.example.SuperExtension</code>
  20. * , then <code>com_example_SuperExtension</code> will also be attempted if
  21. * <code>com_example_MyExtension</code> has not been defined.
  22. * <p>
  23. *
  24. * The initialization function will be called with <code>this</code> pointing to
  25. * a connector wrapper object providing integration to Vaadin with the following
  26. * functions:
  27. * <ul>
  28. * <li><code>getConnectorId()</code> - returns a string with the id of the
  29. * connector.</li>
  30. * <li><code>getParentId([connectorId])</code> - returns a string with the id of
  31. * the connector's parent. If <code>connectorId</code> is provided, the id of
  32. * the parent of the corresponding connector with the passed id is returned
  33. * instead.</li>
  34. * <li><code>getElement([connectorId])</code> - returns the DOM Element that is
  35. * the root of a connector's widget. <code>null</code> is returned if the
  36. * connector can not be found or if the connector doesn't have a widget. If
  37. * <code>connectorId</code> is not provided, the connector id of the current
  38. * connector will be used.</li>
  39. * <li><code>getState()</code> - returns an object corresponding to the shared
  40. * state defined on the server. The scheme for conversion between Java and
  41. * JavaScript types is described bellow.</li>
  42. * <li><code>registerRpc([name, ] rpcObject)</code> - registers the
  43. * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an
  44. * object with field containing functions for all eligible RPC functions. If
  45. * <code>name</code> is provided, the RPC handler will only used for RPC calls
  46. * for the RPC interface with the same fully qualified Java name. If no
  47. * <code>name</code> is provided, the RPC handler will be used for all incoming
  48. * RPC invocations where the RPC method name is defined as a function field in
  49. * the handler. The scheme for conversion between Java types in the RPC
  50. * interface definition and the JavaScript values passed as arguments to the
  51. * handler functions is described bellow.</li>
  52. * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If
  53. * <code>name</code> is provided, the proxy object will contain functions for
  54. * all methods in the RPC interface with the same fully qualified name, provided
  55. * a RPC handler has been registered by the server-side code. If no
  56. * <code>name</code> is provided, the returned RPC proxy object will contain
  57. * functions for all methods in all RPC interfaces registered for the connector
  58. * on the server. If the same method name is present in multiple registered RPC
  59. * interfaces, the corresponding function in the RPC proxy object will throw an
  60. * exception when called. The scheme for conversion between Java types in the
  61. * RPC interface and the JavaScript values that should be passed to the
  62. * functions is described bellow.</li>
  63. * </ul>
  64. * The connector wrapper also supports these special functions:
  65. * <ul>
  66. * <li><code>onStateChange</code> - If the JavaScript code assigns a function to
  67. * the field, that function is called whenever the contents of the shared state
  68. * is changed.</li>
  69. * <li>Any field name corresponding to a call to
  70. * {@link #registerCallback(String, JavaScriptCallback)} on the server will
  71. * automatically be present as a function that triggers the registered callback
  72. * on the server.</li>
  73. * <li>Any field name referred to using
  74. * {@link #invokeCallback(String, Object...)} on the server will be called if a
  75. * function has been assigned to the field.</li>
  76. * </ul>
  77. * <p>
  78. *
  79. * Values in the Shared State and in RPC calls are converted between Java and
  80. * JavaScript using the following conventions:
  81. * <ul>
  82. * <li>Primitive Java numbers (byte, char, int, long, float, double) and their
  83. * boxed types (Byte, Character, Integer, Long, Float, Double) are represented
  84. * by JavaScript numbers.</li>
  85. * <li>The primitive Java boolean and the boxed Boolean are represented by
  86. * JavaScript booleans.</li>
  87. * <li>Java Strings are represented by JavaScript strings.</li>
  88. * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
  89. * <li>Map<String, ?> in Java is represented by JavaScript object with fields
  90. * corresponding to the map keys.</li>
  91. * <li>Any other Java Map is represented by a JavaScript array containing two
  92. * arrays, the first contains the keys and the second contains the values in the
  93. * same order.</li>
  94. * <li>A Java Bean is represented by a JavaScript object with fields
  95. * corresponding to the bean's properties.</li>
  96. * <li>A Java Connector is represented by a JavaScript string containing the
  97. * connector's id.</li>
  98. * <li>A pluggable serialization mechanism is provided for types not described
  99. * here. Please refer to the documentation for specific types for serialization
  100. * information.</li>
  101. * </ul>
  102. *
  103. * @author Vaadin Ltd
  104. * @version @VERSION@
  105. * @since 7.0.0
  106. */
  107. public abstract class AbstractJavaScriptExtension extends AbstractExtension {
  108. private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
  109. this);
  110. @Override
  111. protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
  112. super.registerRpc(implementation, rpcInterfaceType);
  113. callbackHelper.registerRpc(rpcInterfaceType);
  114. }
  115. /**
  116. * Register a {@link JavaScriptCallback} that can be called from the
  117. * JavaScript using the provided name. A JavaScript function with the
  118. * provided name will be added to the connector wrapper object (initially
  119. * available as <code>this</code>). Calling that JavaScript function will
  120. * cause the call method in the registered {@link JavaScriptCallback} to be
  121. * invoked with the same arguments.
  122. *
  123. * @param functionName
  124. * the name that should be used for client-side callback
  125. * @param javaScriptCallback
  126. * the callback object that will be invoked when the JavaScript
  127. * function is called
  128. */
  129. protected void registerCallback(String functionName,
  130. JavaScriptCallback javaScriptCallback) {
  131. callbackHelper.registerCallback(functionName, javaScriptCallback);
  132. }
  133. /**
  134. * Invoke a named function that the connector JavaScript has added to the
  135. * JavaScript connector wrapper object. The arguments should only contain
  136. * data types that can be represented in JavaScript including primitives,
  137. * their boxed types, arrays, String, List, Set, Map, Connector and
  138. * JavaBeans.
  139. *
  140. * @param name
  141. * the name of the function
  142. * @param arguments
  143. * function arguments
  144. */
  145. protected void invokeCallback(String name, Object... arguments) {
  146. callbackHelper.invokeCallback(name, arguments);
  147. }
  148. @Override
  149. public JavaScriptExtensionState getState() {
  150. return (JavaScriptExtensionState) super.getState();
  151. }
  152. }