Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

UIDL.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * Copyright 2000-2018 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;
  17. import java.util.HashSet;
  18. import java.util.Iterator;
  19. import java.util.Set;
  20. import com.google.gwt.core.client.JavaScriptObject;
  21. import com.google.gwt.core.client.JsArrayString;
  22. import com.vaadin.server.PaintTarget;
  23. import com.vaadin.ui.Component;
  24. /**
  25. * When a component is updated, it's client side widget's
  26. * {@link ComponentConnector#updateFromUIDL(UIDL, ApplicationConnection)
  27. * updateFromUIDL()} will be called with the updated ("changes") UIDL received
  28. * from the server.
  29. * <p>
  30. * UIDL is hierarchical, and there are a few methods to retrieve the children,
  31. * {@link #getChildCount()}, {@link #iterator()} {@link #getChildString(int)},
  32. * {@link #getChildUIDL(int)}.
  33. * </p>
  34. * <p>
  35. * It can be helpful to keep in mind that UIDL was originally modeled in XML, so
  36. * it's structure is very XML -like. For instance, the first to children in the
  37. * underlying UIDL representation will contain the "tag" name and attributes,
  38. * but will be skipped by the methods mentioned above.
  39. * </p>
  40. */
  41. public final class UIDL extends JavaScriptObject implements Iterable<Object> {
  42. protected UIDL() {
  43. }
  44. /**
  45. * Shorthand for getting the attribute named "id", which for Paintables is
  46. * the essential paintableId which binds the server side component to the
  47. * client side widget.
  48. *
  49. * @return the value of the id attribute, if available
  50. */
  51. public String getId() {
  52. return getStringAttribute("id");
  53. }
  54. /**
  55. * Gets the name of this UIDL section, as created with
  56. * {@link PaintTarget#startTag(String) PaintTarget.startTag()} in the
  57. * server-side {@link Component#paint(PaintTarget) Component.paint()} or
  58. * (usually)
  59. * {@link com.vaadin.ui.AbstractComponent#paintContent(PaintTarget)
  60. * AbstractComponent.paintContent()}. Note that if the UIDL corresponds to a
  61. * Paintable, a component identifier will be returned instead - this is used
  62. * internally and is not needed within
  63. * {@link ComponentConnector#updateFromUIDL(UIDL, ApplicationConnection)
  64. * updateFromUIDL()}.
  65. *
  66. * @return the name for this section
  67. */
  68. public native String getTag()
  69. /*-{
  70. return this[0];
  71. }-*/;
  72. private native ValueMap attr()
  73. /*-{
  74. return this[1];
  75. }-*/;
  76. private native ValueMap var()
  77. /*-{
  78. return this[1]["v"];
  79. }-*/;
  80. private native boolean hasVariables()
  81. /*-{
  82. return Boolean(this[1]["v"]);
  83. }-*/;
  84. /**
  85. * Gets the named attribute as a String.
  86. *
  87. * @param name
  88. * the name of the attribute to get
  89. * @return the attribute value
  90. */
  91. public String getStringAttribute(String name) {
  92. return attr().getString(name);
  93. }
  94. /**
  95. * Gets the names of the attributes available.
  96. *
  97. * @return the names of available attributes
  98. */
  99. public Set<String> getAttributeNames() {
  100. Set<String> keySet = attr().getKeySet();
  101. keySet.remove("v");
  102. return keySet;
  103. }
  104. /**
  105. * Gets the names of variables available.
  106. *
  107. * @return the names of available variables
  108. */
  109. public Set<String> getVariableNames() {
  110. if (!hasVariables()) {
  111. return new HashSet<>();
  112. } else {
  113. Set<String> keySet = var().getKeySet();
  114. return keySet;
  115. }
  116. }
  117. /**
  118. * Gets the named attribute as an int.
  119. *
  120. * @param name
  121. * the name of the attribute to get
  122. * @return the attribute value
  123. */
  124. public int getIntAttribute(String name) {
  125. return attr().getInt(name);
  126. }
  127. /**
  128. * Gets the named attribute as a long.
  129. *
  130. * @param name
  131. * the name of the attribute to get
  132. * @return the attribute value
  133. */
  134. public long getLongAttribute(String name) {
  135. return (long) attr().getRawNumber(name);
  136. }
  137. /**
  138. * Gets the named attribute as a float.
  139. *
  140. * @param name
  141. * the name of the attribute to get
  142. * @return the attribute value
  143. */
  144. public float getFloatAttribute(String name) {
  145. return (float) attr().getRawNumber(name);
  146. }
  147. /**
  148. * Gets the named attribute as a double.
  149. *
  150. * @param name
  151. * the name of the attribute to get
  152. * @return the attribute value
  153. */
  154. public double getDoubleAttribute(String name) {
  155. return attr().getRawNumber(name);
  156. }
  157. /**
  158. * Gets the named attribute as a boolean.
  159. *
  160. * @param name
  161. * the name of the attribute to get
  162. * @return the attribute value
  163. */
  164. public boolean getBooleanAttribute(String name) {
  165. return attr().getBoolean(name);
  166. }
  167. /**
  168. * Gets the named attribute as a Map of named values (key/value pairs).
  169. *
  170. * @param name
  171. * the name of the attribute to get
  172. * @return the attribute Map
  173. */
  174. public ValueMap getMapAttribute(String name) {
  175. return attr().getValueMap(name);
  176. }
  177. /**
  178. * Gets the named attribute as an array of Strings.
  179. *
  180. * @param name
  181. * the name of the attribute to get
  182. * @return the attribute value
  183. */
  184. public String[] getStringArrayAttribute(String name) {
  185. return attr().getStringArray(name);
  186. }
  187. /**
  188. * Gets the named attribute as an int array.
  189. *
  190. * @param name
  191. * the name of the attribute to get
  192. * @return the attribute value
  193. */
  194. public int[] getIntArrayAttribute(final String name) {
  195. return attr().getIntArray(name);
  196. }
  197. /**
  198. * Get attributes value as string whatever the type is
  199. *
  200. * @param name
  201. * @return string presentation of attribute
  202. */
  203. native String getAttribute(String name)
  204. /*-{
  205. return '' + this[1][name];
  206. }-*/;
  207. native String getVariable(String name)
  208. /*-{
  209. return '' + this[1]['v'][name];
  210. }-*/;
  211. /**
  212. * Indicates whether or not the named attribute is available.
  213. *
  214. * @param name
  215. * the name of the attribute to check
  216. * @return true if the attribute is available, false otherwise
  217. */
  218. public boolean hasAttribute(final String name) {
  219. return attr().containsKey(name);
  220. }
  221. /**
  222. * Gets the UIDL for the child at the given index.
  223. *
  224. * @param i
  225. * the index of the child to get
  226. * @return the UIDL of the child if it exists
  227. */
  228. public native UIDL getChildUIDL(int i)
  229. /*-{
  230. return this[i + 2];
  231. }-*/;
  232. /**
  233. * Gets the child at the given index as a String.
  234. *
  235. * @param i
  236. * the index of the child to get
  237. * @return the String representation of the child if it exists
  238. */
  239. public native String getChildString(int i)
  240. /*-{
  241. return this[i + 2];
  242. }-*/;
  243. private native XML getChildXML(int index)
  244. /*-{
  245. return this[index + 2];
  246. }-*/;
  247. /**
  248. * Gets an iterator that can be used to iterate trough the children of this
  249. * UIDL.
  250. * <p>
  251. * The Object returned by <code>next()</code> will be appropriately typed -
  252. * if it's UIDL, {@link #getTag()} can be used to check which section is in
  253. * question.
  254. * </p>
  255. * <p>
  256. * The basic use case is to iterate over the children of an UIDL update, and
  257. * update the appropriate part of the widget for each child encountered, e.g
  258. * if <code>getTag()</code> returns "color", one would update the widgets
  259. * color to reflect the value of the "color" section.
  260. * </p>
  261. *
  262. * @return an iterator for iterating over UIDL children
  263. * @deprecated As of 8.2, please use {@link #iterator()} instead
  264. */
  265. @Deprecated
  266. public Iterator<Object> getChildIterator() {
  267. return iterator();
  268. }
  269. /**
  270. * Gets an iterator that can be used to iterate trough the children of this
  271. * UIDL.
  272. * <p>
  273. * The Object returned by <code>next()</code> will be appropriately typed -
  274. * if it's UIDL, {@link #getTag()} can be used to check which section is in
  275. * question.
  276. * </p>
  277. * <p>
  278. * The basic use case is to iterate over the children of an UIDL update, and
  279. * update the appropriate part of the widget for each child encountered, e.g
  280. * if <code>getTag()</code> returns "color", one would update the widgets
  281. * color to reflect the value of the "color" section.
  282. * </p>
  283. *
  284. * @return an iterator for iterating over UIDL children
  285. * @since 8.2
  286. */
  287. @Override
  288. public Iterator<Object> iterator() {
  289. return new Iterator<Object>() {
  290. int index = -1;
  291. @Override
  292. public void remove() {
  293. throw new UnsupportedOperationException();
  294. }
  295. @Override
  296. public Object next() {
  297. if (hasNext()) {
  298. int typeOfChild = typeOfChild(++index);
  299. switch (typeOfChild) {
  300. case CHILD_TYPE_UIDL:
  301. UIDL childUIDL = getChildUIDL(index);
  302. return childUIDL;
  303. case CHILD_TYPE_STRING:
  304. return getChildString(index);
  305. case CHILD_TYPE_XML:
  306. return getChildXML(index);
  307. default:
  308. throw new IllegalStateException("Illegal child in tag "
  309. + getTag() + " at index " + index);
  310. }
  311. }
  312. return null;
  313. }
  314. @Override
  315. public boolean hasNext() {
  316. int count = getChildCount();
  317. return count > index + 1;
  318. }
  319. };
  320. }
  321. private static final int CHILD_TYPE_STRING = 0;
  322. private static final int CHILD_TYPE_UIDL = 1;
  323. private static final int CHILD_TYPE_XML = 2;
  324. private native int typeOfChild(int index)
  325. /*-{
  326. var t = typeof this[index + 2];
  327. if (t == "object") {
  328. if (typeof(t.length) == "number") {
  329. return 1;
  330. }
  331. return 2;
  332. }
  333. if (t == "string") {
  334. return 0;
  335. }
  336. return -1;
  337. }-*/;
  338. /**
  339. * @deprecated
  340. */
  341. @Deprecated
  342. public String getChildrenAsXML() {
  343. return toString();
  344. }
  345. /**
  346. * Checks if the named variable is available.
  347. *
  348. * @param name
  349. * the name of the variable desired
  350. * @return true if the variable exists, false otherwise
  351. */
  352. public boolean hasVariable(String name) {
  353. return hasVariables() && var().containsKey(name);
  354. }
  355. /**
  356. * Gets the value of the named variable.
  357. *
  358. * @param name
  359. * the name of the variable
  360. * @return the value of the variable
  361. */
  362. public String getStringVariable(String name) {
  363. return var().getString(name);
  364. }
  365. /**
  366. * Gets the value of the named variable.
  367. *
  368. * @param name
  369. * the name of the variable
  370. * @return the value of the variable
  371. */
  372. public int getIntVariable(String name) {
  373. return var().getInt(name);
  374. }
  375. /**
  376. * Gets the value of the named variable.
  377. *
  378. * @param name
  379. * the name of the variable
  380. * @return the value of the variable
  381. */
  382. public long getLongVariable(String name) {
  383. return (long) var().getRawNumber(name);
  384. }
  385. /**
  386. * Gets the value of the named variable.
  387. *
  388. * @param name
  389. * the name of the variable
  390. * @return the value of the variable
  391. */
  392. public float getFloatVariable(String name) {
  393. return (float) var().getRawNumber(name);
  394. }
  395. /**
  396. * Gets the value of the named variable.
  397. *
  398. * @param name
  399. * the name of the variable
  400. * @return the value of the variable
  401. */
  402. public double getDoubleVariable(String name) {
  403. return var().getRawNumber(name);
  404. }
  405. /**
  406. * Gets the value of the named variable.
  407. *
  408. * @param name
  409. * the name of the variable
  410. * @return the value of the variable
  411. */
  412. public boolean getBooleanVariable(String name) {
  413. return var().getBoolean(name);
  414. }
  415. /**
  416. * Gets the value of the named variable.
  417. *
  418. * @param name
  419. * the name of the variable
  420. * @return the value of the variable
  421. */
  422. public String[] getStringArrayVariable(String name) {
  423. return var().getStringArray(name);
  424. }
  425. /**
  426. * Gets the value of the named String[] variable as a Set of Strings.
  427. *
  428. * @param name
  429. * the name of the variable
  430. * @return the value of the variable
  431. */
  432. public Set<String> getStringArrayVariableAsSet(final String name) {
  433. final HashSet<String> s = new HashSet<>();
  434. JsArrayString a = var().getJSStringArray(name);
  435. for (int i = 0; i < a.length(); i++) {
  436. s.add(a.get(i));
  437. }
  438. return s;
  439. }
  440. /**
  441. * Gets the value of the named variable.
  442. *
  443. * @param name
  444. * the name of the variable
  445. * @return the value of the variable
  446. */
  447. public int[] getIntArrayVariable(String name) {
  448. return var().getIntArray(name);
  449. }
  450. /**
  451. * @deprecated should not be used anymore
  452. */
  453. @Deprecated
  454. public static final class XML extends JavaScriptObject {
  455. protected XML() {
  456. }
  457. public native String getXMLAsString()
  458. /*-{
  459. var buf = new Array();
  460. var self = this;
  461. for (j in self) {
  462. buf.push("<");
  463. buf.push(j);
  464. buf.push(">");
  465. buf.push(self[j]);
  466. buf.push("</");
  467. buf.push(j);
  468. buf.push(">");
  469. }
  470. return buf.join("");
  471. }-*/;
  472. }
  473. /**
  474. * Returns the number of children.
  475. *
  476. * @return the number of children
  477. */
  478. public native int getChildCount()
  479. /*-{
  480. return this.length - 2;
  481. }-*/;
  482. native boolean isMapAttribute(String name)
  483. /*-{
  484. return typeof this[1][name] == "object";
  485. }-*/;
  486. /**
  487. * Gets the Paintable with the id found in the named attributes's value.
  488. *
  489. * @param name
  490. * the name of the attribute
  491. * @return the Paintable referenced by the attribute, if it exists
  492. */
  493. public ServerConnector getPaintableAttribute(String name,
  494. ApplicationConnection connection) {
  495. return ConnectorMap.get(connection)
  496. .getConnector(getStringAttribute(name));
  497. }
  498. /**
  499. * Gets the Paintable with the id found in the named variable's value.
  500. *
  501. * @param name
  502. * the name of the variable
  503. * @return the Paintable referenced by the variable, if it exists
  504. */
  505. public ServerConnector getPaintableVariable(String name,
  506. ApplicationConnection connection) {
  507. return ConnectorMap.get(connection)
  508. .getConnector(getStringVariable(name));
  509. }
  510. /**
  511. * Returns the child UIDL by its name. If several child nodes exist with the
  512. * given name, the first child UIDL will be returned.
  513. *
  514. * @param tagName
  515. * @return the child UIDL or null if child wit given name was not found
  516. */
  517. public UIDL getChildByTagName(String tagName) {
  518. for (Object next : this) {
  519. if (next instanceof UIDL) {
  520. UIDL childUIDL = (UIDL) next;
  521. if (childUIDL.getTag().equals(tagName)) {
  522. return childUIDL;
  523. }
  524. }
  525. }
  526. return null;
  527. }
  528. }