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