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.

PropertysetItem.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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.data.util;
  17. import java.util.Collection;
  18. import java.util.Collections;
  19. import java.util.EventObject;
  20. import java.util.HashMap;
  21. import java.util.Iterator;
  22. import java.util.LinkedList;
  23. import com.vaadin.data.Item;
  24. import com.vaadin.data.Property;
  25. /**
  26. * Class for handling a set of identified Properties. The elements contained in
  27. * a </code>MapItem</code> can be referenced using locally unique identifiers.
  28. * The class supports listeners who are interested in changes to the Property
  29. * set managed by the class.
  30. *
  31. * @author Vaadin Ltd.
  32. * @since 3.0
  33. */
  34. @SuppressWarnings("serial")
  35. public class PropertysetItem implements Item, Item.PropertySetChangeNotifier,
  36. Cloneable {
  37. /* Private representation of the item */
  38. /**
  39. * Mapping from property id to property.
  40. */
  41. private HashMap<Object, Property<?>> map = new HashMap<Object, Property<?>>();
  42. /**
  43. * List of all property ids to maintain the order.
  44. */
  45. private LinkedList<Object> list = new LinkedList<Object>();
  46. /**
  47. * List of property set modification listeners.
  48. */
  49. private LinkedList<Item.PropertySetChangeListener> propertySetChangeListeners = null;
  50. /* Item methods */
  51. /**
  52. * Gets the Property corresponding to the given Property ID stored in the
  53. * Item. If the Item does not contain the Property, <code>null</code> is
  54. * returned.
  55. *
  56. * @param id
  57. * the identifier of the Property to get.
  58. * @return the Property with the given ID or <code>null</code>
  59. */
  60. @Override
  61. public Property getItemProperty(Object id) {
  62. return map.get(id);
  63. }
  64. /**
  65. * Gets the collection of IDs of all Properties stored in the Item.
  66. *
  67. * @return unmodifiable collection containing IDs of the Properties stored
  68. * the Item
  69. */
  70. @Override
  71. public Collection<?> getItemPropertyIds() {
  72. return Collections.unmodifiableCollection(list);
  73. }
  74. /* Item.Managed methods */
  75. /**
  76. * Removes the Property identified by ID from the Item. This functionality
  77. * is optional. If the method is not implemented, the method always returns
  78. * <code>false</code>.
  79. *
  80. * @param id
  81. * the ID of the Property to be removed.
  82. * @return <code>true</code> if the operation succeeded <code>false</code>
  83. * if not
  84. */
  85. @Override
  86. public boolean removeItemProperty(Object id) {
  87. // Cant remove missing properties
  88. if (map.remove(id) == null) {
  89. return false;
  90. }
  91. list.remove(id);
  92. // Send change events
  93. fireItemPropertySetChange();
  94. return true;
  95. }
  96. /**
  97. * Tries to add a new Property into the Item.
  98. *
  99. * @param id
  100. * the ID of the new Property.
  101. * @param property
  102. * the Property to be added and associated with the id.
  103. * @return <code>true</code> if the operation succeeded, <code>false</code>
  104. * if not
  105. */
  106. @Override
  107. public boolean addItemProperty(Object id, Property property) {
  108. // Null ids are not accepted
  109. if (id == null) {
  110. throw new NullPointerException("Item property id can not be null");
  111. }
  112. // Cant add a property twice
  113. if (map.containsKey(id)) {
  114. return false;
  115. }
  116. // Put the property to map
  117. map.put(id, property);
  118. list.add(id);
  119. // Send event
  120. fireItemPropertySetChange();
  121. return true;
  122. }
  123. /**
  124. * Gets the <code>String</code> representation of the contents of the Item.
  125. * The format of the string is a space separated catenation of the
  126. * <code>String</code> representations of the Properties contained by the
  127. * Item.
  128. *
  129. * @return <code>String</code> representation of the Item contents
  130. */
  131. @Override
  132. public String toString() {
  133. String retValue = "";
  134. for (final Iterator<?> i = getItemPropertyIds().iterator(); i.hasNext();) {
  135. final Object propertyId = i.next();
  136. retValue += getItemProperty(propertyId).getValue();
  137. if (i.hasNext()) {
  138. retValue += " ";
  139. }
  140. }
  141. return retValue;
  142. }
  143. /* Notifiers */
  144. /**
  145. * An <code>event</code> object specifying an Item whose Property set has
  146. * changed.
  147. *
  148. * @author Vaadin Ltd.
  149. * @since 3.0
  150. */
  151. private static class PropertySetChangeEvent extends EventObject implements
  152. Item.PropertySetChangeEvent {
  153. private PropertySetChangeEvent(Item source) {
  154. super(source);
  155. }
  156. /**
  157. * Gets the Item whose Property set has changed.
  158. *
  159. * @return source object of the event as an <code>Item</code>
  160. */
  161. @Override
  162. public Item getItem() {
  163. return (Item) getSource();
  164. }
  165. }
  166. /**
  167. * Registers a new property set change listener for this Item.
  168. *
  169. * @param listener
  170. * the new Listener to be registered.
  171. */
  172. @Override
  173. public void addPropertySetChangeListener(
  174. Item.PropertySetChangeListener listener) {
  175. if (propertySetChangeListeners == null) {
  176. propertySetChangeListeners = new LinkedList<PropertySetChangeListener>();
  177. }
  178. propertySetChangeListeners.add(listener);
  179. }
  180. /**
  181. * @deprecated As of 7.0, replaced by
  182. * {@link #addPropertySetChangeListener(com.vaadin.data.Item.PropertySetChangeListener)}
  183. **/
  184. @Override
  185. @Deprecated
  186. public void addListener(Item.PropertySetChangeListener listener) {
  187. addPropertySetChangeListener(listener);
  188. }
  189. /**
  190. * Removes a previously registered property set change listener.
  191. *
  192. * @param listener
  193. * the Listener to be removed.
  194. */
  195. @Override
  196. public void removePropertySetChangeListener(
  197. Item.PropertySetChangeListener listener) {
  198. if (propertySetChangeListeners != null) {
  199. propertySetChangeListeners.remove(listener);
  200. }
  201. }
  202. /**
  203. * @deprecated As of 7.0, replaced by
  204. * {@link #removePropertySetChangeListener(com.vaadin.data.Item.PropertySetChangeListener)}
  205. **/
  206. @Override
  207. @Deprecated
  208. public void removeListener(Item.PropertySetChangeListener listener) {
  209. removePropertySetChangeListener(listener);
  210. }
  211. /**
  212. * Sends a Property set change event to all interested listeners.
  213. */
  214. private void fireItemPropertySetChange() {
  215. if (propertySetChangeListeners != null) {
  216. final Object[] l = propertySetChangeListeners.toArray();
  217. final Item.PropertySetChangeEvent event = new PropertysetItem.PropertySetChangeEvent(
  218. this);
  219. for (int i = 0; i < l.length; i++) {
  220. ((Item.PropertySetChangeListener) l[i])
  221. .itemPropertySetChange(event);
  222. }
  223. }
  224. }
  225. public Collection<?> getListeners(Class<?> eventType) {
  226. if (Item.PropertySetChangeEvent.class.isAssignableFrom(eventType)) {
  227. if (propertySetChangeListeners == null) {
  228. return Collections.EMPTY_LIST;
  229. } else {
  230. return Collections
  231. .unmodifiableCollection(propertySetChangeListeners);
  232. }
  233. }
  234. return Collections.EMPTY_LIST;
  235. }
  236. /**
  237. * Creates and returns a copy of this object.
  238. * <p>
  239. * The method <code>clone</code> performs a shallow copy of the
  240. * <code>PropertysetItem</code>.
  241. * </p>
  242. * <p>
  243. * Note : All arrays are considered to implement the interface Cloneable.
  244. * Otherwise, this method creates a new instance of the class of this object
  245. * and initializes all its fields with exactly the contents of the
  246. * corresponding fields of this object, as if by assignment, the contents of
  247. * the fields are not themselves cloned. Thus, this method performs a
  248. * "shallow copy" of this object, not a "deep copy" operation.
  249. * </p>
  250. *
  251. * @throws CloneNotSupportedException
  252. * if the object's class does not support the Cloneable
  253. * interface.
  254. *
  255. * @see java.lang.Object#clone()
  256. */
  257. @Override
  258. public Object clone() throws CloneNotSupportedException {
  259. final PropertysetItem npsi = new PropertysetItem();
  260. npsi.list = list != null ? (LinkedList<Object>) list.clone() : null;
  261. npsi.propertySetChangeListeners = propertySetChangeListeners != null ? (LinkedList<PropertySetChangeListener>) propertySetChangeListeners
  262. .clone() : null;
  263. npsi.map = (HashMap<Object, Property<?>>) map.clone();
  264. return npsi;
  265. }
  266. /*
  267. * (non-Javadoc)
  268. *
  269. * @see java.lang.Object#equals(java.lang.Object)
  270. */
  271. @Override
  272. public boolean equals(Object obj) {
  273. if (obj == null || !(obj instanceof PropertysetItem)) {
  274. return false;
  275. }
  276. final PropertysetItem other = (PropertysetItem) obj;
  277. if (other.list != list) {
  278. if (other.list == null) {
  279. return false;
  280. }
  281. if (!other.list.equals(list)) {
  282. return false;
  283. }
  284. }
  285. if (other.map != map) {
  286. if (other.map == null) {
  287. return false;
  288. }
  289. if (!other.map.equals(map)) {
  290. return false;
  291. }
  292. }
  293. if (other.propertySetChangeListeners != propertySetChangeListeners) {
  294. boolean thisEmpty = (propertySetChangeListeners == null || propertySetChangeListeners
  295. .isEmpty());
  296. boolean otherEmpty = (other.propertySetChangeListeners == null || other.propertySetChangeListeners
  297. .isEmpty());
  298. if (thisEmpty && otherEmpty) {
  299. return true;
  300. }
  301. if (otherEmpty) {
  302. return false;
  303. }
  304. if (!other.propertySetChangeListeners
  305. .equals(propertySetChangeListeners)) {
  306. return false;
  307. }
  308. }
  309. return true;
  310. }
  311. /*
  312. * (non-Javadoc)
  313. *
  314. * @see java.lang.Object#hashCode()
  315. */
  316. @Override
  317. public int hashCode() {
  318. return (list == null ? 0 : list.hashCode())
  319. ^ (map == null ? 0 : map.hashCode())
  320. ^ ((propertySetChangeListeners == null || propertySetChangeListeners
  321. .isEmpty()) ? 0 : propertySetChangeListeners.hashCode());
  322. }
  323. }