1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.enduser.panels.any;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.stream.Collectors;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.commons.lang3.time.DateFormatUtils;
28 import org.apache.commons.lang3.time.FastDateFormat;
29 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
30 import org.apache.syncope.client.enduser.layout.CustomizationOption;
31 import org.apache.syncope.client.enduser.markup.html.form.BinaryFieldPanel;
32 import org.apache.syncope.client.enduser.markup.html.form.MultiFieldPanel;
33 import org.apache.syncope.client.ui.commons.SchemaUtils;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
35 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
36 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateFieldPanel;
37 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
38 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
39 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
40 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
41 import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel;
42 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
43 import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
44 import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
45 import org.apache.syncope.common.lib.Attr;
46 import org.apache.syncope.common.lib.Attributable;
47 import org.apache.syncope.common.lib.EntityTOUtils;
48 import org.apache.syncope.common.lib.to.AnyTO;
49 import org.apache.syncope.common.lib.to.GroupableRelatableTO;
50 import org.apache.syncope.common.lib.to.MembershipTO;
51 import org.apache.syncope.common.lib.to.PlainSchemaTO;
52 import org.apache.syncope.common.lib.types.AttrSchemaType;
53 import org.apache.syncope.common.lib.types.SchemaType;
54 import org.apache.wicket.AttributeModifier;
55 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
56 import org.apache.wicket.markup.html.WebMarkupContainer;
57 import org.apache.wicket.markup.html.basic.Label;
58 import org.apache.wicket.markup.html.form.IChoiceRenderer;
59 import org.apache.wicket.markup.html.list.ListItem;
60 import org.apache.wicket.markup.html.list.ListView;
61 import org.apache.wicket.model.IModel;
62 import org.apache.wicket.model.LoadableDetachableModel;
63 import org.apache.wicket.model.Model;
64 import org.apache.wicket.model.PropertyModel;
65 import org.apache.wicket.model.StringResourceModel;
66 import org.apache.wicket.model.util.ListModel;
67
68 public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
69
70 private static final long serialVersionUID = 552437609667518888L;
71
72 protected final AnyTO previousObject;
73
74 protected String fileKey = "";
75
76 public PlainAttrs(
77 final String id,
78 final UserWrapper modelObject,
79 final List<String> anyTypeClasses,
80 final Map<String, CustomizationOption> whichPlainAttrs) throws IllegalArgumentException {
81
82 super(id, modelObject, anyTypeClasses, whichPlainAttrs);
83
84 fileKey = modelObject.getInnerObject().getUsername();
85
86 previousObject = modelObject.getPreviousUserTO();
87
88 add(new PlainSchemasOwn("plainSchemas", schemas, attrs).setOutputMarkupId(true));
89 add(new ListView<>("membershipsPlainSchemas", membershipTOs) {
90
91 private static final long serialVersionUID = 6741044372185745296L;
92
93 @Override
94 protected void populateItem(final ListItem<MembershipTO> item) {
95 MembershipTO membershipTO = item.getModelObject();
96 item.add(new Accordion("membershipPlainSchemas", List.of(new AbstractTab(
97 new StringResourceModel(
98 "attributes.membership.accordion",
99 PlainAttrs.this,
100 Model.of(membershipTO))) {
101
102 private static final long serialVersionUID = 1037272333056449378L;
103
104 @Override
105 public WebMarkupContainer getPanel(final String panelId) {
106 return new PlainSchemasMemberships(
107 panelId,
108 membershipTO.getGroupName(),
109 membershipSchemas.get(membershipTO.getGroupKey()),
110 new LoadableDetachableModel<>() {
111
112 private static final long serialVersionUID = 526768546610546553L;
113
114 @Override
115 protected Attributable load() {
116 return membershipTO;
117 }
118
119 });
120 }
121 }), Model.of(-1)).setOutputMarkupId(true));
122 }
123 });
124 }
125
126 @Override
127 protected SchemaType getSchemaType() {
128 return SchemaType.PLAIN;
129 }
130
131 @Override
132 protected List<Attr> getAttrsFromTO() {
133 return userTO.getPlainAttrs().stream().sorted(attrComparator).collect(Collectors.toList());
134 }
135
136 @Override
137 protected List<Attr> getAttrsFromTO(final MembershipTO membershipTO) {
138 return membershipTO.getPlainAttrs().stream().sorted(attrComparator).collect(Collectors.toList());
139 }
140
141 @Override
142 protected void setAttrs() {
143 List<Attr> plainAttrs = new ArrayList<>();
144
145 Map<String, Attr> attrMap = EntityTOUtils.buildAttrMap(userTO.getPlainAttrs());
146
147 plainAttrs.addAll(schemas.values().stream().map(schema -> {
148 Attr attrTO = new Attr();
149 attrTO.setSchema(schema.getKey());
150 if (attrMap.get(schema.getKey()) == null || attrMap.get(schema.getKey()).getValues().isEmpty()) {
151 attrTO.getValues().add("");
152 } else {
153 attrTO = attrMap.get(schema.getKey());
154 }
155 return attrTO;
156 }).collect(Collectors.toList()));
157
158 userTO.getPlainAttrs().clear();
159 userTO.getPlainAttrs().addAll(plainAttrs);
160 }
161
162 @Override
163 protected void setAttrs(final MembershipTO membershipTO) {
164 Map<String, Attr> attrMap = GroupableRelatableTO.class.cast(userTO).getMembership(membershipTO.getGroupKey()).
165 map(gr -> EntityTOUtils.buildAttrMap(gr.getPlainAttrs())).
166 orElseGet(() -> new HashMap<>());
167
168 List<Attr> plainAttrs = membershipSchemas.get(membershipTO.getGroupKey()).values().stream().map(schema -> {
169 Attr attr = new Attr();
170 attr.setSchema(schema.getKey());
171 if (attrMap.get(schema.getKey()) == null || attrMap.get(schema.getKey()).getValues().isEmpty()) {
172 attr.getValues().add(StringUtils.EMPTY);
173 } else {
174 attr.getValues().addAll(attrMap.get(schema.getKey()).getValues());
175 }
176 return attr;
177 }).collect(Collectors.toList());
178
179 membershipTO.getPlainAttrs().clear();
180 membershipTO.getPlainAttrs().addAll(plainAttrs);
181 }
182
183 @SuppressWarnings({ "rawtypes", "unchecked" })
184 protected FieldPanel getFieldPanel(final PlainSchemaTO schemaTO) {
185 return getFieldPanel(schemaTO, null);
186 }
187
188 @SuppressWarnings({ "rawtypes", "unchecked" })
189 protected FieldPanel getFieldPanel(final PlainSchemaTO plainSchema, final String groupName) {
190 boolean required = plainSchema.getMandatoryCondition().equalsIgnoreCase("true");
191 boolean readOnly = plainSchema.isReadonly() || renderAsReadonly(plainSchema.getKey(), groupName);
192 AttrSchemaType type = plainSchema.getType();
193 boolean jexlHelp = false;
194
195 FieldPanel panel;
196 switch (type) {
197 case Boolean:
198 panel = new AjaxCheckBoxPanel(
199 "panel",
200 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
201 new Model<>(),
202 true);
203 panel.setRequired(required);
204 break;
205
206 case Date:
207 String datePattern = plainSchema.getConversionPattern() == null
208 ? DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.getPattern()
209 : plainSchema.getConversionPattern();
210
211 if (StringUtils.containsIgnoreCase(datePattern, "H")) {
212 panel = new AjaxDateTimeFieldPanel(
213 "panel",
214 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
215 new Model<>(),
216 FastDateFormat.getInstance(datePattern));
217 } else {
218 panel = new AjaxDateFieldPanel(
219 "panel",
220 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
221 new Model<>(),
222 FastDateFormat.getInstance(datePattern));
223 }
224
225 if (required) {
226 panel.addRequiredLabel();
227 }
228
229 break;
230
231 case Enum:
232 panel = new AjaxDropDownChoicePanel<>("panel",
233 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
234 ((AjaxDropDownChoicePanel<String>) panel).setChoices(SchemaUtils.getEnumeratedValues(plainSchema));
235
236 if (StringUtils.isNotBlank(plainSchema.getEnumerationKeys())) {
237 ((AjaxDropDownChoicePanel) panel).setChoiceRenderer(new IChoiceRenderer<String>() {
238
239 private static final long serialVersionUID = -3724971416312135885L;
240
241 private final Map<String, String> valueMap = SchemaUtils.getEnumeratedKeyValues(plainSchema);
242
243 @Override
244 public String getDisplayValue(final String value) {
245 return valueMap.get(value) == null ? value : valueMap.get(value);
246 }
247
248 @Override
249 public String getIdValue(final String value, final int i) {
250 return value;
251 }
252
253 @Override
254 public String getObject(
255 final String id, final IModel<? extends List<? extends String>> choices) {
256 return id;
257 }
258 });
259 }
260
261 if (required) {
262 panel.addRequiredLabel();
263 }
264 break;
265
266 case Long:
267 panel = new AjaxSpinnerFieldPanel.Builder<Long>().enableOnChange().build(
268 "panel",
269 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
270 Long.class,
271 new Model<>());
272
273 if (required) {
274 panel.addRequiredLabel();
275 }
276 break;
277
278 case Double:
279 panel = new AjaxSpinnerFieldPanel.Builder<Double>().enableOnChange().step(0.1).build(
280 "panel",
281 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
282 Double.class,
283 new Model<>());
284
285 if (required) {
286 panel.addRequiredLabel();
287 }
288 break;
289
290 case Binary:
291 panel = new BinaryFieldPanel(
292 "panel",
293 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()),
294 new Model<>(),
295 plainSchema.getMimeType(),
296 fileKey);
297 if (required) {
298 panel.addRequiredLabel();
299 }
300 break;
301
302 case Encrypted:
303 panel = new EncryptedFieldPanel("panel",
304 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
305
306 if (required) {
307 panel.addRequiredLabel();
308 }
309 break;
310
311 default:
312 panel = new AjaxTextFieldPanel("panel",
313 plainSchema.getLabel(SyncopeEnduserSession.get().getLocale()), new Model<>(), true);
314
315 if (jexlHelp) {
316 AjaxTextFieldPanel.class.cast(panel).enableJexlHelp();
317 }
318
319 if (required) {
320 panel.addRequiredLabel();
321 }
322 }
323
324 panel.setReadOnly(readOnly);
325 panel.setMarkupId(StringUtils.isBlank(groupName)
326 ? plainSchema.getKey() : groupName + '.' + plainSchema.getKey());
327
328 Label label = (Label) panel.get(AbstractFieldPanel.LABEL);
329 label.add(new AttributeModifier("for", FORM_SUFFIX
330 + (StringUtils.isBlank(groupName) ? plainSchema.getKey() : groupName + '.' + plainSchema.getKey())));
331
332 return panel;
333 }
334
335 protected class PlainSchemasMemberships extends Schemas {
336
337 private static final long serialVersionUID = 456754923340249215L;
338
339 public PlainSchemasMemberships(
340 final String id,
341 final String groupName,
342 final Map<String, PlainSchemaTO> schemas,
343 final IModel<Attributable> attributableTO) {
344
345 super(id);
346
347 add(new ListView<>("schemas",
348 new ListModel<>(new ArrayList<>(
349 attributableTO.getObject().getPlainAttrs().stream().sorted(attrComparator).
350 collect(Collectors.toList())))) {
351
352 private static final long serialVersionUID = 5306618783986001008L;
353
354 @Override
355 @SuppressWarnings({ "unchecked", "rawtypes" })
356 protected void populateItem(final ListItem<Attr> item) {
357 Attr attr = item.getModelObject();
358 PlainSchemaTO schema = schemas.get(attr.getSchema());
359
360
361 if (attr.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
362 attr.getValues().clear();
363 attr.getValues().addAll(getDefaultValues(attr.getSchema(), groupName));
364 }
365
366 AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attr.getSchema()));
367 if (schemas.get(attr.getSchema()).isMultivalue()) {
368 panel = new MultiFieldPanel.Builder<>(
369 new PropertyModel<>(attr, "values")).build(
370 "panel",
371 schemas.get(attr.getSchema()).getLabel(SyncopeEnduserSession.get().getLocale()),
372 FieldPanel.class.cast(panel));
373
374 panel.setReadOnly(schema == null ? false : schema.isReadonly());
375 } else {
376 FieldPanel.class.cast(panel).setNewModel(attr.getValues()).
377 setReadOnly(schema == null ? false : schema.isReadonly());
378 }
379
380 item.add(panel);
381 }
382 });
383 }
384 }
385
386 protected class PlainSchemasOwn extends Schemas {
387
388 private static final long serialVersionUID = -4730563859116024676L;
389
390 public PlainSchemasOwn(
391 final String id,
392 final Map<String, PlainSchemaTO> schemas,
393 final IModel<List<Attr>> attrTOs) {
394
395 super(id);
396
397 add(new ListView<>("schemas", attrTOs) {
398
399 private static final long serialVersionUID = 9101744072914090143L;
400
401 @Override
402 @SuppressWarnings({ "unchecked", "rawtypes" })
403 protected void populateItem(final ListItem<Attr> item) {
404 Attr attrTO = item.getModelObject();
405 PlainSchemaTO schema = schemas.get(attrTO.getSchema());
406
407
408 if (attrTO.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
409 attrTO.getValues().clear();
410 attrTO.getValues().addAll(getDefaultValues(attrTO.getSchema()));
411 }
412
413 AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
414 if (schemas.get(attrTO.getSchema()).isMultivalue()) {
415 panel = new MultiFieldPanel.Builder<>(
416 new PropertyModel<>(attrTO, "values")).build(
417 "panel",
418 attrTO.getSchema(),
419 FieldPanel.class.cast(panel));
420
421 ((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
422 } else {
423 FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
424 setReadOnly(schema == null ? false : schema.isReadonly());
425 }
426 item.add(panel);
427 }
428 });
429 }
430 }
431 }