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.7KB

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