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.

DataSourceConnector.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Copyright 2000-2014 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client.tokka.connectors.data;
  17. import java.util.HashMap;
  18. import java.util.HashSet;
  19. import java.util.List;
  20. import java.util.Map;
  21. import java.util.Set;
  22. import com.google.gwt.core.client.Scheduler;
  23. import com.google.gwt.core.client.Scheduler.ScheduledCommand;
  24. import com.vaadin.client.ServerConnector;
  25. import com.vaadin.client.extensions.AbstractExtensionConnector;
  26. import com.vaadin.client.widget.grid.datasources.ListDataSource;
  27. import com.vaadin.shared.data.DataRequestRpc;
  28. import com.vaadin.shared.data.typed.DataProviderClientRpc;
  29. import com.vaadin.shared.data.typed.DataProviderConstants;
  30. import com.vaadin.shared.ui.Connect;
  31. import com.vaadin.tokka.server.communication.data.SimpleDataProvider;
  32. import elemental.json.Json;
  33. import elemental.json.JsonArray;
  34. import elemental.json.JsonObject;
  35. /**
  36. * A simple connector for DataProvider class. Based on {@link ListDataSource}
  37. * and does not support lazy loading or paging.
  38. *
  39. * @since
  40. */
  41. @Connect(SimpleDataProvider.class)
  42. public class DataSourceConnector extends AbstractExtensionConnector {
  43. private Map<String, JsonObject> keyToJson = new HashMap<String, JsonObject>();
  44. private Set<String> droppedKeys = new HashSet<String>();
  45. private ListDataSource<JsonObject> ds = new ListDataSource<JsonObject>();
  46. private boolean pendingDrop = false;
  47. @Override
  48. protected void extend(ServerConnector target) {
  49. registerRpc(DataProviderClientRpc.class, new DataProviderClientRpc() {
  50. @Override
  51. public void reset() {
  52. ds.asList().clear();
  53. // Inform the server-side that all keys are now dropped.
  54. Set<String> keySet = new HashSet<String>(keyToJson.keySet());
  55. for (String key : keySet) {
  56. dropKey(key);
  57. }
  58. sendDroppedKeys();
  59. }
  60. @Override
  61. public void setData(long firstIndex, JsonArray data) {
  62. List<JsonObject> l = ds.asList();
  63. assert firstIndex <= l.size() : "Gap in data. First Index: "
  64. + firstIndex + ", Size: " + l.size();
  65. for (long i = 0; i < data.length(); ++i) {
  66. JsonObject object = data.getObject((int) i);
  67. if (i + firstIndex == l.size()) {
  68. l.add(object);
  69. } else if (i + firstIndex < l.size()) {
  70. int index = (int) (i + firstIndex);
  71. dropKey(getKey(l.get(index)));
  72. l.set(index, object);
  73. }
  74. keyToJson.put(getKey(object), object);
  75. }
  76. sendDroppedKeys();
  77. }
  78. @Override
  79. public void add(JsonObject dataObject) {
  80. ds.asList().add(dataObject);
  81. keyToJson.put(getKey(dataObject), dataObject);
  82. }
  83. @Override
  84. public void drop(String key) {
  85. if (keyToJson.containsKey(key)) {
  86. ds.asList().remove(keyToJson.get(key));
  87. dropKey(key);
  88. sendDroppedKeys();
  89. }
  90. }
  91. @Override
  92. public void updateData(JsonArray data) {
  93. List<JsonObject> list = ds.asList();
  94. for (int i = 0; i < data.length(); ++i) {
  95. JsonObject json = data.getObject(i);
  96. String key = getKey(json);
  97. if (keyToJson.containsKey(key)) {
  98. int index = list.indexOf(keyToJson.get(key));
  99. list.set(index, json);
  100. keyToJson.put(key, json);
  101. } else {
  102. dropKey(key);
  103. }
  104. }
  105. sendDroppedKeys();
  106. }
  107. });
  108. ServerConnector parent = getParent();
  109. if (parent instanceof HasDataSource) {
  110. ((HasDataSource) parent).setDataSource(ds);
  111. } else {
  112. assert false : "Parent not implementing HasDataSource";
  113. }
  114. }
  115. /**
  116. * Marks a key as dropped. Call to
  117. * {@link DataSourceConnector#sendDroppedKeys()} should be called to make
  118. * sure the information is sent to the server-side.
  119. *
  120. * @param key
  121. * dropped key
  122. */
  123. private void dropKey(String key) {
  124. droppedKeys.add(key);
  125. if (keyToJson.containsKey(key)) {
  126. keyToJson.remove(key);
  127. }
  128. }
  129. /**
  130. * Sends dropped keys to the server-side with a deferred scheduled command.
  131. * Multiple calls to this method will only result to one command being
  132. * executed.
  133. */
  134. private void sendDroppedKeys() {
  135. if (pendingDrop) {
  136. return;
  137. }
  138. pendingDrop = true;
  139. Scheduler.get().scheduleDeferred(new ScheduledCommand() {
  140. @Override
  141. public void execute() {
  142. pendingDrop = false;
  143. if (droppedKeys.isEmpty()) {
  144. return;
  145. }
  146. JsonArray keyArray = Json.createArray();
  147. int i = 0;
  148. for (String key : droppedKeys) {
  149. keyArray.set(i++, key);
  150. }
  151. getRpcProxy(DataRequestRpc.class).dropRows(keyArray);
  152. // Force RPC since it's delayed.
  153. getConnection().getServerRpcQueue().flush();
  154. droppedKeys.clear();
  155. }
  156. });
  157. }
  158. /**
  159. * Gets the mapping key from given {@link JsonObject}.
  160. *
  161. * @param jsonObject
  162. * json object to get the key from
  163. */
  164. protected String getKey(JsonObject jsonObject) {
  165. if (jsonObject.hasKey(DataProviderConstants.KEY)) {
  166. return jsonObject.getString(DataProviderConstants.KEY);
  167. }
  168. return null;
  169. }
  170. }