1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.tapas.evidence.fe.form;
20
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.Collection;
24 import java.util.Locale;
25
26 import lombok.extern.slf4j.Slf4j;
27
28 import org.springframework.validation.BeanPropertyBindingResult;
29 import org.springframework.validation.BindingResult;
30 import org.springframework.validation.FieldError;
31 import org.springframework.validation.Validator;
32 import org.vaadin.mvp.uibinder.IUiMessageSource;
33
34 import com.vaadin.data.util.BeanItem;
35 import com.vaadin.data.util.NestedMethodProperty;
36 import com.vaadin.terminal.UserError;
37 import com.vaadin.ui.AbstractField;
38 import com.vaadin.ui.Component;
39 import com.vaadin.ui.Field;
40 import com.vaadin.ui.Form;
41 import com.vaadin.ui.FormFieldFactory;
42
43
44
45
46
47 @Slf4j
48 public class EvidenceForm extends Form {
49
50 private static final String MISSING_MESSAGE = "{{missing message: ";
51
52 private static final long serialVersionUID = 1L;
53
54 private static final String NESTED_SEPARATOR = ".";
55
56 public void addFooter(final Component component) {
57 this.getFooter().addComponent(component);
58 }
59
60 public void setItemDataSource(final Model model, final MetaModel metaModel, final IUiMessageSource messageSource,
61 final String messagePrefix, final Locale locale) {
62 final BeanItem<Model> beanItem = new BeanItem<Model>(model);
63 for (FieldInfo fieldInfo : metaModel.getFieldInfos()) {
64 if (fieldInfo.isNested()) {
65 beanItem.addItemProperty(fieldInfo.getFieldNestedName(),
66 new NestedMethodProperty(model, fieldInfo.getFieldNestedName()));
67 }
68 }
69 this.setItemDataSource(beanItem);
70 setupFormFieldFactory(model, metaModel, messageSource, locale);
71 this.setVisibleItemProperties(metaModel.getOrderedFields());
72 for (String fieldName : metaModel.getCaptionedFields()) {
73 log.trace("Processing caption for field:{}", fieldName);
74 final String fieldCaption = messagePrefix + NESTED_SEPARATOR + metaModel.getFieldCaption(fieldName);
75 final Field field = this.getField(fieldName);
76 field.setCaption(messageSource.getMessage(fieldCaption, locale));
77 }
78 for (String fieldName : metaModel.getRequiredFields()) {
79 log.trace("Processing required for field:{}", fieldName);
80 final Boolean fieldRequired = metaModel.getFieldRequired(fieldName);
81 final Field field = this.getField(fieldName);
82 log.trace("Field:{} is required:{}", fieldName, fieldRequired);
83 if (field != null) {
84 field.setRequired(fieldRequired);
85 field.setRequiredError(messageSource.getMessage("field.required", locale));
86 } else {
87 log.trace("Field: {} doesnt exists and will be skiped!", fieldName);
88 }
89 }
90 }
91
92 public boolean validate(final MetaModel metaModel, final Validator validator, final Model model,
93 final IUiMessageSource messageSource, final Locale locale) {
94 boolean result = false;
95 final BindingResult validationResult = new BeanPropertyBindingResult(model, model.getClass().getName());
96 clearFields(metaModel);
97 validator.validate(model, validationResult);
98 if (validationResult.hasErrors()) {
99 for (FieldError error : validationResult.getFieldErrors()) {
100 final String field = error.getField();
101 final String message = getMessage(error.getCodes(), messageSource, locale);
102 final Field fieldComponent = this.getField(field);
103 if (fieldComponent instanceof AbstractField) {
104 ((AbstractField)fieldComponent).setComponentError(new UserError(message));
105 }
106 }
107 result = false;
108 } else {
109 result = true;
110 }
111 return result;
112 }
113
114 private String getMessage(final String[] codes, final IUiMessageSource messageSource, final Locale locale) {
115 String result = null;
116 for (String code : codes) {
117 result = messageSource.getMessage(code, locale);
118 if (result != null && !result.startsWith(MISSING_MESSAGE)) {
119 break;
120 }
121 }
122 return result;
123 }
124
125 private void clearFields(final MetaModel metaModel) {
126 final Collection<String> validatedFields = metaModel.getValidatedFields();
127 for (String fieldName : validatedFields) {
128 final boolean isFieldValidated = metaModel.getFieldValidated(fieldName);
129 log.trace("Field: {} will be validated: {}", fieldName, isFieldValidated);
130 if (isFieldValidated) {
131 final Field fieldComponent = this.getField(fieldName);
132 if (fieldComponent instanceof AbstractField) {
133 log.trace("Cleanup error for field:{}", fieldName);
134 ((AbstractField)fieldComponent).setComponentError(null);
135 }
136 }
137 }
138 }
139
140 private void setupFormFieldFactory(final Model model, final MetaModel metaModel, final IUiMessageSource messageSource, final Locale locale) {
141 final Class<? extends FormFieldFactory> formFieldFactory = metaModel.getFormFieldFactory();
142 if (formFieldFactory != null) {
143 try {
144 final Constructor<? extends FormFieldFactory> constructor = formFieldFactory
145 .getConstructor(new Class[] { IUiMessageSource.class, Locale.class });
146 final EvidenceFormFieldFactory instance = (EvidenceFormFieldFactory) constructor
147 .newInstance(new Object[] { messageSource, locale });
148 this.setFormFieldFactory(instance);
149 } catch (InstantiationException e) {
150 throw new EvidenceFormException("InstantiationException for " + formFieldFactory.getName(), e);
151 } catch (IllegalAccessException e) {
152 throw new EvidenceFormException("IllegalAccessException for " + formFieldFactory.getName(), e);
153 } catch (SecurityException e) {
154 throw new EvidenceFormException("SecurityException for " + formFieldFactory.getName(), e);
155 } catch (NoSuchMethodException e) {
156 throw new EvidenceFormException("NoSuchMethodException for " + formFieldFactory.getName(), e);
157 } catch (IllegalArgumentException e) {
158 throw new EvidenceFormException("IllegalArgumentException for " + formFieldFactory.getName(), e);
159 } catch (InvocationTargetException e) {
160 throw new EvidenceFormException("InvocationTargetException for " + formFieldFactory.getName(), e);
161 }
162 }
163 }
164 }