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.dialog.formdialog;
35
36 import info.magnolia.objectfactory.Components;
37 import info.magnolia.ui.api.app.SubAppContext;
38 import info.magnolia.ui.api.context.UiContext;
39 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
40 import info.magnolia.ui.form.Form;
41 import info.magnolia.ui.form.FormItem;
42 import info.magnolia.ui.form.FormPresenter;
43 import info.magnolia.ui.form.FormTab;
44 import info.magnolia.ui.form.definition.FormDefinition;
45 import info.magnolia.ui.form.definition.TabDefinition;
46 import info.magnolia.ui.form.field.definition.FieldDefinition;
47 import info.magnolia.ui.vaadin.form.FormSection;
48 import info.magnolia.ui.vaadin.form.FormViewReduced;
49
50 import java.util.Iterator;
51 import java.util.List;
52 import java.util.Locale;
53 import java.util.Map;
54 import java.util.Optional;
55
56 import javax.inject.Inject;
57
58 import org.apache.commons.lang3.ObjectUtils;
59 import org.apache.commons.lang3.StringUtils;
60
61 import com.google.common.collect.Maps;
62 import com.vaadin.ui.Component;
63 import com.vaadin.v7.data.Item;
64 import com.vaadin.v7.ui.Field;
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public class FormPresenterImpl implements FormPresenter {
79
80 private final Map<String, Field<?>> cachedFields = Maps.newHashMap();
81
82 private final Map<String, FormTab> cachedTabs = Maps.newHashMap();
83
84 private final I18NAuthoringSupport i18nAuthoringSupport;
85
86 private final FormBuilder formBuilder;
87
88 private final UiContext uiContext;
89
90 private FormDefinition formDefinition;
91
92 private FormViewReduced formView;
93
94 private Locale activeLocale;
95
96 private Item itemDatasource;
97
98 @Inject
99 public FormPresenterImpl(FormBuilder formBuilder, UiContext uiContext, I18NAuthoringSupport i18nAuthoringSupport) {
100 this.i18nAuthoringSupport = i18nAuthoringSupport;
101 this.formBuilder = formBuilder;
102 this.uiContext = uiContext;
103 }
104
105
106
107
108 @Deprecated
109 public FormPresenterImpl(FormBuilder formBuilder, UiContext uiContext) {
110 this(formBuilder, uiContext, Components.getComponent(I18NAuthoringSupport.class));
111 }
112
113 @Override
114 public void presentView(FormViewReduced formView, FormDefinition formDefinition, Item item, FormItem parent) {
115 this.formView = formView;
116 this.itemDatasource = item;
117 this.formDefinition = formDefinition;
118
119 cachedFields.clear();
120 cachedTabs.clear();
121 activeLocale = getCurrentAuthoringLocale(uiContext, item);
122
123 buildForm((FormView) this.formView, formDefinition, item, parent, activeLocale);
124
125
126 if (uiContext instanceof SubAppContext) {
127 formView.setListener(newLocale -> {
128 if (newLocale != null && !ObjectUtils.equals(((SubAppContext) uiContext).getAuthoringLocale(), newLocale)) {
129 setLocale(newLocale);
130 }
131 });
132 }
133 }
134
135 @Override
136 public boolean isValid() {
137 return formView.isValid();
138 }
139
140 @Override
141 public void setLocale(Locale locale) {
142 if (uiContext instanceof SubAppContext && !ObjectUtils.equals(locale, this.activeLocale)) {
143 this.activeLocale = locale;
144 ((SubAppContext) uiContext).setAuthoringLocale(locale);
145 updateForm(locale);
146 }
147 }
148
149 protected void updateForm(Locale locale) {
150 for (FormSection formSection : formView.getFormSections()) {
151 String tabName = formSection.getName();
152 Optional<TabDefinition> matchingTab = formDefinition.getTabs().stream()
153 .filter(tabDefinition -> tabDefinition.getName().equals(tabName))
154 .findFirst();
155
156 if (matchingTab.isPresent()) {
157 TabDefinition tabDefinition = matchingTab.get();
158 FormTab formTab = cachedTabs.get(tabDefinition.getName());
159 formSection.removeAllComponents();
160 for (FieldDefinition fieldDefinition : tabDefinition.getFields()) {
161 Field<?> field = getCachedField(fieldDefinition, locale);
162 if (field == null) {
163 field = createField(fieldDefinition, itemDatasource, formTab, locale);
164 putToCache(fieldDefinition, field, locale);
165 }
166 if (field != null) {
167 formSection.addComponent(field);
168 }
169 }
170 }
171 }
172
173 if (formView instanceof ResurfaceFormViewImpl) {
174 ((ResurfaceFormViewImpl) formView).updateFormView();
175 }
176 }
177
178 private void buildForm(FormView view, FormDefinition formDefinition, Item item, FormItem parent, Locale locale) {
179 final String description = formDefinition.getDescription();
180 final String label = formDefinition.getLabel();
181
182
183
184
185
186 if (StringUtils.isNotBlank(description) && !formBuilder.isMessageKey(description)) {
187 view.setDescription(description);
188 }
189
190 if (StringUtils.isNotBlank(label) && !formBuilder.isMessageKey(label)) {
191 view.setCaption(label);
192 }
193
194 buildReducedForm(formDefinition, view, item, parent, locale);
195
196 if (formBuilder.hasI18nAwareFields(formDefinition)) {
197 view.setAvailableLocales(i18nAuthoringSupport.getAvailableLocales(item));
198 view.setCurrentLocale(locale);
199 }
200 }
201
202 private void buildReducedForm(FormDefinition formDefinition, FormViewReduced view, Item item, FormItem parent, Locale locale) {
203 final Form form = new Form(formDefinition);
204 form.setParent(parent);
205 view.setItemDataSource(item);
206
207 boolean firstFieldIsBuilt = false;
208
209 for (TabDefinition tabDefinition : formDefinition.getTabs()) {
210 FormTab tab = buildFormTab(tabDefinition, item, form, locale);
211 if (tab == null) continue;
212
213 Iterator<Component> fieldIt = tab.getContainer().iterator();
214 while (fieldIt.hasNext()) {
215 view.addField((Field<?>) fieldIt.next());
216 }
217
218 fieldIt = tab.getContainer().iterator();
219 if (!firstFieldIsBuilt && fieldIt.hasNext()) {
220 ((Component.Focusable) fieldIt.next()).focus();
221 firstFieldIsBuilt = true;
222 }
223
224 view.addFormSection(tabDefinition.getLabel(), tab.getContainer());
225 cachedTabs.put(tabDefinition.getName(), tab);
226 }
227 view.setShowAllEnabled(view.getFormSections().size() > 1);
228 }
229
230 private FormTab buildFormTab(TabDefinition tabDefinition, Item itemDatasource, Form parentForm, Locale locale) {
231 List<FieldDefinition> fields = tabDefinition.getFields();
232 if (fields == null || fields.isEmpty()) {
233 return null;
234 }
235 FormTab tab = new FormTab(tabDefinition);
236 tab.setParent(parentForm);
237 tab.getContainer().setName(tabDefinition.getName());
238 for (final FieldDefinition fieldDefinition : fields) {
239
240 Field<?> field = getCachedField(fieldDefinition, locale);
241 if (field == null) {
242 field = createField(fieldDefinition, itemDatasource, tab, locale);
243 }
244
245 if (field != null) {
246 tab.addField(field);
247 final String helpDescription = fieldDefinition.getDescription();
248 if (StringUtils.isNotBlank(helpDescription) && !formBuilder.isMessageKey(helpDescription)) {
249 tab.setComponentHelpDescription(field, helpDescription);
250 }
251 }
252 }
253 return tab;
254 }
255
256
257
258
259 private Locale getCurrentAuthoringLocale(UiContext uiContext, Item item) {
260 if (uiContext instanceof SubAppContext && ((SubAppContext) uiContext).getAuthoringLocale() != null) {
261 return ((SubAppContext) uiContext).getAuthoringLocale();
262 } else {
263 return i18nAuthoringSupport.getDefaultLocale(item);
264 }
265 }
266
267
268
269
270 private Field<?> createField(FieldDefinition fieldDefinition, Item item, FormTab parentTab, Locale locale) {
271 Field<?> field = formBuilder.createField(fieldDefinition, item, parentTab);
272
273 if (field != null) {
274 String cachedFieldName = getCachedFieldName(fieldDefinition, locale);
275 cachedFields.put(cachedFieldName, field);
276 }
277 return field;
278 }
279
280 private String getCachedFieldName(FieldDefinition fieldDefinition, Locale locale) {
281 if (!formBuilder.isI18nAware(fieldDefinition) || locale == null) {
282 return fieldDefinition.getName();
283 }
284 String cachedFieldName = fieldDefinition.getName() + "_" + locale.getDisplayLanguage();
285 if (!locale.getDisplayCountry().isEmpty()) {
286 cachedFieldName += "_" + locale.getDisplayCountry();
287 }
288
289 return cachedFieldName;
290 }
291
292 private Field<?> getCachedField(FieldDefinition fieldDefinition, Locale locale) {
293 return cachedFields.get(getCachedFieldName(fieldDefinition, locale));
294 }
295
296 private void putToCache(FieldDefinition fieldDefinition, Field<?> field, Locale locale) {
297 cachedFields.put(getCachedFieldName(fieldDefinition, locale), field);
298 }
299 }