1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.form.field.factory;
35
36 import info.magnolia.cms.i18n.I18nContentSupport;
37 import info.magnolia.objectfactory.ComponentProvider;
38 import info.magnolia.ui.api.view.View;
39 import info.magnolia.ui.form.AbstractFormItem;
40 import info.magnolia.ui.form.field.definition.FieldDefinition;
41 import info.magnolia.ui.form.field.definition.TextFieldDefinition;
42 import info.magnolia.ui.form.field.transformer.TransformedProperty;
43 import info.magnolia.ui.form.field.transformer.Transformer;
44 import info.magnolia.ui.form.field.transformer.UndefinedPropertyType;
45 import info.magnolia.ui.form.field.transformer.basic.BasicTransformer;
46 import info.magnolia.ui.form.validator.definition.FieldValidatorDefinition;
47 import info.magnolia.ui.form.validator.factory.FieldValidatorFactory;
48 import info.magnolia.ui.form.validator.registry.FieldValidatorFactoryFactory;
49 import info.magnolia.ui.vaadin.integration.ItemAdapter;
50 import info.magnolia.ui.vaadin.integration.jcr.DefaultPropertyUtil;
51
52 import java.util.Locale;
53
54 import org.apache.commons.lang3.StringUtils;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import com.vaadin.data.Item;
59 import com.vaadin.data.Property;
60 import com.vaadin.data.util.converter.AbstractStringToNumberConverter;
61 import com.vaadin.data.util.converter.Converter;
62 import com.vaadin.server.Sizeable.Unit;
63 import com.vaadin.ui.AbstractField;
64 import com.vaadin.ui.AbstractTextField;
65 import com.vaadin.ui.Component;
66 import com.vaadin.ui.CssLayout;
67 import com.vaadin.ui.Field;
68 import com.vaadin.ui.Label;
69
70
71
72
73
74
75
76
77 public abstract class AbstractFieldFactory<D extends FieldDefinition, T> extends AbstractFormItem implements FieldFactory {
78 private static final Logger log = LoggerFactory.getLogger(AbstractFieldFactory.class);
79 protected Item item;
80 protected Field<T> field;
81 protected D definition;
82 private FieldValidatorFactoryFactory fieldValidatorFactoryFactory;
83 private I18nContentSupport i18nContentSupport;
84 private ComponentProvider componentProvider;
85
86 public AbstractFieldFactory(D definition, Item relatedFieldItem) {
87 this.definition = definition;
88 this.item = relatedFieldItem;
89 }
90
91 @Override
92 public void setFieldValidatorFactoryFactory(FieldValidatorFactoryFactory fieldValidatorFactoryFactory) {
93 this.fieldValidatorFactoryFactory = fieldValidatorFactoryFactory;
94 }
95
96 @Override
97 public void setI18nContentSupport(I18nContentSupport i18nContentSupport) {
98 this.i18nContentSupport = i18nContentSupport;
99 }
100
101 @Override
102 public Field<T> createField() {
103 if (field == null) {
104
105 this.field = createFieldComponent();
106 if (field instanceof AbstractField && definition.getConverterClass() != null) {
107 Converter<?, ?> converter = initializeConverter(definition.getConverterClass());
108 ((AbstractField) field).setConverter(converter);
109 }
110
111 Property<?> property = initializeProperty();
112
113
114 if (Long.class.equals(property.getType()) && field instanceof AbstractTextField) {
115 ((AbstractTextField) field).setConverter(new StringToLongConverter());
116 }
117
118 setPropertyDataSourceAndDefaultValue(property);
119
120 if (StringUtils.isNotBlank(definition.getStyleName())) {
121 this.field.addStyleName(definition.getStyleName());
122 }
123
124 field.setWidth(100, Unit.PERCENTAGE);
125
126
127 if (StringUtils.isNotBlank(getFieldDefinition().getLabel())) {
128 this.field.setCaption(getFieldDefinition().getLabel() + (getFieldDefinition().isRequired() ? "<span class=\"requiredfield\">*</span>" : ""));
129 }
130
131 setConstraints();
132
133 }
134 return this.field;
135 }
136
137
138
139
140
141
142
143
144 public void setPropertyDataSourceAndDefaultValue(Property<?> property) {
145 this.field.setPropertyDataSource(property);
146
147 if ((item instanceof ItemAdapter && ((ItemAdapter) item).isNew() && property.getValue() == null) || (!(item instanceof ItemAdapter) && property.getValue() == null)) {
148 setPropertyDataSourceDefaultValue(property);
149 }
150 }
151
152
153
154
155 protected void setPropertyDataSourceDefaultValue(Property property) {
156 Object defaultValue = createDefaultValue(property);
157 if (defaultValue != null && !definition.isReadOnly()) {
158 if (defaultValue.getClass().isAssignableFrom(property.getType())) {
159 property.setValue(defaultValue);
160 } else {
161 log.warn("Default value {} is not assignable to the field of type {}.", defaultValue, field.getPropertyDataSource().getType().getName());
162 }
163 }
164 }
165
166
167
168
169 protected Object createDefaultValue(Property<?> property) {
170 String defaultValue = definition.getDefaultValue();
171 if (StringUtils.isNotBlank(defaultValue)) {
172 return DefaultPropertyUtil.createTypedValue(property.getType(), defaultValue);
173 }
174 return null;
175 }
176
177 @Override
178 public D getFieldDefinition() {
179 return this.definition;
180 }
181
182
183
184
185 protected abstract Field<T> createFieldComponent();
186
187 @Override
188 public View getView() {
189 final CssLayout fieldView = new CssLayout();
190 fieldView.setStyleName("field-view");
191
192 Label label = new Label();
193 label.setSizeUndefined();
194 label.setCaption(getFieldDefinition().getLabel());
195
196 if (getFieldDefinition().getClass().isAssignableFrom(TextFieldDefinition.class)) {
197 final TextFieldDefinition textFieldDefinition = (TextFieldDefinition) getFieldDefinition();
198 if (textFieldDefinition.getRows() > 0) {
199 label.addStyleName("textarea");
200 }
201 }
202 if (definition.getConverterClass() != null) {
203 Converter converter = initializeConverter(definition.getConverterClass());
204 label.setConverter(converter);
205 }
206
207 Property<?> property = initializeProperty();
208
209 label.setPropertyDataSource(property);
210
211 fieldView.addComponent(label);
212
213 return new View() {
214 @Override
215 public Component asVaadinComponent() {
216 return fieldView;
217 }
218 };
219 }
220
221
222
223
224
225 @SuppressWarnings("unchecked")
226 private Property<?> initializeProperty() {
227 Class<? extends Transformer<?>> transformerClass = definition.getTransformerClass();
228
229 if (transformerClass == null) {
230
231 transformerClass = (Class<? extends Transformer<?>>) (Object) BasicTransformer.class;
232 }
233 Transformer<?> transformer = initializeTransformer(transformerClass);
234
235 return new TransformedProperty(transformer);
236 }
237
238
239
240
241
242 protected Transformer<?> initializeTransformer(Class<? extends Transformer<?>> transformerClass) {
243 return this.componentProvider.newInstance(transformerClass, item, definition, getFieldType());
244 }
245
246
247
248
249
250 protected Converter<?, ?> initializeConverter(Class<? extends Converter<?, ?>> converterClass) {
251 return this.componentProvider.newInstance(converterClass, item, definition, getFieldType());
252 }
253
254
255
256
257
258
259
260
261
262 protected Class<?> getFieldType() {
263 Class<?> type = getDefinitionType();
264 if (type == null) {
265 type = getDefaultFieldType();
266 }
267 return type;
268 }
269
270
271
272
273 protected Class<?> getDefinitionType() {
274 if (StringUtils.isNotBlank(definition.getType())) {
275 return DefaultPropertyUtil.getFieldTypeClass(definition.getType());
276 }
277 return null;
278 }
279
280
281
282
283 protected Class<?> getDefaultFieldType() {
284 return UndefinedPropertyType.class;
285 }
286
287 @Override
288 protected String getI18nBasename() {
289 return definition.getI18nBasename();
290 }
291
292
293
294
295
296
297
298 private void setConstraints() {
299
300 for (FieldValidatorDefinition validatorDefinition : definition.getValidators()) {
301 FieldValidatorFactory validatorFactory = this.fieldValidatorFactoryFactory.createFieldValidatorFactory(validatorDefinition, item);
302 if (validatorFactory != null) {
303 field.addValidator(validatorFactory.createValidator());
304 } else {
305 log.warn("Not able to create Validation for the following definition {}", definition.toString());
306 }
307 }
308
309 if (definition.isRequired()) {
310 field.setInvalidCommitted(true);
311 field.setRequired(true);
312 field.setRequiredError(definition.getRequiredErrorMessage());
313 }
314
315
316 if (field.getPropertyDataSource() != null) {
317 field.getPropertyDataSource().setReadOnly(definition.isReadOnly());
318 }
319 }
320
321 @Override
322 public void setComponentProvider(ComponentProvider componentProvider) {
323 this.componentProvider = componentProvider;
324 }
325
326
327
328
329
330
331
332
333 @Deprecated
334 private static class StringToLongConverter extends AbstractStringToNumberConverter<Long> {
335
336 @Override
337 public Long convertToModel(String value, Class<? extends Long> targetType, Locale locale) throws ConversionException {
338 Number n = convertToNumber(value, targetType, locale);
339 return n == null ? null : n.longValue();
340 }
341
342 @Override
343 public Class<Long> getModelType() {
344 return Long.class;
345 }
346 }
347
348 }