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 attrTO = item.getModelObject();
358 PlainSchemaTO schema = schemas.get(attrTO.getSchema());
359
360
361 if (attrTO.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
362 attrTO.getValues().clear();
363 attrTO.getValues().addAll(getDefaultValues(attrTO.getSchema(), groupName));
364 }
365
366 AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
367 if (schemas.get(attrTO.getSchema()).isMultivalue()) {
368 panel = new MultiFieldPanel.Builder<>(new PropertyModel<>(attrTO, "values")).
369 build("panel", attrTO.getSchema(), FieldPanel.class.cast(panel));
370
371 ((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
372 } else {
373 FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
374 setReadOnly(schema == null ? false : schema.isReadonly());
375 }
376
377 item.add(panel);
378 }
379 });
380 }
381 }
382
383 protected class PlainSchemasOwn extends Schemas {
384
385 private static final long serialVersionUID = -4730563859116024676L;
386
387 public PlainSchemasOwn(
388 final String id,
389 final Map<String, PlainSchemaTO> schemas,
390 final IModel<List<Attr>> attrTOs) {
391
392 super(id);
393
394 add(new ListView<>("schemas", attrTOs) {
395
396 private static final long serialVersionUID = 9101744072914090143L;
397
398 @Override
399 @SuppressWarnings({ "unchecked", "rawtypes" })
400 protected void populateItem(final ListItem<Attr> item) {
401 Attr attrTO = item.getModelObject();
402 PlainSchemaTO schema = schemas.get(attrTO.getSchema());
403
404
405 if (attrTO.getValues().stream().noneMatch(StringUtils::isNotBlank)) {
406 attrTO.getValues().clear();
407 attrTO.getValues().addAll(getDefaultValues(attrTO.getSchema()));
408 }
409
410 AbstractFieldPanel<?> panel = getFieldPanel(schemas.get(attrTO.getSchema()));
411 if (schemas.get(attrTO.getSchema()).isMultivalue()) {
412 panel = new MultiFieldPanel.Builder<>(
413 new PropertyModel<>(attrTO, "values")).build(
414 "panel",
415 attrTO.getSchema(),
416 FieldPanel.class.cast(panel));
417
418 ((MultiFieldPanel) panel).setReadOnly(schema == null ? false : schema.isReadonly());
419 } else {
420 FieldPanel.class.cast(panel).setNewModel(attrTO.getValues()).
421 setReadOnly(schema == null ? false : schema.isReadonly());
422 }
423 item.add(panel);
424 }
425 });
426 }
427 }
428 }