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 ComponentProvider componentProvider;
84
85 public AbstractFieldFactory(D definition, Item relatedFieldItem) {
86 this.definition = definition;
87 this.item = relatedFieldItem;
88 }
89
90 @Override
91 public void setFieldValidatorFactoryFactory(FieldValidatorFactoryFactory fieldValidatorFactoryFactory) {
92 this.fieldValidatorFactoryFactory = fieldValidatorFactoryFactory;
93 }
94
95
96
97
98
99 @Override
100 @Deprecated
101 public void setI18nContentSupport(I18nContentSupport i18nContentSupport) {
102 }
103
104 @Override
105 public Field<T> createField() {
106 if (field == null) {
107
108 this.field = createFieldComponent();
109 if (field instanceof AbstractField && definition.getConverterClass() != null) {
110 Converter<?, ?> converter = initializeConverter(definition.getConverterClass());
111 ((AbstractField) field).setConverter(converter);
112 }
113
114 Property<?> property = initializeProperty();
115
116
117 if (Long.class.equals(property.getType()) && field instanceof AbstractTextField) {
118 ((AbstractTextField) field).setConverter(new StringToLongConverter());
119 }
120
121 setPropertyDataSourceAndDefaultValue(property);
122
123 if (StringUtils.isNotBlank(definition.getStyleName())) {
124 this.field.addStyleName(definition.getStyleName());
125 }
126
127 field.setWidth(100, Unit.PERCENTAGE);
128
129
130 if (StringUtils.isNotBlank(getFieldDefinition().getLabel())) {
131 this.field.setCaption(getFieldDefinition().getLabel() + (getFieldDefinition().isRequired() ? "<span class=\"requiredfield\">*</span>" : ""));
132 }
133
134 setConstraints();
135
136 }
137 return this.field;
138 }
139
140
141
142
143
144
145
146
147 public void setPropertyDataSourceAndDefaultValue(Property<?> property) {
148 this.field.setPropertyDataSource(property);
149
150 if ((item instanceof ItemAdapter && ((ItemAdapter) item).isNew() && property.getValue() == null) || (!(item instanceof ItemAdapter) && property.getValue() == null)) {
151 setPropertyDataSourceDefaultValue(property);
152 }
153 }
154
155
156
157
158 protected void setPropertyDataSourceDefaultValue(Property property) {
159 Object defaultValue = createDefaultValue(property);
160 if (defaultValue != null && !definition.isReadOnly()) {
161 if (defaultValue.getClass().isAssignableFrom(property.getType())) {
162 property.setValue(defaultValue);
163 } else {
164 log.warn("Default value {} is not assignable to the field of type {}.", defaultValue, field.getPropertyDataSource().getType().getName());
165 }
166 }
167 }
168
169
170
171
172 protected Object createDefaultValue(Property<?> property) {
173 String defaultValue = definition.getDefaultValue();
174 if (StringUtils.isNotBlank(defaultValue)) {
175 return DefaultPropertyUtil.createTypedValue(property.getType(), defaultValue);
176 }
177 return null;
178 }
179
180 @Override
181 public D getFieldDefinition() {
182 return this.definition;
183 }
184
185
186
187
188 protected abstract Field<T> createFieldComponent();
189
190 @Override
191 public View getView() {
192 final CssLayout fieldView = new CssLayout();
193 fieldView.setStyleName("field-view");
194
195 Label label = new Label();
196 label.setSizeUndefined();
197 label.setCaption(getFieldDefinition().getLabel());
198
199 if (getFieldDefinition().getClass().isAssignableFrom(TextFieldDefinition.class)) {
200 final TextFieldDefinition textFieldDefinition = (TextFieldDefinition) getFieldDefinition();
201 if (textFieldDefinition.getRows() > 0) {
202 label.addStyleName("textarea");
203 }
204 }
205 if (definition.getConverterClass() != null) {
206 Converter converter = initializeConverter(definition.getConverterClass());
207 label.setConverter(converter);
208 }
209
210 Property<?> property = initializeProperty();
211
212 label.setPropertyDataSource(property);
213
214 fieldView.addComponent(label);
215
216 return new View() {
217 @Override
218 public Component asVaadinComponent() {
219 return fieldView;
220 }
221 };
222 }
223
224
225
226
227
228 @SuppressWarnings("unchecked")
229 private Property<?> initializeProperty() {
230 Class<? extends Transformer<?>> transformerClass = definition.getTransformerClass();
231
232 if (transformerClass == null) {
233
234 transformerClass = (Class<? extends Transformer<?>>) (Object) BasicTransformer.class;
235 }
236 Transformer<?> transformer = initializeTransformer(transformerClass);
237
238 return new TransformedProperty(transformer);
239 }
240
241
242
243
244
245 protected Transformer<?> initializeTransformer(Class<? extends Transformer<?>> transformerClass) {
246 return this.componentProvider.newInstance(transformerClass, item, definition, getFieldType());
247 }
248
249
250
251
252
253 protected Converter<?, ?> initializeConverter(Class<? extends Converter<?, ?>> converterClass) {
254 return this.componentProvider.newInstance(converterClass, item, definition, getFieldType());
255 }
256
257
258
259
260
261
262
263
264
265 protected Class<?> getFieldType() {
266 Class<?> type = getDefinitionType();
267 if (type == null) {
268 type = getDefaultFieldType();
269 }
270 return type;
271 }
272
273
274
275
276 protected Class<?> getDefinitionType() {
277 if (StringUtils.isNotBlank(definition.getType())) {
278 return DefaultPropertyUtil.getFieldTypeClass(definition.getType());
279 }
280 return null;
281 }
282
283
284
285
286 protected Class<?> getDefaultFieldType() {
287 return UndefinedPropertyType.class;
288 }
289
290 @Override
291 protected String getI18nBasename() {
292 return definition.getI18nBasename();
293 }
294
295
296
297
298
299
300
301 private void setConstraints() {
302
303 for (FieldValidatorDefinition validatorDefinition : definition.getValidators()) {
304 FieldValidatorFactory validatorFactory = this.fieldValidatorFactoryFactory.createFieldValidatorFactory(validatorDefinition, item);
305 if (validatorFactory != null) {
306 field.addValidator(validatorFactory.createValidator());
307 } else {
308 log.warn("Not able to create Validation for the following definition {}", definition.toString());
309 }
310 }
311
312 if (definition.isRequired()) {
313 field.setInvalidCommitted(true);
314 field.setRequired(true);
315 field.setRequiredError(definition.getRequiredErrorMessage());
316 }
317
318
319 if (field.getPropertyDataSource() != null) {
320 field.getPropertyDataSource().setReadOnly(definition.isReadOnly());
321 }
322 }
323
324 @Override
325 public void setComponentProvider(ComponentProvider componentProvider) {
326 this.componentProvider = componentProvider;
327 }
328
329 protected ComponentProvider getComponentProvider() {
330 return componentProvider;
331 }
332
333
334
335
336
337
338
339
340 @Deprecated
341 private static class StringToLongConverter extends AbstractStringToNumberConverter<Long> {
342
343 @Override
344 public Long convertToModel(String value, Class<? extends Long> targetType, Locale locale) throws ConversionException {
345 Number n = convertToNumber(value, targetType, locale);
346 return n == null ? null : n.longValue();
347 }
348
349 @Override
350 public Class<Long> getModelType() {
351 return Long.class;
352 }
353 }
354
355 }