1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.ui.commons.panels;
20
21 import java.text.ParseException;
22 import java.util.ArrayList;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.stream.Collectors;
27 import org.apache.commons.lang3.BooleanUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.commons.lang3.math.NumberUtils;
30 import org.apache.commons.lang3.time.FastDateFormat;
31 import org.apache.syncope.client.ui.commons.MapChoiceRenderer;
32 import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
33 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
35 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
36 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
37 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
38 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
39 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
40 import org.apache.syncope.common.lib.form.FormProperty;
41 import org.apache.syncope.common.lib.form.FormPropertyValue;
42 import org.apache.syncope.common.lib.form.SyncopeForm;
43 import org.apache.wicket.markup.html.list.ListItem;
44 import org.apache.wicket.markup.html.list.ListView;
45 import org.apache.wicket.markup.html.panel.Panel;
46 import org.apache.wicket.model.IModel;
47 import org.apache.wicket.model.PropertyModel;
48 import org.apache.wicket.model.util.ListModel;
49 import org.apache.wicket.validation.validator.PatternValidator;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class SyncopeFormPanel<F extends SyncopeForm> extends Panel {
54
55 private static final long serialVersionUID = -8847854414429745216L;
56
57 protected static final Logger LOG = LoggerFactory.getLogger(SyncopeFormPanel.class);
58
59 public SyncopeFormPanel(final String id, final F form) {
60 super(id);
61
62 ListModel<FormProperty> model = new ListModel<>(new ArrayList<>());
63 model.getObject().addAll(form.getProperties());
64
65 ListView<FormProperty> propView = new ListView<>("propView", model) {
66
67 private static final long serialVersionUID = 9101744072914090143L;
68
69 @Override
70 protected void populateItem(final ListItem<FormProperty> item) {
71 FormProperty prop = item.getModelObject();
72
73 String label = StringUtils.isBlank(prop.getName()) ? prop.getId() : prop.getName();
74
75 AbstractFieldPanel<?> field;
76 switch (prop.getType()) {
77 case Boolean:
78 field = new AjaxCheckBoxPanel("value", label, new PropertyModel<Boolean>(prop, "value") {
79
80 private static final long serialVersionUID = -3743432456095828573L;
81
82 @Override
83 public Boolean getObject() {
84 return BooleanUtils.toBoolean(prop.getValue());
85 }
86
87 @Override
88 public void setObject(final Boolean object) {
89 prop.setValue(BooleanUtils.toStringTrueFalse(object));
90 }
91 }, false);
92 break;
93
94 case Date:
95 FastDateFormat formatter = FastDateFormat.getInstance(prop.getDatePattern());
96 field = new AjaxDateTimeFieldPanel("value", label, new PropertyModel<>(prop, "value") {
97
98 private static final long serialVersionUID = -3743432456095828573L;
99
100 @Override
101 public Date getObject() {
102 try {
103 return StringUtils.isBlank(prop.getValue())
104 ? null
105 : formatter.parse(prop.getValue());
106 } catch (ParseException e) {
107 LOG.error("Unparsable date: {}", prop.getValue(), e);
108 return null;
109 }
110 }
111
112 @Override
113 public void setObject(final Date object) {
114 prop.setValue(formatter.format(object));
115 }
116 }, formatter);
117 break;
118
119 case Enum:
120 field = new AjaxDropDownChoicePanel<>(
121 "value", label, new PropertyModel<String>(prop, "value"), false).
122 setChoiceRenderer(new MapChoiceRenderer(prop.getEnumValues().stream().
123 collect(Collectors.toMap(
124 FormPropertyValue::getKey,
125 FormPropertyValue::getValue)))).
126 setChoices(prop.getEnumValues().stream().
127 map(FormPropertyValue::getKey).collect(Collectors.toList()));
128 break;
129
130 case Dropdown:
131 if (prop.isDropdownFreeForm()) {
132 field = new AjaxTextFieldPanel("value", label, new PropertyModel<>(prop, "value"), false);
133 ((AjaxTextFieldPanel) field).setChoices(prop.getDropdownValues().stream().
134 map(FormPropertyValue::getKey).collect(Collectors.toList()));
135 } else if (prop.isDropdownSingleSelection()) {
136 field = new AjaxDropDownChoicePanel<>(
137 "value", label, new PropertyModel<String>(prop, "value"), false).
138 setChoiceRenderer(new MapChoiceRenderer(prop.getDropdownValues().stream().
139 collect(Collectors.toMap(
140 FormPropertyValue::getKey,
141 FormPropertyValue::getValue)))).
142 setChoices(prop.getDropdownValues().stream().
143 map(FormPropertyValue::getKey).collect(Collectors.toList()));
144 } else {
145 field = new AjaxPalettePanel.Builder<String>().setName(label).
146 setRenderer(new MapChoiceRenderer(prop.getDropdownValues().stream().
147 collect(Collectors.toMap(
148 FormPropertyValue::getKey,
149 FormPropertyValue::getValue)))).build(
150 "value",
151 new IModel<List<String>>() {
152
153 private static final long serialVersionUID = 1015030402166681242L;
154
155 @Override
156 public List<String> getObject() {
157 return Optional.ofNullable(prop.getValue()).
158 map(v -> List.of(v.split(";"))).
159 orElse(null);
160 }
161
162 @Override
163 public void setObject(final List<String> object) {
164 prop.setValue(Optional.ofNullable(object).
165 map(v -> v.stream().collect(Collectors.joining(";"))).
166 orElse(null));
167 }
168 }, new ListModel<>(prop.getDropdownValues().stream().
169 map(FormPropertyValue::getKey).collect(Collectors.toList())));
170 }
171 break;
172
173 case Long:
174 field = new AjaxSpinnerFieldPanel.Builder<Long>().build(
175 "value",
176 label,
177 Long.class,
178 new PropertyModel<>(prop, "value") {
179
180 private static final long serialVersionUID = -7688359318035249200L;
181
182 @Override
183 public Long getObject() {
184 return StringUtils.isBlank(prop.getValue())
185 ? null
186 : NumberUtils.toLong(prop.getValue());
187 }
188
189 @Override
190 public void setObject(final Long object) {
191 prop.setValue(String.valueOf(object));
192 }
193 });
194 break;
195
196 case Password:
197 field = new AjaxPasswordFieldPanel("value", label, new PropertyModel<>(prop, "value"), false).
198 setResetPassword(false);
199 break;
200
201 case String:
202 default:
203 field = new AjaxTextFieldPanel("value", label, new PropertyModel<>(prop, "value"), false);
204 Optional.ofNullable(prop.getStringRegEx()).
205 ifPresent(re -> ((AjaxTextFieldPanel) field).addValidator(new PatternValidator(re)));
206 break;
207 }
208
209 field.setReadOnly(!prop.isWritable());
210 if (prop.isRequired()) {
211 field.addRequiredLabel();
212 }
213
214 item.add(field);
215 }
216 };
217 add(propView.setReuseItems(true));
218 }
219 }