blob: 1edd67122dc208b222fec538627bf8a6597b267f [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.wizards.any;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.console.SyncopeWebApplication;
import java.util.Optional;
import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
import org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
import org.apache.syncope.client.ui.commons.layout.AbstractAnyFormLayout;
import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
import org.apache.syncope.client.ui.commons.wizards.any.AbstractAnyWizardBuilder;
import org.apache.syncope.client.ui.commons.wizards.any.AnyForm;
import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.GroupableRelatableTO;
import org.apache.wicket.PageReference;
import org.apache.wicket.extensions.wizard.WizardModel;
public abstract class AnyWizardBuilder<A extends AnyTO> extends AbstractAnyWizardBuilder<A> {
private static final long serialVersionUID = -2480279868319546243L;
protected final List<String> anyTypeClasses;
protected AbstractAnyFormLayout<A, ? extends AnyForm<A>> formLayoutInfo;
/**
* Construct.
*
* @param anyTO any
* @param anyTypeClasses any type classes
* @param formLayoutInfo form layout info
* @param pageRef caller page reference.
*/
public AnyWizardBuilder(
final A anyTO,
final List<String> anyTypeClasses,
final AbstractAnyFormLayout<A, ? extends AnyForm<A>> formLayoutInfo,
final PageReference pageRef) {
super(new AnyWrapper<>(anyTO), pageRef);
this.anyTypeClasses = anyTypeClasses;
this.formLayoutInfo = formLayoutInfo;
}
/**
* Construct.
*
* @param wrapper any wrapper
* @param anyTypeClasses any type classes
* @param formLayoutInfo form layout info
* @param pageRef caller page reference.
*/
public AnyWizardBuilder(
final AnyWrapper<A> wrapper,
final List<String> anyTypeClasses,
final AbstractAnyFormLayout<A, ? extends AnyForm<A>> formLayoutInfo,
final PageReference pageRef) {
super(wrapper, pageRef);
this.anyTypeClasses = anyTypeClasses;
this.formLayoutInfo = formLayoutInfo;
}
@Override
protected WizardModel buildModelSteps(final AnyWrapper<A> modelObject, final WizardModel wizardModel) {
// optional details panel step
addOptionalDetailsPanel(modelObject).ifPresent(wizardModel::add);
if ((this instanceof GroupWizardBuilder)
&& (modelObject.getInnerObject() instanceof GroupTO)
&& (formLayoutInfo instanceof GroupFormLayoutInfo)) {
GroupFormLayoutInfo groupFormLayoutInfo = GroupFormLayoutInfo.class.cast(formLayoutInfo);
if (groupFormLayoutInfo.isOwnership()) {
wizardModel.add(new Ownership(GroupWrapper.class.cast(modelObject), pageRef));
}
if (groupFormLayoutInfo.isDynamicMemberships()) {
wizardModel.add(new DynamicMemberships(GroupWrapper.class.cast(modelObject)));
}
}
if (formLayoutInfo.isAuxClasses()) {
wizardModel.add(new ConsoleAuxClasses(modelObject, anyTypeClasses));
}
if (formLayoutInfo.isGroups()) {
wizardModel.add(new Groups(modelObject, mode == AjaxWizard.Mode.TEMPLATE));
}
// attributes panel steps
if (formLayoutInfo.isPlainAttrs()) {
wizardModel.add(
new PlainAttrs(modelObject, mode, anyTypeClasses, formLayoutInfo.getWhichPlainAttrs()) {
private static final long serialVersionUID = 8167894751609598306L;
@Override
public PageReference getPageReference() {
return pageRef;
}
});
}
if (formLayoutInfo.isDerAttrs() && mode != AjaxWizard.Mode.TEMPLATE) {
wizardModel.add(new DerAttrs(modelObject, anyTypeClasses, formLayoutInfo.getWhichDerAttrs()));
}
if (formLayoutInfo.isVirAttrs()) {
wizardModel.add(new VirAttrs(modelObject, mode, anyTypeClasses, formLayoutInfo.getWhichVirAttrs()));
}
// role panel step (just available for users)
if ((this instanceof UserWizardBuilder)
&& modelObject instanceof UserWrapper
&& formLayoutInfo instanceof UserFormLayoutInfo
&& UserFormLayoutInfo.class.cast(formLayoutInfo).isRoles()) {
wizardModel.add(new Roles((UserWrapper) modelObject));
}
// relationship panel step (available for users and any objects)
if ((formLayoutInfo instanceof UserFormLayoutInfo
&& UserFormLayoutInfo.class.cast(formLayoutInfo).isRelationships())
|| (formLayoutInfo instanceof AnyObjectFormLayoutInfo
&& AnyObjectFormLayoutInfo.class.cast(formLayoutInfo).isRelationships())) {
wizardModel.add(new Relationships(modelObject, pageRef));
}
SyncopeWebApplication.get().getAnyWizardBuilderAdditionalSteps().
buildModelSteps(modelObject, wizardModel, formLayoutInfo);
return wizardModel;
}
protected Optional<Details<A>> addOptionalDetailsPanel(final AnyWrapper<A> modelObject) {
if (modelObject.getInnerObject().getKey() == null) {
return Optional.empty();
} else {
return Optional.of(new Details<>(modelObject, mode == AjaxWizard.Mode.TEMPLATE, true, pageRef));
}
}
@Override
protected void fixPlainAndVirAttrs(final AnyTO updated, final AnyTO original) {
// re-add to the updated object any missing plain or virtual attribute (compared to original): this to cope with
// form layout, which might have not included some plain or virtual attributes
for (Attr plainAttr : original.getPlainAttrs()) {
if (updated.getPlainAttr(plainAttr.getSchema()).isEmpty()) {
updated.getPlainAttrs().add(plainAttr);
}
}
for (Attr virAttr : original.getVirAttrs()) {
if (updated.getVirAttr(virAttr.getSchema()).isEmpty()) {
updated.getVirAttrs().add(virAttr);
}
}
if (updated instanceof GroupableRelatableTO && original instanceof GroupableRelatableTO) {
GroupableRelatableTO.class.cast(original).getMemberships().
forEach(oMemb -> GroupableRelatableTO.class.cast(updated).getMembership(oMemb.getGroupKey()).
ifPresent(uMemb -> {
oMemb.getPlainAttrs().stream().
filter(attr -> uMemb.getPlainAttr(attr.getSchema()).isEmpty()).
forEach(attr -> uMemb.getPlainAttrs().add(attr));
oMemb.getVirAttrs().stream().
filter(attr -> uMemb.getVirAttr(attr.getSchema()).isEmpty()).
forEach(attr -> uMemb.getVirAttrs().add(attr));
}));
}
// remove from the updated object any plain or virtual attribute without values, thus triggering for removal in
// the generated patch
updated.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty());
updated.getVirAttrs().removeIf(attr -> attr.getValues().isEmpty());
if (updated instanceof GroupableRelatableTO) {
GroupableRelatableTO.class.cast(updated).getMemberships().forEach(memb -> {
memb.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty());
memb.getVirAttrs().removeIf(attr -> attr.getValues().isEmpty());
});
}
}
@Override
protected long getMaxWaitTimeInSeconds() {
return SyncopeWebApplication.get().getMaxWaitTimeInSeconds();
}
@Override
protected void sendError(final Exception exception) {
SyncopeConsoleSession.get().onException(exception);
}
@Override
protected void sendWarning(final String message) {
SyncopeConsoleSession.get().warn(message);
}
@Override
protected Future<Pair<Serializable, Serializable>> execute(
final Callable<Pair<Serializable, Serializable>> future) {
return SyncopeConsoleSession.get().execute(future);
}
}