1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.console.wizards.mapping;
20
21 import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverBehavior;
22 import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig;
23 import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
24 import java.io.Serializable;
25 import java.util.Comparator;
26 import java.util.List;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
29 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
30 import org.apache.syncope.client.console.widgets.ItemTransformerWidget;
31 import org.apache.syncope.client.console.widgets.JEXLTransformerWidget;
32 import org.apache.syncope.client.ui.commons.ConnIdSpecialName;
33 import org.apache.syncope.client.ui.commons.Constants;
34 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
35 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
36 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
37 import org.apache.syncope.common.lib.to.Item;
38 import org.apache.syncope.common.lib.types.MappingPurpose;
39 import org.apache.wicket.ajax.AjaxRequestTarget;
40 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
41 import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
42 import org.apache.wicket.markup.html.WebMarkupContainer;
43 import org.apache.wicket.markup.html.basic.Label;
44 import org.apache.wicket.markup.html.list.ListItem;
45 import org.apache.wicket.markup.html.list.ListView;
46 import org.apache.wicket.markup.html.panel.Panel;
47 import org.apache.wicket.model.IModel;
48 import org.apache.wicket.model.Model;
49 import org.apache.wicket.model.PropertyModel;
50 import org.apache.wicket.model.ResourceModel;
51
52 public abstract class AbstractMappingPanel extends Panel {
53
54 private static final long serialVersionUID = -8295587900937040104L;
55
56 protected static final Comparator<Item> ITEM_COMPARATOR = (left, right) -> {
57 int compared;
58 if (left == null && right == null) {
59 compared = 0;
60 } else if (left == null) {
61 compared = 1;
62 } else if (right == null) {
63 compared = -1;
64 } else if (left.isConnObjectKey()) {
65 compared = -1;
66 } else if (right.isConnObjectKey()) {
67 compared = 1;
68 } else if (left.isPassword()) {
69 compared = -1;
70 } else if (right.isPassword()) {
71 compared = 1;
72 } else if (left.getPurpose() == MappingPurpose.BOTH && right.getPurpose() != MappingPurpose.BOTH) {
73 compared = -1;
74 } else if (left.getPurpose() != MappingPurpose.BOTH && right.getPurpose() == MappingPurpose.BOTH) {
75 compared = 1;
76 } else if (left.getPurpose() == MappingPurpose.PROPAGATION
77 && (right.getPurpose() == MappingPurpose.PULL
78 || right.getPurpose() == MappingPurpose.NONE)) {
79 compared = -1;
80 } else if (left.getPurpose() == MappingPurpose.PULL
81 && right.getPurpose() == MappingPurpose.PROPAGATION) {
82 compared = 1;
83 } else if (left.getPurpose() == MappingPurpose.PULL
84 && right.getPurpose() == MappingPurpose.NONE) {
85 compared = -1;
86 } else if (left.getPurpose() == MappingPurpose.NONE
87 && right.getPurpose() != MappingPurpose.NONE) {
88 compared = 1;
89 } else {
90 compared = left.getIntAttrName().compareTo(right.getIntAttrName());
91 }
92 return compared;
93 };
94
95 protected final Label connObjectKeyLabel;
96
97 protected final Label passwordLabel;
98
99 protected final Label purposeLabel;
100
101 protected final Label intAttrNameInfo;
102
103 protected final WebMarkupContainer mandatoryHeader;
104
105
106
107
108 protected final AjaxButton addMappingBtn;
109
110
111
112
113 protected final ListView<Item> mappings;
114
115
116
117
118 protected final WebMarkupContainer mappingContainer;
119
120 public AbstractMappingPanel(
121 final String id,
122 final ItemTransformersTogglePanel itemTransformers,
123 final JEXLTransformersTogglePanel jexlTransformers,
124 final IModel<List<Item>> model,
125 final boolean addMappingBtnVisible,
126 final MappingPurpose defaultPurpose) {
127
128 super(id);
129 setOutputMarkupId(true);
130
131 mappingContainer = new WebMarkupContainer("mappingContainer");
132 mappingContainer.setOutputMarkupId(true);
133 add(mappingContainer);
134
135 mappingContainer.add(new Label("itemTransformersLabel", Model.of()).setVisible(itemTransformers != null));
136
137 mappingContainer.add(new Label("jexlTransformersLabel", Model.of()).setVisible(jexlTransformers != null));
138
139 connObjectKeyLabel = new Label("connObjectKeyLabel", new ResourceModel("connObjectKey"));
140 mappingContainer.add(connObjectKeyLabel);
141
142 passwordLabel = new Label("passwordLabel", new ResourceModel("password"));
143 mappingContainer.add(passwordLabel);
144
145 purposeLabel = new Label("purposeLabel", new ResourceModel("purpose"));
146 mappingContainer.add(purposeLabel);
147
148 intAttrNameInfo = new Label("intAttrNameInfo", Model.of());
149 intAttrNameInfo.add(new PopoverBehavior(
150 Model.of(),
151 Model.of(getString("intAttrNameInfo.help")
152 + "<code>groups[groupName].attribute</code>, "
153 + "<code>users[userName].attribute</code>, "
154 + "<code>anyObjects[anyObjectName].attribute</code>, "
155 + "<code>relationships[relationshipType][anyType].attribute</code> or "
156 + "<code>memberships[groupName].attribute</code> or "
157 + "<code>privileges[applicationKey]</code>"),
158 new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.right)) {
159
160 private static final long serialVersionUID = -7867802555691605021L;
161
162 @Override
163 protected String createRelAttribute() {
164 return "intAttrNameInfo";
165 }
166 });
167 mappingContainer.add(intAttrNameInfo);
168
169 mandatoryHeader = new WebMarkupContainer("mandatoryHeader");
170 mandatoryHeader.setOutputMarkupId(true);
171 mandatoryHeader.add(Constants.getJEXLPopover(this, TooltipConfig.Placement.bottom));
172 mappingContainer.add(mandatoryHeader);
173
174 model.getObject().sort(ITEM_COMPARATOR);
175
176 mappings = new ListView<>("mappings", model) {
177
178 private static final long serialVersionUID = 4949588177564901031L;
179
180 @Override
181 protected void populateItem(final ListItem<Item> item) {
182 final Item itemTO = item.getModelObject();
183 if (itemTO.getPurpose() == null) {
184 itemTO.setPurpose(defaultPurpose);
185 }
186
187
188
189
190 AjaxTextFieldPanel intAttrName = new AjaxTextFieldPanel(
191 "intAttrName",
192 "intAttrName",
193 new PropertyModel<>(itemTO, "intAttrName"),
194 false);
195 intAttrName.setChoices(List.of());
196 intAttrName.setRequired(true).hideLabel();
197 item.add(intAttrName);
198
199
200
201
202
203 AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel(
204 "extAttrName",
205 "extAttrName",
206 new PropertyModel<>(itemTO, "extAttrName"));
207 extAttrName.setChoices(getExtAttrNames().getObject());
208
209 boolean required = !itemTO.isPassword();
210 extAttrName.setRequired(required).hideLabel();
211 extAttrName.setEnabled(required);
212 item.add(extAttrName);
213
214
215
216
217
218 if (jexlTransformers == null) {
219 item.add(new Label("jexlTransformers").setVisible(false));
220 } else {
221 item.add(new JEXLTransformerWidget(
222 "jexlTransformers", itemTO, jexlTransformers).setRenderBodyOnly(true));
223 }
224
225
226
227
228
229 if (itemTransformers == null) {
230 item.add(new Label("itemTransformers").setVisible(false));
231
232 } else {
233 item.add(new ItemTransformerWidget(
234 "itemTransformers", itemTO, itemTransformers).setRenderBodyOnly(true));
235 }
236
237
238
239
240
241 AjaxTextFieldPanel mandatory = new AjaxTextFieldPanel(
242 "mandatoryCondition",
243 "mandatoryCondition",
244 new PropertyModel<>(itemTO, "mandatoryCondition"));
245 mandatory.hideLabel();
246 mandatory.setChoices(List.of("true", "false"));
247 mandatory.setEnabled(!itemTO.isConnObjectKey());
248 item.add(mandatory);
249
250
251
252
253
254 AjaxCheckBoxPanel connObjectKey = new AjaxCheckBoxPanel(
255 "connObjectKey",
256 "connObjectKey",
257 new PropertyModel<>(itemTO, "connObjectKey"), false);
258 connObjectKey.hideLabel();
259 item.add(connObjectKey);
260
261
262
263
264
265 AjaxCheckBoxPanel password = new AjaxCheckBoxPanel(
266 "password",
267 "password",
268 new PropertyModel<>(itemTO, "password"), false);
269 item.add(password.hideLabel());
270
271
272
273
274
275 WebMarkupContainer purpose = new WebMarkupContainer("purpose");
276 purpose.setOutputMarkupId(true);
277
278 MappingPurposePanel purposeActions = new MappingPurposePanel(
279 "purposeActions", new PropertyModel<>(itemTO, "purpose"), purpose);
280 purpose.add(purposeActions.setRenderBodyOnly(true));
281 item.add(purpose);
282
283
284
285
286
287 ActionsPanel<Serializable> actions = new ActionsPanel<>("toRemove", null);
288 actions.add(new ActionLink<>() {
289
290 private static final long serialVersionUID = -3722207913631435501L;
291
292 @Override
293 public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
294 model.getObject().remove(item.getIndex());
295 item.getParent().removeAll();
296 target.add(AbstractMappingPanel.this);
297 }
298 }, ActionLink.ActionType.DELETE, StringUtils.EMPTY, true).hideLabel();
299 item.add(actions);
300
301
302 intAttrName.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
303
304 private static final long serialVersionUID = -1107858522700306810L;
305
306 @Override
307 protected void onUpdate(final AjaxRequestTarget target) {
308 }
309 });
310
311 connObjectKey.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
312
313 private static final long serialVersionUID = -1107858522700306810L;
314
315 @Override
316 protected void onUpdate(final AjaxRequestTarget target) {
317 if (connObjectKey.getModelObject()) {
318 itemTO.setMandatoryCondition("true");
319 mandatory.setModelObject("true");
320 mandatory.setEnabled(false);
321 } else {
322 itemTO.setMandatoryCondition("false");
323 mandatory.setModelObject("false");
324 mandatory.setEnabled(true);
325 }
326 target.add(mandatory);
327 }
328 });
329
330 password.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
331
332 private static final long serialVersionUID = -1107858522700306810L;
333
334 @Override
335 protected void onUpdate(final AjaxRequestTarget target) {
336 extAttrName.setEnabled(!password.getModelObject());
337 extAttrName.setModelObject(password.getModelObject()
338 ? ConnIdSpecialName.PASSWORD : extAttrName.getModelObject());
339 extAttrName.setRequired(!password.getModelObject());
340 target.add(extAttrName);
341
342 setConnObjectKey(connObjectKey, password);
343 target.add(connObjectKey);
344 }
345 });
346
347 setConnObjectKey(connObjectKey, password);
348 setAttrNames(intAttrName);
349
350 if (hidePassword()) {
351 password.setVisible(false);
352
353
354 extAttrName.setEnabled(true);
355 if (itemTO.isPassword()) {
356
357 intAttrName.setEnabled(true);
358 }
359 itemTO.setPassword(false);
360 }
361
362 purpose.setVisible(!hidePurpose());
363
364 mandatory.setVisible(!hideMandatory());
365
366 connObjectKey.setVisible(!hideConnObjectKey());
367 }
368 };
369
370 mappings.setReuseItems(true);
371 mappingContainer.add(mappings);
372
373 addMappingBtn = new IndicatingAjaxButton("addMappingBtn") {
374
375 private static final long serialVersionUID = -4804368561204623354L;
376
377 @Override
378 protected void onSubmit(final AjaxRequestTarget target) {
379 model.getObject().add(new Item());
380 target.add(AbstractMappingPanel.this);
381 }
382 };
383 addMappingBtn.setDefaultFormProcessing(false);
384 addMappingBtn.setEnabled(addMappingBtnVisible);
385 mappingContainer.add(addMappingBtn);
386 }
387
388 @Override
389 protected void onBeforeRender() {
390 super.onBeforeRender();
391
392 passwordLabel.setVisible(!hidePassword());
393 purposeLabel.setVisible(!hidePurpose());
394 mandatoryHeader.setVisible(!hideMandatory());
395 connObjectKeyLabel.setVisible(!hideConnObjectKey());
396 }
397
398 protected boolean hidePassword() {
399 return true;
400 }
401
402 protected boolean hidePurpose() {
403 return false;
404 }
405
406 protected boolean hideMandatory() {
407 return false;
408 }
409
410 protected boolean hideConnObjectKey() {
411 return false;
412 }
413
414 protected abstract IModel<List<String>> getExtAttrNames();
415
416
417
418
419
420
421 protected abstract void setAttrNames(AjaxTextFieldPanel toBeUpdated);
422
423
424
425
426
427
428
429 protected void setConnObjectKey(final AjaxCheckBoxPanel connObjectKey, final AjaxCheckBoxPanel password) {
430 if (password.getModelObject()) {
431 connObjectKey.setReadOnly(true);
432 connObjectKey.setModelObject(false);
433 } else {
434 connObjectKey.setReadOnly(false);
435 }
436 }
437 }