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.jcr.util.NodeUtil;
37 import info.magnolia.jcr.util.SessionUtil;
38 import info.magnolia.objectfactory.Components;
39 import info.magnolia.ui.api.context.UiContext;
40 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
41 import info.magnolia.ui.form.field.definition.SelectFieldDefinition;
42 import info.magnolia.ui.form.field.definition.SelectFieldOptionDefinition;
43 import info.magnolia.ui.form.field.transformer.UndefinedPropertyType;
44
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.Comparator;
48 import java.util.HashSet;
49 import java.util.Iterator;
50 import java.util.List;
51
52 import javax.inject.Inject;
53 import javax.jcr.Node;
54 import javax.jcr.RepositoryException;
55
56 import org.apache.commons.collections4.ComparatorUtils;
57 import org.apache.commons.lang3.StringUtils;
58 import org.apache.jackrabbit.commons.predicate.Predicate;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 import com.vaadin.server.Resource;
63 import com.vaadin.server.ThemeResource;
64 import com.vaadin.v7.data.Item;
65 import com.vaadin.v7.data.Property;
66 import com.vaadin.v7.data.util.IndexedContainer;
67 import com.vaadin.v7.ui.AbstractSelect;
68 import com.vaadin.v7.ui.AbstractSelect.ItemCaptionMode;
69 import com.vaadin.v7.ui.ComboBox;
70
71
72
73
74
75
76
77
78
79
80 @Deprecated
81 public class SelectFieldFactory<D extends SelectFieldDefinition> extends AbstractFieldFactory<D, Object> {
82
83 private static final Logger log = LoggerFactory.getLogger(SelectFieldFactory.class);
84
85 private List<String> initialSelectedKeys = new ArrayList<>();
86 private String optionValueName;
87 private String optionLabelName;
88 private final String optionIconName = SelectFieldDefinition.OPTION_ICONSRC_PROPERTY_NAME;
89 private boolean hasOptionIcon = false;
90 private boolean sortOptions = true;
91
92 protected AbstractSelect select;
93
94 @Inject
95 public SelectFieldFactory(D definition, Item relatedFieldItem, UiContext uiContext, I18NAuthoringSupport i18nAuthoringSupport) {
96 super(definition, relatedFieldItem, uiContext, i18nAuthoringSupport);
97 }
98
99
100
101
102 @Deprecated
103 public SelectFieldFactory(D definition, Item relatedFieldItem) {
104 this(definition, relatedFieldItem, null, Components.getComponent(I18NAuthoringSupport.class));
105 }
106
107 @Override
108 protected AbstractSelect createFieldComponent() {
109
110 optionValueName = definition.getValueProperty();
111 optionLabelName = definition.getLabelProperty();
112 sortOptions = definition.isSortOptions();
113
114 select = createSelectionField();
115 select.setContainerDataSource(buildOptions());
116 select.setNullSelectionAllowed(false);
117 select.setMultiSelect(false);
118 select.setNewItemsAllowed(false);
119 if (select instanceof ComboBox) {
120 ((ComboBox) select).setFilteringMode(definition.getFilteringMode());
121 ((ComboBox) select).setTextInputAllowed(definition.isTextInputAllowed());
122 ((ComboBox) select).setPageLength(definition.getPageLength());
123 }
124 select.setItemCaptionMode(ItemCaptionMode.PROPERTY);
125 select.setItemCaptionPropertyId(optionLabelName);
126
127 return select;
128 }
129
130
131
132
133 protected AbstractSelect createSelectionField() {
134 return new ComboBox();
135 }
136
137
138
139
140
141
142
143
144 @SuppressWarnings("unchecked")
145 private IndexedContainer buildOptions() {
146 IndexedContainer optionContainer = new IndexedContainer();
147
148 List<SelectFieldOptionDefinition> options = getOptions();
149 sortOptions(options);
150
151 if (!options.isEmpty()) {
152 Class<?> resolvedFieldType = getFieldType();
153
154 Class<?> fieldType = resolvedFieldType != UndefinedPropertyType.class ? resolvedFieldType : String.class;
155 optionContainer.addContainerProperty(optionValueName, fieldType, null);
156 optionContainer.addContainerProperty(optionLabelName, String.class, null);
157 if (hasOptionIcon) {
158 optionContainer.addContainerProperty(optionIconName, Resource.class, null);
159 }
160 for (SelectFieldOptionDefinition option : options) {
161 Object value = createTypedValue(option.getValue(), fieldType);
162 Item item = optionContainer.addItem(value);
163 item.getItemProperty(optionValueName).setValue(value);
164 item.getItemProperty(optionLabelName).setValue(option.getLabel());
165 if (StringUtils.isNotBlank(option.getIconSrc())) {
166 item.getItemProperty(optionIconName).setValue(getIconResource(option));
167 }
168 }
169 }
170 return optionContainer;
171 }
172
173 private void sortOptions(List<SelectFieldOptionDefinition> options) {
174 if (sortOptions) {
175 if (definition.getComparatorClass() != null) {
176 Comparator<SelectFieldOptionDefinition> comparator = initializeComparator(definition.getComparatorClass());
177 Collections.sort(options, comparator);
178 } else {
179 Collections.sort(options, new DefaultOptionComparator());
180 }
181 }
182 }
183
184 protected Comparator<SelectFieldOptionDefinition> initializeComparator(Class<? extends Comparator<SelectFieldOptionDefinition>> comparatorClass) {
185 return getComponentProvider().newInstance(comparatorClass, item, definition, getFieldType());
186 }
187
188
189
190
191
192
193
194
195
196
197 public List<SelectFieldOptionDefinition> getOptions() {
198
199
200 return getSelectFieldOptionDefinition();
201 }
202
203
204
205
206 @Deprecated
207 public List<SelectFieldOptionDefinition> getSelectFieldOptionDefinition() {
208 List<SelectFieldOptionDefinition> res = new ArrayList<>();
209
210 if (definition.getOptions() != null && !definition.getOptions().isEmpty()) {
211 for (SelectFieldOptionDefinition option : definition.getOptions()) {
212 option.setValue(getValue(option));
213 if (option.isSelected()) {
214 initialSelectedKeys.add(getValue(option));
215 }
216 if (!hasOptionIcon && StringUtils.isNotBlank(option.getIconSrc())) {
217 hasOptionIcon = true;
218 }
219 res.add(option);
220 }
221 } else if (StringUtils.isNotBlank(definition.getPath())) {
222
223 buildRemoteOptions(res);
224 }
225
226 return res;
227 }
228
229
230
231
232
233
234 public Resource getIconResource(SelectFieldOptionDefinition option) {
235 return new ThemeResource(option.getIconSrc());
236 }
237
238
239
240
241
242
243
244 private String getValue(SelectFieldOptionDefinition option) {
245 if (StringUtils.isBlank(option.getValue())) {
246 if (StringUtils.isNotBlank(option.getName())) {
247 return option.getName();
248 } else {
249 return option.getLabel();
250 }
251 } else {
252 return option.getValue();
253 }
254 }
255
256
257
258
259 @Override
260 protected Object createDefaultValue(Property property) {
261 Object defaultValue = super.createDefaultValue(property);
262 if (defaultValue == null) {
263 boolean shouldPreselectFirstValue = !select.isNullSelectionAllowed() && !select.isMultiSelect() && property.getValue() == null;
264 if (shouldPreselectFirstValue) {
265
266 if (select.getItemIds() != null && !select.getItemIds().isEmpty()) {
267 defaultValue = select.getItemIds().iterator().next();
268 }
269 }
270 }
271 return defaultValue;
272 }
273
274
275
276
277
278 protected Object getConfiguredDefaultValue() {
279 if (initialSelectedKeys.isEmpty()) {
280 return null;
281 }
282 if (select.isMultiSelect()) {
283 return new HashSet<>(initialSelectedKeys);
284 } else {
285 return initialSelectedKeys.get(0);
286 }
287 }
288
289
290
291
292
293
294
295 private void buildRemoteOptions(List<SelectFieldOptionDefinition> res) {
296 Node parent = SessionUtil.getNode(definition.getRepository(), definition.getPath());
297 if (parent != null) {
298 try {
299
300 Iterable<Node> iterable = NodeUtil.getNodes(parent, createRemoteOptionFilterPredicate());
301 Iterator<Node> iterator = iterable.iterator();
302
303 while (iterator.hasNext()) {
304 SelectFieldOptionDefinitionctFieldOptionDefinition.html#SelectFieldOptionDefinition">SelectFieldOptionDefinition option = new SelectFieldOptionDefinition();
305 Node child = iterator.next();
306
307 String label = getRemoteOptionsName(child, optionLabelName);
308 String value = getRemoteOptionsValue(child, optionValueName);
309 option.setLabel(label);
310 option.setValue(value);
311
312 if (child.hasProperty(SelectFieldDefinition.OPTION_SELECTED_PROPERTY_NAME) && Boolean.parseBoolean(child.getProperty(SelectFieldDefinition.OPTION_SELECTED_PROPERTY_NAME).getString())) {
313 option.setSelected(true);
314 initialSelectedKeys.add(option.getValue());
315 }
316 if (child.hasProperty(SelectFieldDefinition.OPTION_NAME_PROPERTY_NAME)) {
317 option.setName(child.getProperty(SelectFieldDefinition.OPTION_NAME_PROPERTY_NAME).getString());
318 }
319 if (child.hasProperty(SelectFieldDefinition.OPTION_ICONSRC_PROPERTY_NAME)) {
320 option.setIconSrc(child.getProperty(SelectFieldDefinition.OPTION_ICONSRC_PROPERTY_NAME).getString());
321 hasOptionIcon = true;
322 }
323 res.add(option);
324 }
325 } catch (Exception e) {
326 log.warn("Not able to build options based on option node " + parent.toString(), e);
327 }
328 }
329 }
330
331
332
333
334 protected Predicate createRemoteOptionFilterPredicate() {
335 return NodeUtil.MAGNOLIA_FILTER;
336 }
337
338
339
340
341
342
343 protected String getRemoteOptionsName(Node option, String propertyName) throws RepositoryException {
344 if (option.hasProperty(propertyName)) {
345 return option.getProperty(propertyName).getString();
346 } else {
347 return option.getName();
348 }
349 }
350
351
352
353
354
355
356 protected String getRemoteOptionsValue(Node option, String propertyName) throws RepositoryException {
357 return getRemoteOptionsName(option, propertyName);
358 }
359
360
361
362
363 public static class DefaultOptionComparator implements Comparator<SelectFieldOptionDefinition> {
364
365 @Override
366 public int compare(SelectFieldOptionDefinition./info/magnolia/ui/form/field/definition/SelectFieldOptionDefinition.html#SelectFieldOptionDefinition">SelectFieldOptionDefinition def, SelectFieldOptionDefinition otherDef) {
367
368 return ComparatorUtils.nullLowComparator(String.CASE_INSENSITIVE_ORDER).compare(def.getLabel(), otherDef.getLabel());
369 }
370 }
371 }