blob: e7d82c63c52ac71eae206cd512d1afe409609733 [file] [log] [blame]
/*
* 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.tasks;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.console.SyncopeWebApplication;
import org.apache.syncope.client.console.commons.RealmsUtils;
import org.apache.syncope.client.console.rest.RealmRestClient;
import org.apache.syncope.client.console.rest.TaskRestClient;
import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSearchFieldPanel;
import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
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.AjaxDropDownChoicePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.MacroTaskTO;
import org.apache.syncope.common.lib.to.ProvisioningTaskTO;
import org.apache.syncope.common.lib.to.PullTaskTO;
import org.apache.syncope.common.lib.to.PushTaskTO;
import org.apache.syncope.common.lib.to.RealmTO;
import org.apache.syncope.common.lib.to.SchedTaskTO;
import org.apache.syncope.common.lib.types.MatchingRule;
import org.apache.syncope.common.lib.types.PullMode;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.lib.types.ThreadPoolSettings;
import org.apache.syncope.common.lib.types.UnmatchingRule;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
import org.apache.wicket.extensions.wizard.WizardModel;
import org.apache.wicket.extensions.wizard.WizardStep;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.util.ListModel;
import org.springframework.beans.PropertyAccessorFactory;
public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends BaseAjaxWizardBuilder<T> {
private static final long serialVersionUID = 5945391813567245081L;
protected final TaskType type;
protected final RealmRestClient realmRestClient;
protected final TaskRestClient taskRestClient;
protected PushTaskWrapper wrapper;
protected CrontabPanel crontabPanel;
protected final boolean fullRealmsTree;
public SchedTaskWizardBuilder(
final TaskType type,
final T taskTO,
final RealmRestClient realmRestClient,
final TaskRestClient taskRestClient,
final PageReference pageRef) {
super(taskTO, pageRef);
this.type = type;
this.realmRestClient = realmRestClient;
this.taskRestClient = taskRestClient;
this.fullRealmsTree = SyncopeWebApplication.get().fullRealmsTree(realmRestClient);
}
@Override
protected Serializable onApplyInternal(final SchedTaskTO modelObject) {
if (modelObject instanceof PushTaskTO && wrapper != null) {
wrapper.fillFilterConditions();
}
modelObject.setCronExpression(crontabPanel.getCronExpression());
if (modelObject.getKey() == null) {
taskRestClient.create(type, modelObject);
} else {
taskRestClient.update(type, modelObject);
}
return modelObject;
}
@Override
protected WizardModel buildModelSteps(final SchedTaskTO modelObject, final WizardModel wizardModel) {
wizardModel.add(new Profile(modelObject));
if (modelObject instanceof PushTaskTO) {
wrapper = new PushTaskWrapper(PushTaskTO.class.cast(modelObject));
wizardModel.add(new PushTaskFilters(wrapper, pageRef));
}
wizardModel.add(new Schedule(modelObject));
return wizardModel;
}
protected List<String> searchRealms(final String realmQuery) {
return realmRestClient.search(fullRealmsTree
? RealmsUtils.buildRootQuery()
: RealmsUtils.buildKeywordQuery(realmQuery)).
getResult().stream().map(RealmTO::getFullPath).collect(Collectors.toList());
}
public class Profile extends WizardStep {
private static final long serialVersionUID = -3043839139187792810L;
private final IModel<List<String>> taskJobDelegates = SyncopeWebApplication.get().
getImplementationInfoProvider().getTaskJobDelegates();
private final IModel<List<String>> reconFilterBuilders = SyncopeWebApplication.get().
getImplementationInfoProvider().getReconFilterBuilders();
private final IModel<List<String>> macroActions = SyncopeWebApplication.get().
getImplementationInfoProvider().getMacroActions();
private final IModel<List<String>> pullActions = SyncopeWebApplication.get().
getImplementationInfoProvider().getPullActions();
private final IModel<List<String>> pushActions = SyncopeWebApplication.get().
getImplementationInfoProvider().getPushActions();
public Profile(final SchedTaskTO taskTO) {
AjaxTextFieldPanel name = new AjaxTextFieldPanel(
Constants.NAME_FIELD_NAME, Constants.NAME_FIELD_NAME,
new PropertyModel<>(taskTO, Constants.NAME_FIELD_NAME),
false);
name.addRequiredLabel();
name.setEnabled(true);
add(name);
AjaxTextFieldPanel description = new AjaxTextFieldPanel(
Constants.DESCRIPTION_FIELD_NAME, Constants.DESCRIPTION_FIELD_NAME,
new PropertyModel<>(taskTO, Constants.DESCRIPTION_FIELD_NAME), false);
description.setEnabled(true);
add(description);
AjaxCheckBoxPanel active = new AjaxCheckBoxPanel(
"active", "active", new PropertyModel<>(taskTO, "active"), false);
add(active);
AjaxDropDownChoicePanel<String> jobDelegate = new AjaxDropDownChoicePanel<>(
"jobDelegate", "jobDelegate", new PropertyModel<>(taskTO, "jobDelegate"), false);
jobDelegate.setChoices(taskJobDelegates.getObject());
jobDelegate.addRequiredLabel();
jobDelegate.setEnabled(taskTO.getKey() == null);
add(jobDelegate);
AutoCompleteSettings settings = new AutoCompleteSettings();
settings.setShowCompleteListOnFocusGain(fullRealmsTree);
settings.setShowListOnEmptyInput(fullRealmsTree);
// ------------------------------
// Only for macro tasks
// ------------------------------
WebMarkupContainer macroTaskSpecifics = new WebMarkupContainer("macroTaskSpecifics");
add(macroTaskSpecifics.setRenderBodyOnly(true));
AjaxSearchFieldPanel realm = new AjaxSearchFieldPanel(
"realm", "realm", new PropertyModel<>(taskTO, "realm"), settings) {
private static final long serialVersionUID = -6390474600233486704L;
@Override
protected Iterator<String> getChoices(final String input) {
return (RealmsUtils.checkInput(input)
? searchRealms(input)
: List.<String>of()).iterator();
}
};
if (taskTO instanceof MacroTaskTO) {
realm.addRequiredLabel();
if (StringUtils.isBlank(MacroTaskTO.class.cast(taskTO).getRealm())) {
// add a default destination realm if missing in the task
realm.setModelObject(SyncopeConstants.ROOT_REALM);
}
}
macroTaskSpecifics.add(realm);
macroTaskSpecifics.add(new AjaxDropDownChoicePanel<>(
"macroActions", "macroActions", new PropertyModel<>(taskTO, "macroActions"), false).
setChoices(macroActions));
AjaxCheckBoxPanel continueOnError = new AjaxCheckBoxPanel(
"continueOnError", "continueOnError", new PropertyModel<>(taskTO, "continueOnError"), false);
macroTaskSpecifics.add(continueOnError);
AjaxCheckBoxPanel saveExecs = new AjaxCheckBoxPanel(
"saveExecs", "saveExecs", new PropertyModel<>(taskTO, "saveExecs"), false);
macroTaskSpecifics.add(saveExecs);
// ------------------------------
// Only for pull tasks
// ------------------------------
WebMarkupContainer pullTaskSpecifics = new WebMarkupContainer("pullTaskSpecifics");
add(pullTaskSpecifics.setRenderBodyOnly(true));
boolean isFiltered = false;
if (taskTO instanceof PullTaskTO) {
isFiltered = PullTaskTO.class.cast(taskTO).getPullMode() == PullMode.FILTERED_RECONCILIATION;
} else {
pullTaskSpecifics.setEnabled(false).setVisible(false);
}
AjaxDropDownChoicePanel<PullMode> pullMode = new AjaxDropDownChoicePanel<>(
"pullMode", "pullMode", new PropertyModel<>(taskTO, "pullMode"), false);
pullMode.setChoices(List.of(PullMode.values()));
if (taskTO instanceof PullTaskTO) {
pullMode.addRequiredLabel();
}
pullMode.setNullValid(!(taskTO instanceof PullTaskTO));
pullTaskSpecifics.add(pullMode);
AjaxDropDownChoicePanel<String> reconFilterBuilder = new AjaxDropDownChoicePanel<>(
"reconFilterBuilder", "reconFilterBuilder",
new PropertyModel<>(taskTO, "reconFilterBuilder"), false);
reconFilterBuilder.setChoices(reconFilterBuilders.getObject());
reconFilterBuilder.setEnabled(isFiltered);
reconFilterBuilder.setRequired(isFiltered);
pullTaskSpecifics.add(reconFilterBuilder);
pullMode.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = -1107858522700306810L;
@Override
protected void onUpdate(final AjaxRequestTarget target) {
reconFilterBuilder.setEnabled(pullMode.getModelObject() == PullMode.FILTERED_RECONCILIATION);
reconFilterBuilder.setRequired(pullMode.getModelObject() == PullMode.FILTERED_RECONCILIATION);
target.add(reconFilterBuilder);
}
});
AjaxSearchFieldPanel destinationRealm =
new AjaxSearchFieldPanel("destinationRealm", "destinationRealm",
new PropertyModel<>(taskTO, "destinationRealm"), settings) {
private static final long serialVersionUID = -6390474600233486704L;
@Override
protected Iterator<String> getChoices(final String input) {
return (RealmsUtils.checkInput(input)
? searchRealms(input)
: List.<String>of()).iterator();
}
};
if (taskTO instanceof PullTaskTO) {
destinationRealm.addRequiredLabel();
if (StringUtils.isBlank(PullTaskTO.class.cast(taskTO).getDestinationRealm())) {
// add a default destination realm if missing in the task
destinationRealm.setModelObject(SyncopeConstants.ROOT_REALM);
}
}
pullTaskSpecifics.add(destinationRealm);
AjaxCheckBoxPanel remediation = new AjaxCheckBoxPanel(
"remediation", "remediation", new PropertyModel<>(taskTO, "remediation"), false);
pullTaskSpecifics.add(remediation);
// ------------------------------
// Only for push tasks
// ------------------------------
WebMarkupContainer pushTaskSpecifics = new WebMarkupContainer("pushTaskSpecifics");
add(pushTaskSpecifics.setRenderBodyOnly(true));
if (!(taskTO instanceof PushTaskTO)) {
pushTaskSpecifics.setEnabled(false).setVisible(false);
}
AjaxSearchFieldPanel sourceRealm = new AjaxSearchFieldPanel(
"sourceRealm", "sourceRealm", new PropertyModel<>(taskTO, "sourceRealm"), settings) {
private static final long serialVersionUID = -6390474600233486704L;
@Override
protected Iterator<String> getChoices(final String input) {
return (RealmsUtils.checkInput(input)
? searchRealms(input)
: List.<String>of()).iterator();
}
};
if (taskTO instanceof PushTaskTO) {
sourceRealm.addRequiredLabel();
}
pushTaskSpecifics.add(sourceRealm);
// ------------------------------
// For push and pull tasks
// ------------------------------
WebMarkupContainer provisioningTaskSpecifics = new WebMarkupContainer("provisioningTaskSpecifics");
add(provisioningTaskSpecifics.setOutputMarkupId(true));
if (taskTO instanceof ProvisioningTaskTO) {
jobDelegate.setEnabled(false).setVisible(false);
macroTaskSpecifics.setEnabled(false).setVisible(false);
} else if (taskTO instanceof MacroTaskTO) {
jobDelegate.setEnabled(false).setVisible(false);
provisioningTaskSpecifics.setEnabled(false).setVisible(false);
} else {
provisioningTaskSpecifics.setEnabled(false).setVisible(false);
macroTaskSpecifics.setEnabled(false).setVisible(false);
}
AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>().
setAllowMoveAll(true).setAllowOrder(true).
build("actions",
new PropertyModel<>(taskTO, "actions"),
new ListModel<>(taskTO instanceof PushTaskTO
? pushActions.getObject() : pullActions.getObject()));
provisioningTaskSpecifics.add(actions.setOutputMarkupId(true));
AjaxDropDownChoicePanel<MatchingRule> matchingRule = new AjaxDropDownChoicePanel<>(
"matchingRule", "matchingRule", new PropertyModel<>(taskTO, "matchingRule"), false);
matchingRule.setChoices(List.of(MatchingRule.values()));
provisioningTaskSpecifics.add(matchingRule);
AjaxDropDownChoicePanel<UnmatchingRule> unmatchingRule = new AjaxDropDownChoicePanel<>(
"unmatchingRule", "unmatchingRule", new PropertyModel<>(taskTO, "unmatchingRule"), false);
unmatchingRule.setChoices(List.of(UnmatchingRule.values()));
provisioningTaskSpecifics.add(unmatchingRule);
AjaxCheckBoxPanel performCreate = new AjaxCheckBoxPanel(
"performCreate", "performCreate", new PropertyModel<>(taskTO, "performCreate"), false);
provisioningTaskSpecifics.add(performCreate);
AjaxCheckBoxPanel performUpdate = new AjaxCheckBoxPanel(
"performUpdate", "performUpdate", new PropertyModel<>(taskTO, "performUpdate"), false);
provisioningTaskSpecifics.add(performUpdate);
AjaxCheckBoxPanel performDelete = new AjaxCheckBoxPanel(
"performDelete", "performDelete", new PropertyModel<>(taskTO, "performDelete"), false);
provisioningTaskSpecifics.add(performDelete);
AjaxCheckBoxPanel syncStatus = new AjaxCheckBoxPanel(
"syncStatus", "syncStatus", new PropertyModel<>(taskTO, "syncStatus"), false);
provisioningTaskSpecifics.add(syncStatus);
// Concurrent settings
PropertyModel<ThreadPoolSettings> concurrentSettingsModel =
new PropertyModel<>(taskTO, "concurrentSettings");
AjaxCheckBoxPanel enableConcurrentSettings = new AjaxCheckBoxPanel(
"enableConcurrentSettings", "enableConcurrentSettings", new IModel<Boolean>() {
private static final long serialVersionUID = -7126718045816207110L;
@Override
public Boolean getObject() {
return concurrentSettingsModel.getObject() != null;
}
@Override
public void setObject(final Boolean object) {
// nothing to do
}
});
provisioningTaskSpecifics.add(enableConcurrentSettings.
setVisible(taskTO instanceof ProvisioningTaskTO).setOutputMarkupId(true));
FieldPanel<Integer> poolSize = new AjaxSpinnerFieldPanel.Builder<Integer>().min(1).build(
"poolSize",
"poolSize",
Integer.class,
new ConcurrentSettingsValueModel(concurrentSettingsModel, "poolSize")).setRequired(true);
poolSize.setOutputMarkupPlaceholderTag(true).setOutputMarkupId(true);
poolSize.setVisible(taskTO instanceof ProvisioningTaskTO
? concurrentSettingsModel.getObject() != null
: false);
provisioningTaskSpecifics.add(poolSize);
enableConcurrentSettings.getField().add(
new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = -1107858522700306810L;
@Override
protected void onUpdate(final AjaxRequestTarget target) {
if (concurrentSettingsModel.getObject() == null) {
concurrentSettingsModel.setObject(new ThreadPoolSettings());
} else {
concurrentSettingsModel.setObject(null);
}
poolSize.setVisible(concurrentSettingsModel.getObject() != null);
target.add(provisioningTaskSpecifics);
}
});
}
}
protected static class ConcurrentSettingsValueModel implements IModel<Integer> {
private static final long serialVersionUID = 8869612332790116116L;
private final PropertyModel<ThreadPoolSettings> concurrentSettingsModel;
private final String property;
public ConcurrentSettingsValueModel(
final PropertyModel<ThreadPoolSettings> concurrentSettingsModel,
final String property) {
this.concurrentSettingsModel = concurrentSettingsModel;
this.property = property;
}
@Override
public Integer getObject() {
return Optional.ofNullable(concurrentSettingsModel.getObject()).
map(s -> (Integer) PropertyAccessorFactory.forBeanPropertyAccess(s).getPropertyValue(property)).
orElse(null);
}
@Override
public void setObject(final Integer object) {
Optional.ofNullable(concurrentSettingsModel.getObject()).
ifPresent(s -> PropertyAccessorFactory.forBeanPropertyAccess(s).setPropertyValue(property, object));
}
}
public class Schedule extends WizardStep {
private static final long serialVersionUID = -785981096328637758L;
public Schedule(final SchedTaskTO taskTO) {
crontabPanel = new CrontabPanel(
"schedule", new PropertyModel<>(taskTO, "cronExpression"), taskTO.getCronExpression());
add(crontabPanel);
}
}
}