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.i18n.I18NAwareProperty;
39 import info.magnolia.ui.api.view.View;
40 import info.magnolia.ui.form.AbstractFormItem;
41 import info.magnolia.ui.form.field.definition.FieldDefinition;
42 import info.magnolia.ui.form.field.definition.TextFieldDefinition;
43 import info.magnolia.ui.form.validator.definition.FieldValidatorDefinition;
44 import info.magnolia.ui.form.validator.factory.FieldValidatorFactory;
45 import info.magnolia.ui.form.validator.registry.FieldValidatorFactoryFactory;
46 import info.magnolia.ui.vaadin.integration.jcr.DefaultPropertyUtil;
47 import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
48 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
49
50 import java.util.Locale;
51
52 import javax.jcr.Node;
53 import javax.jcr.RepositoryException;
54
55 import org.apache.commons.lang.StringUtils;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import com.vaadin.data.Item;
60 import com.vaadin.data.Property;
61 import com.vaadin.data.util.converter.AbstractStringToNumberConverter;
62 import com.vaadin.server.Sizeable.Unit;
63 import com.vaadin.ui.AbstractTextField;
64 import com.vaadin.ui.Component;
65 import com.vaadin.ui.CssLayout;
66 import com.vaadin.ui.Field;
67 import com.vaadin.ui.Label;
68
69
70
71
72
73
74
75
76 public abstract class AbstractFieldFactory<D extends FieldDefinition, T> extends AbstractFormItem implements FieldFactory {
77 private static final Logger log = LoggerFactory.getLogger(AbstractFieldFactory.class);
78 protected Item item;
79 protected Field<T> field;
80 protected D definition;
81 private FieldValidatorFactoryFactory fieldValidatorFactoryFactory;
82 private I18nContentSupport i18nContentSupport;
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 @Override
96 public void setI18nContentSupport(I18nContentSupport i18nContentSupport) {
97 this.i18nContentSupport = i18nContentSupport;
98 }
99
100 @Override
101 public Field<T> createField() {
102 if (field == null) {
103
104 this.field = createFieldComponent();
105
106 Property<?> property = getOrCreateProperty();
107
108
109 if (Long.class.equals(property.getType()) && field instanceof AbstractTextField) {
110 ((AbstractTextField) field).setConverter(new StringToLongConverter());
111 }
112 setPropertyDataSource(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 this.field.setCaption(getMessage(getFieldDefinition().getLabel()) + (getFieldDefinition().isRequired() ? "<span class=\"requiredfield\">*</span>" : ""));
122
123 setConstraints();
124
125 }
126 return this.field;
127 }
128
129 @Override
130 public D getFieldDefinition() {
131 return this.definition;
132 }
133
134
135
136
137 public void setPropertyDataSource(Property<?> property) {
138 this.field.setPropertyDataSource(property);
139 }
140
141
142
143
144 protected abstract Field<T> createFieldComponent();
145
146 @Override
147 public View getView() {
148 Property<?> property = getOrCreateProperty();
149
150 final CssLayout fieldView = new CssLayout();
151 fieldView.setStyleName("field-view");
152
153 Label label = new Label();
154 label.setSizeUndefined();
155 label.setCaption(getFieldDefinition().getLabel());
156
157 if (getFieldDefinition().getClass().isAssignableFrom(TextFieldDefinition.class)) {
158 final TextFieldDefinition textFieldDefinition = (TextFieldDefinition) getFieldDefinition();
159 if (textFieldDefinition.getRows() > 0) {
160 label.addStyleName("textarea");
161 }
162 }
163 label.setPropertyDataSource(property);
164
165 fieldView.addComponent(label);
166
167 return new View() {
168 @Override
169 public Component asVaadinComponent() {
170 return fieldView;
171 }
172 };
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187 protected Property<?> getOrCreateProperty() {
188 String propertyName = definition.getName();
189 Class<?> fieldType = getFieldType(definition);
190 String defaultValue = definition.getDefaultValue();
191 if (definition.isI18n()) {
192 I18NAwareProperty<String> property = componentProvider.newInstance(I18NAwareProperty.class, propertyName, fieldType, item);
193 property.setDefaultValue(defaultValue);
194 return property;
195
196 } else {
197 Property<?> property = item.getItemProperty(propertyName);
198 if (property == null) {
199 property = DefaultPropertyUtil.newDefaultProperty(fieldType.getSimpleName(), defaultValue);
200 item.addItemProperty(propertyName, property);
201 }
202 return property;
203 }
204 }
205
206
207
208
209
210
211 protected Class<?> getFieldType(FieldDefinition fieldDefinition) {
212 if (StringUtils.isNotBlank(fieldDefinition.getType())) {
213 return DefaultPropertyUtil.getFieldTypeClass(fieldDefinition.getType());
214 }
215 return getDefaultFieldType(fieldDefinition);
216 }
217
218 protected Class<?> getDefaultFieldType(FieldDefinition fieldDefinition) {
219 return String.class;
220 }
221
222
223
224
225
226
227 protected Node getRelatedNode(Item fieldRelatedItem) throws RepositoryException {
228 return (fieldRelatedItem instanceof JcrNewNodeAdapter) ? ((JcrNewNodeAdapter) fieldRelatedItem).getJcrItem() : ((JcrNodeAdapter) fieldRelatedItem).applyChanges();
229 }
230
231 public String getPropertyName() {
232 return definition.getName();
233 }
234
235 @Override
236 protected String getI18nBasename() {
237 return definition.getI18nBasename();
238 }
239
240
241
242
243
244
245
246 private void setConstraints() {
247
248 for (FieldValidatorDefinition validatorDefinition : definition.getValidators()) {
249 FieldValidatorFactory validatorFactory = this.fieldValidatorFactoryFactory.createFieldValidatorFactory(validatorDefinition, item);
250 if (validatorFactory != null) {
251 this.field.addValidator(validatorFactory.createValidator());
252 } else {
253 log.warn("Not able to create Validation for the following definition {}", definition.toString());
254 }
255 }
256
257 if (definition.isRequired()) {
258 field.setRequired(true);
259 field.setRequiredError(getMessage(definition.getRequiredErrorMessage()));
260 }
261
262
263 if (field.getPropertyDataSource() != null) {
264 field.getPropertyDataSource().setReadOnly(definition.isReadOnly());
265 }
266 }
267
268 @Override
269 public void setComponentProvider(ComponentProvider componentProvider) {
270 this.componentProvider = componentProvider;
271 }
272
273
274
275
276
277
278
279
280 @Deprecated
281 private static class StringToLongConverter extends AbstractStringToNumberConverter<Long> {
282
283 @Override
284 public Long convertToModel(String value, Class<? extends Long> targetType, Locale locale) throws ConversionException {
285 Number n = convertToNumber(value, targetType, locale);
286 return n == null ? null : n.longValue();
287 }
288
289 @Override
290 public Class<Long> getModelType() {
291 return Long.class;
292 }
293 }
294 }