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.

DefaultFieldGroupFieldFactory.java 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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.fieldgroup;
  17. import java.util.Date;
  18. import java.util.EnumSet;
  19. import com.vaadin.data.Item;
  20. import com.vaadin.data.fieldgroup.FieldGroup.BindException;
  21. import com.vaadin.ui.AbstractSelect;
  22. import com.vaadin.ui.ComboBox;
  23. import com.vaadin.ui.ListSelect;
  24. import com.vaadin.ui.NativeSelect;
  25. import com.vaadin.ui.OptionGroup;
  26. import com.vaadin.ui.RichTextArea;
  27. import com.vaadin.ui.Table;
  28. import com.vaadin.v7.ui.LegacyAbstractField;
  29. import com.vaadin.v7.ui.LegacyAbstractTextField;
  30. import com.vaadin.v7.ui.LegacyCheckBox;
  31. import com.vaadin.v7.ui.LegacyDateField;
  32. import com.vaadin.v7.ui.LegacyField;
  33. import com.vaadin.v7.ui.LegacyInlineDateField;
  34. import com.vaadin.v7.ui.LegacyPopupDateField;
  35. import com.vaadin.v7.ui.LegacyTextField;
  36. /**
  37. * This class contains a basic implementation for {@link FieldGroupFieldFactory}
  38. * .The class is singleton, use {@link #get()} method to get reference to the
  39. * instance.
  40. *
  41. * @author Vaadin Ltd
  42. */
  43. public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory {
  44. private static final DefaultFieldGroupFieldFactory INSTANCE = new DefaultFieldGroupFieldFactory();
  45. public static final Object CAPTION_PROPERTY_ID = "Caption";
  46. protected DefaultFieldGroupFieldFactory() {
  47. }
  48. /**
  49. * Gets the singleton instance.
  50. *
  51. * @since 7.4
  52. *
  53. * @return the singleton instance
  54. */
  55. public static DefaultFieldGroupFieldFactory get() {
  56. return INSTANCE;
  57. }
  58. @Override
  59. public <T extends LegacyField> T createField(Class<?> type,
  60. Class<T> fieldType) {
  61. if (Enum.class.isAssignableFrom(type)) {
  62. return createEnumField(type, fieldType);
  63. } else if (Date.class.isAssignableFrom(type)) {
  64. return createDateField(type, fieldType);
  65. } else if (Boolean.class.isAssignableFrom(type)
  66. || boolean.class.isAssignableFrom(type)) {
  67. return createBooleanField(fieldType);
  68. }
  69. if (LegacyAbstractTextField.class.isAssignableFrom(fieldType)) {
  70. return fieldType.cast(createAbstractTextField(
  71. fieldType.asSubclass(LegacyAbstractTextField.class)));
  72. } else if (fieldType == RichTextArea.class) {
  73. return fieldType.cast(createRichTextArea());
  74. }
  75. return createDefaultField(type, fieldType);
  76. }
  77. protected RichTextArea createRichTextArea() {
  78. RichTextArea rta = new RichTextArea();
  79. rta.setImmediate(true);
  80. return rta;
  81. }
  82. private <T extends LegacyField> T createEnumField(Class<?> type,
  83. Class<T> fieldType) {
  84. // Determine first if we should (or can) create a select for the enum
  85. Class<AbstractSelect> selectClass = null;
  86. if (AbstractSelect.class.isAssignableFrom(fieldType)) {
  87. selectClass = (Class<AbstractSelect>) fieldType;
  88. } else if (anySelect(fieldType)) {
  89. selectClass = AbstractSelect.class;
  90. }
  91. if (selectClass != null) {
  92. AbstractSelect s = createCompatibleSelect(selectClass);
  93. populateWithEnumData(s, (Class<? extends Enum>) type);
  94. return (T) s;
  95. } else if (LegacyAbstractTextField.class.isAssignableFrom(fieldType)) {
  96. return (T) createAbstractTextField(
  97. (Class<? extends LegacyAbstractTextField>) fieldType);
  98. }
  99. return null;
  100. }
  101. private <T extends LegacyField> T createDateField(Class<?> type,
  102. Class<T> fieldType) {
  103. LegacyAbstractField field;
  104. if (LegacyInlineDateField.class.isAssignableFrom(fieldType)) {
  105. field = new LegacyInlineDateField();
  106. } else if (anyField(fieldType)
  107. || LegacyDateField.class.isAssignableFrom(fieldType)) {
  108. field = new LegacyPopupDateField();
  109. } else if (LegacyAbstractTextField.class.isAssignableFrom(fieldType)) {
  110. field = createAbstractTextField(
  111. (Class<? extends LegacyAbstractTextField>) fieldType);
  112. } else {
  113. return null;
  114. }
  115. field.setImmediate(true);
  116. return (T) field;
  117. }
  118. protected AbstractSelect createCompatibleSelect(
  119. Class<? extends AbstractSelect> fieldType) {
  120. AbstractSelect select;
  121. if (fieldType.isAssignableFrom(ListSelect.class)) {
  122. select = new ListSelect();
  123. select.setMultiSelect(false);
  124. } else if (fieldType.isAssignableFrom(NativeSelect.class)) {
  125. select = new NativeSelect();
  126. } else if (fieldType.isAssignableFrom(OptionGroup.class)) {
  127. select = new OptionGroup();
  128. select.setMultiSelect(false);
  129. } else if (fieldType.isAssignableFrom(Table.class)) {
  130. Table t = new Table();
  131. t.setSelectable(true);
  132. select = t;
  133. } else {
  134. select = new ComboBox(null);
  135. }
  136. select.setImmediate(true);
  137. select.setNullSelectionAllowed(false);
  138. return select;
  139. }
  140. /**
  141. * @since 7.4
  142. * @param fieldType
  143. * the type of the field
  144. * @return true if any LegacyAbstractField can be assigned to the field
  145. */
  146. protected boolean anyField(Class<?> fieldType) {
  147. return fieldType == LegacyField.class
  148. || fieldType == LegacyAbstractField.class;
  149. }
  150. /**
  151. * @since 7.4
  152. * @param fieldType
  153. * the type of the field
  154. * @return true if any AbstractSelect can be assigned to the field
  155. */
  156. protected boolean anySelect(Class<? extends LegacyField> fieldType) {
  157. return anyField(fieldType) || fieldType == AbstractSelect.class;
  158. }
  159. protected <T extends LegacyField> T createBooleanField(Class<T> fieldType) {
  160. if (fieldType.isAssignableFrom(LegacyCheckBox.class)) {
  161. LegacyCheckBox cb = new LegacyCheckBox(null);
  162. cb.setImmediate(true);
  163. return (T) cb;
  164. } else if (LegacyAbstractTextField.class.isAssignableFrom(fieldType)) {
  165. return (T) createAbstractTextField(
  166. (Class<? extends LegacyAbstractTextField>) fieldType);
  167. }
  168. return null;
  169. }
  170. protected <T extends LegacyAbstractTextField> T createAbstractTextField(
  171. Class<T> fieldType) {
  172. if (fieldType == LegacyAbstractTextField.class) {
  173. fieldType = (Class<T>) LegacyTextField.class;
  174. }
  175. try {
  176. T field = fieldType.newInstance();
  177. field.setImmediate(true);
  178. return field;
  179. } catch (Exception e) {
  180. throw new BindException(
  181. "Could not create a field of type " + fieldType, e);
  182. }
  183. }
  184. /**
  185. * Fallback when no specific field has been created. Typically returns a
  186. * TextField.
  187. *
  188. * @param <T>
  189. * The type of field to create
  190. * @param type
  191. * The type of data that should be edited
  192. * @param fieldType
  193. * The type of field to create
  194. * @return A field capable of editing the data or null if no field could be
  195. * created
  196. */
  197. protected <T extends LegacyField> T createDefaultField(Class<?> type,
  198. Class<T> fieldType) {
  199. if (fieldType.isAssignableFrom(LegacyTextField.class)) {
  200. return fieldType
  201. .cast(createAbstractTextField(LegacyTextField.class));
  202. }
  203. return null;
  204. }
  205. /**
  206. * Populates the given select with all the enums in the given {@link Enum}
  207. * class. Uses {@link Enum}.toString() for caption.
  208. *
  209. * @param select
  210. * The select to populate
  211. * @param enumClass
  212. * The Enum class to use
  213. */
  214. protected void populateWithEnumData(AbstractSelect select,
  215. Class<? extends Enum> enumClass) {
  216. select.removeAllItems();
  217. for (Object p : select.getContainerPropertyIds()) {
  218. select.removeContainerProperty(p);
  219. }
  220. select.addContainerProperty(CAPTION_PROPERTY_ID, String.class, "");
  221. select.setItemCaptionPropertyId(CAPTION_PROPERTY_ID);
  222. @SuppressWarnings("unchecked")
  223. EnumSet<?> enumSet = EnumSet.allOf(enumClass);
  224. for (Object r : enumSet) {
  225. Item newItem = select.addItem(r);
  226. newItem.getItemProperty(CAPTION_PROPERTY_ID).setValue(r.toString());
  227. }
  228. }
  229. }