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.

PropertyFormatter.java 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.data.util;
  5. import com.vaadin.data.Property;
  6. import com.vaadin.data.util.converter.Converter;
  7. /**
  8. * Formatting proxy for a {@link Property}.
  9. *
  10. * <p>
  11. * This class can be used to implement formatting for any type of Property
  12. * datasources. The idea is to connect this as proxy between UI component and
  13. * the original datasource.
  14. * </p>
  15. *
  16. * <p>
  17. * For example <code>
  18. * <pre>textfield.setPropertyDataSource(new PropertyFormatter(property) {
  19. public String format(Object value) {
  20. return ((Double) value).toString() + "000000000";
  21. }
  22. public Object parse(String formattedValue) throws Exception {
  23. return Double.parseDouble(formattedValue);
  24. }
  25. });</pre></code> adds formatter for Double-typed property that extends
  26. * standard "1.0" notation with more zeroes.
  27. * </p>
  28. *
  29. * @param T
  30. * type of the underlying property (a PropertyFormatter is always a
  31. * Property&lt;String&gt;)
  32. *
  33. * @deprecated Since 7.0 replaced by {@link Converter}
  34. * @author Vaadin Ltd.
  35. * @since 5.3.0
  36. */
  37. @SuppressWarnings("serial")
  38. @Deprecated
  39. public abstract class PropertyFormatter<T> extends AbstractProperty<String>
  40. implements Property.Viewer, Property.ValueChangeListener,
  41. Property.ReadOnlyStatusChangeListener {
  42. /** Datasource that stores the actual value. */
  43. Property<T> dataSource;
  44. /**
  45. * Construct a new {@code PropertyFormatter} that is not connected to any
  46. * data source. Call {@link #setPropertyDataSource(Property)} later on to
  47. * attach it to a property.
  48. *
  49. */
  50. protected PropertyFormatter() {
  51. }
  52. /**
  53. * Construct a new formatter that is connected to given data source. Calls
  54. * {@link #format(Object)} which can be a problem if the formatter has not
  55. * yet been initialized.
  56. *
  57. * @param propertyDataSource
  58. * to connect this property to.
  59. */
  60. public PropertyFormatter(Property<T> propertyDataSource) {
  61. setPropertyDataSource(propertyDataSource);
  62. }
  63. /**
  64. * Gets the current data source of the formatter, if any.
  65. *
  66. * @return the current data source as a Property, or <code>null</code> if
  67. * none defined.
  68. */
  69. @Override
  70. public Property<T> getPropertyDataSource() {
  71. return dataSource;
  72. }
  73. /**
  74. * Sets the specified Property as the data source for the formatter.
  75. *
  76. *
  77. * <p>
  78. * Remember that new data sources getValue() must return objects that are
  79. * compatible with parse() and format() methods.
  80. * </p>
  81. *
  82. * @param newDataSource
  83. * the new data source Property.
  84. */
  85. @Override
  86. public void setPropertyDataSource(Property newDataSource) {
  87. boolean readOnly = false;
  88. String prevValue = null;
  89. if (dataSource != null) {
  90. if (dataSource instanceof Property.ValueChangeNotifier) {
  91. ((Property.ValueChangeNotifier) dataSource)
  92. .removeListener(this);
  93. }
  94. if (dataSource instanceof Property.ReadOnlyStatusChangeListener) {
  95. ((Property.ReadOnlyStatusChangeNotifier) dataSource)
  96. .removeListener(this);
  97. }
  98. readOnly = isReadOnly();
  99. prevValue = getValue();
  100. }
  101. dataSource = newDataSource;
  102. if (dataSource != null) {
  103. if (dataSource instanceof Property.ValueChangeNotifier) {
  104. ((Property.ValueChangeNotifier) dataSource).addListener(this);
  105. }
  106. if (dataSource instanceof Property.ReadOnlyStatusChangeListener) {
  107. ((Property.ReadOnlyStatusChangeNotifier) dataSource)
  108. .addListener(this);
  109. }
  110. }
  111. if (isReadOnly() != readOnly) {
  112. fireReadOnlyStatusChange();
  113. }
  114. String newVal = getValue();
  115. if ((prevValue == null && newVal != null)
  116. || (prevValue != null && !prevValue.equals(newVal))) {
  117. fireValueChange();
  118. }
  119. }
  120. /* Documented in the interface */
  121. @Override
  122. public Class<String> getType() {
  123. return String.class;
  124. }
  125. /**
  126. * Get the formatted value.
  127. *
  128. * @return If the datasource returns null, this is null. Otherwise this is
  129. * String given by format().
  130. */
  131. @Override
  132. public String getValue() {
  133. T value = dataSource == null ? null : dataSource.getValue();
  134. if (value == null) {
  135. return null;
  136. }
  137. return format(value);
  138. }
  139. /** Reflects the read-only status of the datasource. */
  140. @Override
  141. public boolean isReadOnly() {
  142. return dataSource == null ? false : dataSource.isReadOnly();
  143. }
  144. /**
  145. * This method must be implemented to format the values received from
  146. * DataSource.
  147. *
  148. * @param value
  149. * Value object got from the datasource. This is guaranteed to be
  150. * non-null and of the type compatible with getType() of the
  151. * datasource.
  152. * @return
  153. */
  154. abstract public String format(T value);
  155. /**
  156. * Parse string and convert it to format compatible with datasource.
  157. *
  158. * The method is required to assure that parse(format(x)) equals x.
  159. *
  160. * @param formattedValue
  161. * This is guaranteed to be non-null string.
  162. * @return Non-null value compatible with datasource.
  163. * @throws Exception
  164. * Any type of exception can be thrown to indicate that the
  165. * conversion was not succesful.
  166. */
  167. abstract public T parse(String formattedValue) throws Exception;
  168. /**
  169. * Sets the Property's read-only mode to the specified status.
  170. *
  171. * @param newStatus
  172. * the new read-only status of the Property.
  173. */
  174. @Override
  175. public void setReadOnly(boolean newStatus) {
  176. if (dataSource != null) {
  177. dataSource.setReadOnly(newStatus);
  178. }
  179. }
  180. @Override
  181. public void setValue(Object newValue) throws ReadOnlyException {
  182. if (dataSource == null) {
  183. return;
  184. }
  185. if (newValue == null) {
  186. if (dataSource.getValue() != null) {
  187. dataSource.setValue(null);
  188. fireValueChange();
  189. }
  190. } else {
  191. try {
  192. dataSource.setValue(parse(newValue.toString()));
  193. if (!newValue.equals(getValue())) {
  194. fireValueChange();
  195. }
  196. } catch (Exception e) {
  197. throw new IllegalArgumentException("Could not parse value", e);
  198. }
  199. }
  200. }
  201. /**
  202. * Listens for changes in the datasource.
  203. *
  204. * This should not be called directly.
  205. */
  206. @Override
  207. public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
  208. fireValueChange();
  209. }
  210. /**
  211. * Listens for changes in the datasource.
  212. *
  213. * This should not be called directly.
  214. */
  215. @Override
  216. public void readOnlyStatusChange(
  217. com.vaadin.data.Property.ReadOnlyStatusChangeEvent event) {
  218. fireReadOnlyStatusChange();
  219. }
  220. }