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

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