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