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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright 2000-2016 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.converter;
  17. import java.io.Serializable;
  18. import java.util.function.Function;
  19. import com.vaadin.data.Binder.BindingBuilder;
  20. import com.vaadin.data.Result;
  21. import com.vaadin.server.SerializableFunction;
  22. /**
  23. * Interface that implements conversion between a model and a presentation type.
  24. * <p>
  25. * Converters must not have any side effects (never update UI from inside a
  26. * converter).
  27. *
  28. * @param <PRESENTATION>
  29. * The presentation type.
  30. * @param <MODEL>
  31. * The model type.
  32. * @author Vaadin Ltd.
  33. * @since 8.0
  34. */
  35. public interface Converter<PRESENTATION, MODEL> extends Serializable {
  36. /**
  37. * Converts the given value from model type to presentation type.
  38. * <p>
  39. * A converter can optionally use locale to do the conversion.
  40. *
  41. * @param value
  42. * The value to convert. Can be null
  43. * @param context
  44. * The value context for the conversion.
  45. * @return The converted value compatible with the source type
  46. */
  47. public Result<MODEL> convertToModel(PRESENTATION value,
  48. ValueContext context);
  49. /**
  50. * Converts the given value from presentation type to model type.
  51. * <p>
  52. * A converter can optionally use locale to do the conversion.
  53. *
  54. * @param value
  55. * The value to convert. Can be null
  56. * @param context
  57. * The value context for the conversion.
  58. * @return The converted value compatible with the source type
  59. */
  60. public PRESENTATION convertToPresentation(MODEL value,
  61. ValueContext context);
  62. /**
  63. * Returns a converter that returns its input as-is in both directions.
  64. *
  65. * @param <T>
  66. * the input and output type
  67. * @return an identity converter
  68. */
  69. public static <T> Converter<T, T> identity() {
  70. return from(t -> Result.ok(t), t -> t);
  71. }
  72. /**
  73. * Constructs a converter from two functions. Any {@code Exception}
  74. * instances thrown from the {@code toModel} function are converted into
  75. * error-bearing {@code Result} objects using the given {@code onError}
  76. * function.
  77. *
  78. * @param <P>
  79. * the presentation type
  80. * @param <M>
  81. * the model type
  82. * @param toModel
  83. * the function to convert to model
  84. * @param toPresentation
  85. * the function to convert to presentation
  86. * @param onError
  87. * the function to provide error messages
  88. * @return the new converter
  89. *
  90. * @see Result
  91. * @see Function
  92. */
  93. public static <P, M> Converter<P, M> from(
  94. SerializableFunction<P, M> toModel,
  95. SerializableFunction<M, P> toPresentation,
  96. SerializableFunction<Exception, String> onError) {
  97. return from(val -> Result.of(() -> toModel.apply(val), onError),
  98. toPresentation);
  99. }
  100. /**
  101. * Constructs a converter from a filter and a function.
  102. *
  103. * @param <P>
  104. * the presentation type
  105. * @param <M>
  106. * the model type
  107. * @param toModel
  108. * the function to convert to model
  109. * @param toPresentation
  110. * the function to convert to presentation
  111. * @return the new converter
  112. *
  113. * @see Function
  114. */
  115. public static <P, M> Converter<P, M> from(
  116. SerializableFunction<P, Result<M>> toModel,
  117. SerializableFunction<M, P> toPresentation) {
  118. return new Converter<P, M>() {
  119. @Override
  120. public Result<M> convertToModel(P value, ValueContext context) {
  121. return toModel.apply(value);
  122. }
  123. @Override
  124. public P convertToPresentation(M value, ValueContext context) {
  125. return toPresentation.apply(value);
  126. }
  127. };
  128. }
  129. /**
  130. * Returns a converter that chains together this converter with the given
  131. * type-compatible converter.
  132. * <p>
  133. * The chained converters will form a new converter capable of converting
  134. * from the presentation type of this converter to the model type of the
  135. * other converter.
  136. * <p>
  137. * In most typical cases you should not need this method but instead only
  138. * need to define one converter for a binding using
  139. * {@link BindingBuilder#withConverter(Converter)}.
  140. *
  141. * @param <T>
  142. * the model type of the resulting converter
  143. * @param other
  144. * the converter to chain, not null
  145. * @return a chained converter
  146. */
  147. public default <T> Converter<PRESENTATION, T> chain(
  148. Converter<MODEL, T> other) {
  149. return new Converter<PRESENTATION, T>() {
  150. @Override
  151. public Result<T> convertToModel(PRESENTATION value,
  152. ValueContext context) {
  153. Result<MODEL> model = Converter.this.convertToModel(value,
  154. context);
  155. return model.flatMap(v -> other.convertToModel(v, context));
  156. }
  157. @Override
  158. public PRESENTATION convertToPresentation(T value,
  159. ValueContext context) {
  160. MODEL model = other.convertToPresentation(value, context);
  161. return Converter.this.convertToPresentation(model, context);
  162. }
  163. };
  164. }
  165. }