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.

UIDL.java 15KB

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