| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.syncope.client.console.wizards.mapping; |
| |
| import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverBehavior; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig; |
| import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig; |
| import java.io.Serializable; |
| import java.util.List; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.syncope.client.console.rest.AnyTypeClassRestClient; |
| import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; |
| import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel; |
| import org.apache.syncope.client.console.widgets.JEXLTransformerWidget; |
| import org.apache.syncope.client.console.widgets.ItemTransformerWidget; |
| import org.apache.syncope.client.ui.commons.ConnIdSpecialName; |
| import org.apache.syncope.client.ui.commons.Constants; |
| import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior; |
| import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel; |
| import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; |
| import org.apache.syncope.common.lib.to.ItemTO; |
| import org.apache.syncope.common.lib.types.MappingPurpose; |
| import org.apache.wicket.ajax.AjaxRequestTarget; |
| import org.apache.wicket.ajax.markup.html.form.AjaxButton; |
| import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; |
| import org.apache.wicket.markup.html.WebMarkupContainer; |
| import org.apache.wicket.markup.html.basic.Label; |
| import org.apache.wicket.markup.html.list.ListItem; |
| import org.apache.wicket.markup.html.list.ListView; |
| import org.apache.wicket.markup.html.panel.Panel; |
| import org.apache.wicket.model.IModel; |
| import org.apache.wicket.model.Model; |
| import org.apache.wicket.model.PropertyModel; |
| import org.apache.wicket.model.ResourceModel; |
| |
| public abstract class AbstractMappingPanel extends Panel { |
| |
| private static final long serialVersionUID = -8295587900937040104L; |
| |
| /** |
| * Any type class rest client. |
| */ |
| protected final AnyTypeClassRestClient anyTypeClassRestClient = new AnyTypeClassRestClient(); |
| |
| protected final Label connObjectKeyLabel; |
| |
| protected final Label passwordLabel; |
| |
| protected final Label purposeLabel; |
| |
| protected final Label intAttrNameInfo; |
| |
| protected final WebMarkupContainer mandatoryHeader; |
| |
| /** |
| * Add mapping button. |
| */ |
| protected final AjaxButton addMappingBtn; |
| |
| /** |
| * All mappings. |
| */ |
| protected final ListView<ItemTO> mappings; |
| |
| /** |
| * Mapping container. |
| */ |
| protected final WebMarkupContainer mappingContainer; |
| |
| public AbstractMappingPanel( |
| final String id, |
| final ItemTransformersTogglePanel itemTransformers, |
| final JEXLTransformersTogglePanel jexlTransformers, |
| final IModel<List<ItemTO>> model, |
| final boolean addMappingBtnVisible, |
| final MappingPurpose defaultPurpose) { |
| |
| super(id); |
| setOutputMarkupId(true); |
| |
| mappingContainer = new WebMarkupContainer("mappingContainer"); |
| mappingContainer.setOutputMarkupId(true); |
| add(mappingContainer); |
| |
| mappingContainer.add(new Label("itemTransformersLabel", Model.of()).setVisible(itemTransformers != null)); |
| |
| mappingContainer.add(new Label("jexlTransformersLabel", Model.of()).setVisible(jexlTransformers != null)); |
| |
| connObjectKeyLabel = new Label("connObjectKeyLabel", new ResourceModel("connObjectKey")); |
| mappingContainer.add(connObjectKeyLabel); |
| |
| passwordLabel = new Label("passwordLabel", new ResourceModel("password")); |
| mappingContainer.add(passwordLabel); |
| |
| purposeLabel = new Label("purposeLabel", new ResourceModel("purpose")); |
| mappingContainer.add(purposeLabel); |
| |
| intAttrNameInfo = new Label("intAttrNameInfo", Model.of()); |
| intAttrNameInfo.add(new PopoverBehavior( |
| Model.of(), |
| Model.of(getString("intAttrNameInfo.help") |
| + "<code>groups[groupName].attribute</code>, " |
| + "<code>users[userName].attribute</code>, " |
| + "<code>anyObjects[anyObjectName].attribute</code>, " |
| + "<code>relationships[relationshipType][anyType].attribute</code> or " |
| + "<code>memberships[groupName].attribute</code> or " |
| + "<code>privileges[applicationKey]</code>"), |
| new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.right)) { |
| |
| private static final long serialVersionUID = -7867802555691605021L; |
| |
| @Override |
| protected String createRelAttribute() { |
| return "intAttrNameInfo"; |
| } |
| }); |
| mappingContainer.add(intAttrNameInfo); |
| |
| mandatoryHeader = new WebMarkupContainer("mandatoryHeader"); |
| mandatoryHeader.setOutputMarkupId(true); |
| mandatoryHeader.add(Constants.getJEXLPopover(this, TooltipConfig.Placement.bottom)); |
| mappingContainer.add(mandatoryHeader); |
| |
| model.getObject().sort((left, right) -> { |
| int compared; |
| if (left == null && right == null) { |
| compared = 0; |
| } else if (left == null) { |
| compared = 1; |
| } else if (right == null) { |
| compared = -1; |
| } else if (left.isConnObjectKey()) { |
| compared = -1; |
| } else if (right.isConnObjectKey()) { |
| compared = 1; |
| } else if (left.isPassword()) { |
| compared = -1; |
| } else if (right.isPassword()) { |
| compared = 1; |
| } else if (left.getPurpose() == MappingPurpose.BOTH && right.getPurpose() != MappingPurpose.BOTH) { |
| compared = -1; |
| } else if (left.getPurpose() != MappingPurpose.BOTH && right.getPurpose() == MappingPurpose.BOTH) { |
| compared = 1; |
| } else if (left.getPurpose() == MappingPurpose.PROPAGATION |
| && (right.getPurpose() == MappingPurpose.PULL |
| || right.getPurpose() == MappingPurpose.NONE)) { |
| compared = -1; |
| } else if (left.getPurpose() == MappingPurpose.PULL |
| && right.getPurpose() == MappingPurpose.PROPAGATION) { |
| compared = 1; |
| } else if (left.getPurpose() == MappingPurpose.PULL |
| && right.getPurpose() == MappingPurpose.NONE) { |
| compared = -1; |
| } else if (left.getPurpose() == MappingPurpose.NONE |
| && right.getPurpose() != MappingPurpose.NONE) { |
| compared = 1; |
| } else { |
| compared = left.getIntAttrName().compareTo(right.getIntAttrName()); |
| } |
| return compared; |
| }); |
| |
| mappings = new ListView<>("mappings", model) { |
| |
| private static final long serialVersionUID = 4949588177564901031L; |
| |
| @Override |
| protected void populateItem(final ListItem<ItemTO> item) { |
| final ItemTO itemTO = item.getModelObject(); |
| if (itemTO.getPurpose() == null) { |
| itemTO.setPurpose(defaultPurpose); |
| } |
| |
| //-------------------------------- |
| // Internal attribute |
| // ------------------------------- |
| AjaxTextFieldPanel intAttrName = new AjaxTextFieldPanel( |
| "intAttrName", |
| "intAttrName", |
| new PropertyModel<>(itemTO, "intAttrName"), |
| false); |
| intAttrName.setChoices(List.of()); |
| intAttrName.setRequired(true).hideLabel(); |
| item.add(intAttrName); |
| // ------------------------------- |
| |
| //-------------------------------- |
| // External attribute |
| // ------------------------------- |
| AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel( |
| "extAttrName", |
| "extAttrName", |
| new PropertyModel<>(itemTO, "extAttrName")); |
| extAttrName.setChoices(getExtAttrNames().getObject()); |
| |
| boolean required = !itemTO.isPassword(); |
| extAttrName.setRequired(required).hideLabel(); |
| extAttrName.setEnabled(required); |
| item.add(extAttrName); |
| // ------------------------------- |
| |
| //-------------------------------- |
| // JEXL transformers |
| // ------------------------------- |
| if (jexlTransformers == null) { |
| item.add(new Label("jexlTransformers").setVisible(false)); |
| } else { |
| item.add(new JEXLTransformerWidget( |
| "jexlTransformers", itemTO, jexlTransformers).setRenderBodyOnly(true)); |
| } |
| // ------------------------------- |
| |
| //-------------------------------- |
| // Mapping item transformers |
| // ------------------------------- |
| if (itemTransformers == null) { |
| item.add(new Label("itemTransformers").setVisible(false)); |
| |
| } else { |
| item.add(new ItemTransformerWidget( |
| "itemTransformers", itemTO, itemTransformers).setRenderBodyOnly(true)); |
| } |
| // ------------------------------- |
| |
| //-------------------------------- |
| // Mandatory |
| // ------------------------------- |
| AjaxTextFieldPanel mandatory = new AjaxTextFieldPanel( |
| "mandatoryCondition", |
| "mandatoryCondition", |
| new PropertyModel<>(itemTO, "mandatoryCondition")); |
| mandatory.hideLabel(); |
| mandatory.setChoices(List.of("true", "false")); |
| mandatory.setEnabled(!itemTO.isConnObjectKey()); |
| item.add(mandatory); |
| // ------------------------------- |
| |
| //-------------------------------- |
| // Connector object key |
| // ------------------------------- |
| AjaxCheckBoxPanel connObjectKey = new AjaxCheckBoxPanel( |
| "connObjectKey", |
| "connObjectKey", |
| new PropertyModel<>(itemTO, "connObjectKey"), false); |
| connObjectKey.hideLabel(); |
| item.add(connObjectKey); |
| // ------------------------------- |
| |
| //-------------------------------- |
| // Password |
| // ------------------------------- |
| AjaxCheckBoxPanel password = new AjaxCheckBoxPanel( |
| "password", |
| "password", |
| new PropertyModel<>(itemTO, "password"), false); |
| item.add(password.hideLabel()); |
| // ------------------------------- |
| |
| //-------------------------------- |
| // Purpose |
| // ------------------------------- |
| WebMarkupContainer purpose = new WebMarkupContainer("purpose"); |
| purpose.setOutputMarkupId(true); |
| |
| MappingPurposePanel purposeActions = new MappingPurposePanel( |
| "purposeActions", new PropertyModel<>(itemTO, "purpose"), purpose); |
| purpose.add(purposeActions.setRenderBodyOnly(true)); |
| item.add(purpose); |
| // ------------------------------- |
| |
| //-------------------------------- |
| // Remove |
| // ------------------------------- |
| ActionsPanel<Serializable> actions = new ActionsPanel<>("toRemove", null); |
| actions.add(new ActionLink<>() { |
| |
| private static final long serialVersionUID = -3722207913631435501L; |
| |
| @Override |
| public void onClick(final AjaxRequestTarget target, final Serializable ignore) { |
| model.getObject().remove(item.getIndex()); |
| |
| item.getParent().removeAll(); |
| target.add(AbstractMappingPanel.this); |
| } |
| }, ActionLink.ActionType.DELETE, StringUtils.EMPTY, true).hideLabel(); |
| item.add(actions); |
| // ------------------------------- |
| |
| intAttrName.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { |
| |
| private static final long serialVersionUID = -1107858522700306810L; |
| |
| @Override |
| protected void onUpdate(final AjaxRequestTarget target) { |
| } |
| }); |
| |
| connObjectKey.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { |
| |
| private static final long serialVersionUID = -1107858522700306810L; |
| |
| @Override |
| protected void onUpdate(final AjaxRequestTarget target) { |
| if (connObjectKey.getModelObject()) { |
| itemTO.setMandatoryCondition("true"); |
| mandatory.setModelObject("true"); |
| mandatory.setEnabled(false); |
| } else { |
| itemTO.setMandatoryCondition("false"); |
| mandatory.setModelObject("false"); |
| mandatory.setEnabled(true); |
| } |
| target.add(mandatory); |
| } |
| }); |
| |
| password.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { |
| |
| private static final long serialVersionUID = -1107858522700306810L; |
| |
| @Override |
| protected void onUpdate(final AjaxRequestTarget target) { |
| extAttrName.setEnabled(!password.getModelObject()); |
| extAttrName.setModelObject(password.getModelObject() |
| ? ConnIdSpecialName.PASSWORD : extAttrName.getModelObject()); |
| extAttrName.setRequired(!password.getModelObject()); |
| target.add(extAttrName); |
| |
| setConnObjectKey(connObjectKey, password); |
| target.add(connObjectKey); |
| } |
| }); |
| |
| setConnObjectKey(connObjectKey, password); |
| setAttrNames(intAttrName); |
| |
| if (hidePassword()) { |
| password.setVisible(false); |
| |
| // Changes required by clone .... |
| extAttrName.setEnabled(true); |
| if (itemTO.isPassword()) { |
| // re-enable if and only if cloned object mapping item was a password |
| intAttrName.setEnabled(true); |
| } |
| itemTO.setPassword(false); |
| } |
| |
| purpose.setVisible(!hidePurpose()); |
| |
| mandatory.setVisible(!hideMandatory()); |
| |
| connObjectKey.setVisible(!hideConnObjectKey()); |
| } |
| }; |
| |
| mappings.setReuseItems(true); |
| mappingContainer.add(mappings); |
| |
| addMappingBtn = new IndicatingAjaxButton("addMappingBtn") { |
| |
| private static final long serialVersionUID = -4804368561204623354L; |
| |
| @Override |
| protected void onSubmit(final AjaxRequestTarget target) { |
| model.getObject().add(new ItemTO()); |
| target.add(AbstractMappingPanel.this); |
| } |
| }; |
| addMappingBtn.setDefaultFormProcessing(false); |
| addMappingBtn.setEnabled(addMappingBtnVisible); |
| mappingContainer.add(addMappingBtn); |
| } |
| |
| @Override |
| protected void onBeforeRender() { |
| super.onBeforeRender(); |
| |
| passwordLabel.setVisible(!hidePassword()); |
| purposeLabel.setVisible(!hidePurpose()); |
| mandatoryHeader.setVisible(!hideMandatory()); |
| connObjectKeyLabel.setVisible(!hideConnObjectKey()); |
| } |
| |
| protected boolean hidePassword() { |
| return true; |
| } |
| |
| protected boolean hidePurpose() { |
| return false; |
| } |
| |
| protected boolean hideMandatory() { |
| return false; |
| } |
| |
| protected boolean hideConnObjectKey() { |
| return false; |
| } |
| |
| protected abstract IModel<List<String>> getExtAttrNames(); |
| |
| /** |
| * Set attribute names for a drop down choice list. |
| * |
| * @param toBeUpdated drop down choice to be updated. |
| */ |
| protected abstract void setAttrNames(AjaxTextFieldPanel toBeUpdated); |
| |
| /** |
| * Enable/Disable connObjectKey checkbox. |
| * |
| * @param connObjectKey connObjectKey checkbox. |
| * @param password password checkbox. |
| */ |
| private static void setConnObjectKey(final AjaxCheckBoxPanel connObjectKey, final AjaxCheckBoxPanel password) { |
| if (password.getModelObject()) { |
| connObjectKey.setReadOnly(true); |
| connObjectKey.setModelObject(false); |
| } else { |
| connObjectKey.setReadOnly(false); |
| } |
| } |
| } |