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.

AbstractConnector.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.ArrayList;
  6. import java.util.Collection;
  7. import java.util.Collections;
  8. import java.util.HashMap;
  9. import java.util.List;
  10. import java.util.Map;
  11. import com.google.gwt.event.shared.GwtEvent;
  12. import com.google.gwt.event.shared.HandlerManager;
  13. import com.google.web.bindery.event.shared.HandlerRegistration;
  14. import com.vaadin.shared.communication.ClientRpc;
  15. import com.vaadin.shared.communication.SharedState;
  16. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  17. import com.vaadin.terminal.gwt.client.ServerConnector;
  18. import com.vaadin.terminal.gwt.client.Util;
  19. import com.vaadin.terminal.gwt.client.VConsole;
  20. import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
  21. import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
  22. /**
  23. * An abstract implementation of Connector.
  24. *
  25. * @author Vaadin Ltd
  26. * @version @VERSION@
  27. * @since 7.0.0
  28. *
  29. */
  30. public abstract class AbstractConnector implements ServerConnector,
  31. StateChangeHandler {
  32. private ApplicationConnection connection;
  33. private String id;
  34. private HandlerManager handlerManager;
  35. private Map<String, Collection<ClientRpc>> rpcImplementations;
  36. private final boolean debugLogging = false;
  37. private SharedState state;
  38. private ServerConnector parent;
  39. /**
  40. * Temporary storage for last enabled state to be able to see if it has
  41. * changed. Can be removed once we are able to listen specifically for
  42. * enabled changes in the state. Widget.isEnabled() cannot be used as all
  43. * Widgets do not implement HasEnabled
  44. */
  45. private boolean lastEnabledState = true;
  46. private List<ServerConnector> children;
  47. /*
  48. * (non-Javadoc)
  49. *
  50. * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection()
  51. */
  52. @Override
  53. public final ApplicationConnection getConnection() {
  54. return connection;
  55. }
  56. /*
  57. * (non-Javadoc)
  58. *
  59. * @see com.vaadin.terminal.gwt.client.Connector#getId()
  60. */
  61. @Override
  62. public String getConnectorId() {
  63. return id;
  64. }
  65. /**
  66. * Called once by the framework to initialize the connector.
  67. * <p>
  68. * Note that the shared state is not yet available when this method is
  69. * called.
  70. * <p>
  71. * Connector classes should override {@link #init()} instead of this method.
  72. */
  73. @Override
  74. public final void doInit(String connectorId,
  75. ApplicationConnection connection) {
  76. this.connection = connection;
  77. id = connectorId;
  78. addStateChangeHandler(this);
  79. init();
  80. }
  81. /**
  82. * Called when the connector has been initialized. Override this method to
  83. * perform initialization of the connector.
  84. */
  85. // FIXME: It might make sense to make this abstract to force users to
  86. // use init instead of constructor, where connection and id has not yet been
  87. // set.
  88. protected void init() {
  89. }
  90. /**
  91. * Registers an implementation for a server to client RPC interface.
  92. *
  93. * Multiple registrations can be made for a single interface, in which case
  94. * all of them receive corresponding RPC calls.
  95. *
  96. * @param rpcInterface
  97. * RPC interface
  98. * @param implementation
  99. * implementation that should receive RPC calls
  100. * @param <T>
  101. * The type of the RPC interface that is being registered
  102. */
  103. protected <T extends ClientRpc> void registerRpc(Class<T> rpcInterface,
  104. T implementation) {
  105. String rpcInterfaceId = rpcInterface.getName().replaceAll("\\$", ".");
  106. if (null == rpcImplementations) {
  107. rpcImplementations = new HashMap<String, Collection<ClientRpc>>();
  108. }
  109. if (null == rpcImplementations.get(rpcInterfaceId)) {
  110. rpcImplementations.put(rpcInterfaceId, new ArrayList<ClientRpc>());
  111. }
  112. rpcImplementations.get(rpcInterfaceId).add(implementation);
  113. }
  114. /**
  115. * Unregisters an implementation for a server to client RPC interface.
  116. *
  117. * @param rpcInterface
  118. * RPC interface
  119. * @param implementation
  120. * implementation to unregister
  121. */
  122. protected <T extends ClientRpc> void unregisterRpc(Class<T> rpcInterface,
  123. T implementation) {
  124. String rpcInterfaceId = rpcInterface.getName().replaceAll("\\$", ".");
  125. if (null != rpcImplementations
  126. && null != rpcImplementations.get(rpcInterfaceId)) {
  127. rpcImplementations.get(rpcInterfaceId).remove(implementation);
  128. }
  129. }
  130. @Override
  131. public <T extends ClientRpc> Collection<T> getRpcImplementations(
  132. String rpcInterfaceId) {
  133. if (null == rpcImplementations) {
  134. return Collections.emptyList();
  135. }
  136. return (Collection<T>) rpcImplementations.get(rpcInterfaceId);
  137. }
  138. @Override
  139. public void fireEvent(GwtEvent<?> event) {
  140. if (handlerManager != null) {
  141. handlerManager.fireEvent(event);
  142. }
  143. }
  144. protected HandlerManager ensureHandlerManager() {
  145. if (handlerManager == null) {
  146. handlerManager = new HandlerManager(this);
  147. }
  148. return handlerManager;
  149. }
  150. @Override
  151. public HandlerRegistration addStateChangeHandler(StateChangeHandler handler) {
  152. return ensureHandlerManager()
  153. .addHandler(StateChangeEvent.TYPE, handler);
  154. }
  155. @Override
  156. public void onStateChanged(StateChangeEvent stateChangeEvent) {
  157. if (debugLogging) {
  158. VConsole.log("State change event for "
  159. + Util.getConnectorString(stateChangeEvent.getConnector())
  160. + " received by " + Util.getConnectorString(this));
  161. }
  162. updateEnabledState(isEnabled());
  163. }
  164. /*
  165. * (non-Javadoc)
  166. *
  167. * @see com.vaadin.terminal.gwt.client.ServerConnector#onUnregister()
  168. */
  169. @Override
  170. public void onUnregister() {
  171. if (debugLogging) {
  172. VConsole.log("Unregistered connector "
  173. + Util.getConnectorString(this));
  174. }
  175. }
  176. /**
  177. * Returns the shared state object for this connector.
  178. *
  179. * Override this method to define the shared state type for your connector.
  180. *
  181. * @return the current shared state (never null)
  182. */
  183. @Override
  184. public SharedState getState() {
  185. if (state == null) {
  186. state = createState();
  187. }
  188. return state;
  189. }
  190. /**
  191. * Creates a state object with default values for this connector. The
  192. * created state object must be compatible with the return type of
  193. * {@link #getState()}. The default implementation creates a state object
  194. * using GWT.create() using the defined return type of {@link #getState()}.
  195. *
  196. * @return A new state object
  197. */
  198. protected SharedState createState() {
  199. return ConnectorStateFactory.createState(getClass());
  200. }
  201. @Override
  202. public ServerConnector getParent() {
  203. return parent;
  204. }
  205. @Override
  206. public void setParent(ServerConnector parent) {
  207. this.parent = parent;
  208. }
  209. @Override
  210. public List<ServerConnector> getChildren() {
  211. if (children == null) {
  212. return Collections.emptyList();
  213. }
  214. return children;
  215. }
  216. @Override
  217. public void setChildren(List<ServerConnector> children) {
  218. this.children = children;
  219. }
  220. @Override
  221. public boolean isEnabled() {
  222. if (!getState().isEnabled()) {
  223. return false;
  224. }
  225. if (getParent() == null) {
  226. return true;
  227. } else {
  228. return getParent().isEnabled();
  229. }
  230. }
  231. @Override
  232. public void updateEnabledState(boolean enabledState) {
  233. if (lastEnabledState == enabledState) {
  234. return;
  235. }
  236. lastEnabledState = enabledState;
  237. for (ServerConnector c : getChildren()) {
  238. // Update children as they might be affected by the enabled state of
  239. // their parent
  240. c.updateEnabledState(c.isEnabled());
  241. }
  242. }
  243. }