This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new 73b4f6d23e [SYNCOPE-1908] Streamline Resources and Relationships 
management (#1167)
73b4f6d23e is described below

commit 73b4f6d23e1622290e6dc7bad97b45f7de18d9de
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Thu Sep 4 10:35:14 2025 +0200

    [SYNCOPE-1908] Streamline Resources and Relationships management (#1167)
---
 .../commons/IdMExternalResourceProvider.java       |  16 ++-
 .../client/console/wizards/any/Resources.java      |   6 +-
 .../ui/commons/layout/AbstractAnyFormLayout.java   |  10 ++
 .../ui/commons/wizards/any/AbstractResources.java  |  18 +--
 .../console/commons/ExternalResourceProvider.java  |   5 +-
 .../commons/IdRepoExternalResourceProvider.java    |   7 +-
 .../client/console/layout/UserFormLayoutInfo.java  |  10 --
 .../client/console/panels/RealmDetails.java        |   2 +-
 .../console/panels/RelationshipViewPanel.java      |  42 +++----
 .../console/panels/search/AbstractSearchPanel.java |  16 +--
 .../panels/search/AnyObjectSearchPanel.java        |   8 +-
 .../console/panels/search/GroupSearchPanel.java    |   2 +-
 .../client/console/panels/search/SearchUtils.java  |  18 +--
 .../console/wizards/any/AnyWizardBuilder.java      |  11 +-
 .../client/console/wizards/any/Relationships.java  | 140 ++++++---------------
 .../wizards/any/Relationships$Specification.html   |   2 +-
 .../apache/syncope/common/lib/AnyOperations.java   |  28 ++++-
 .../common/validation/RelationshipValidator.java   |   8 +-
 .../apache/syncope/fit/console/UsersITCase.java    |  97 --------------
 pom.xml                                            |   4 +-
 20 files changed, 163 insertions(+), 287 deletions(-)

diff --git 
a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMExternalResourceProvider.java
 
b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMExternalResourceProvider.java
index bb92a28554..53b47ff685 100644
--- 
a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMExternalResourceProvider.java
+++ 
b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMExternalResourceProvider.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
 import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 public class IdMExternalResourceProvider implements ExternalResourceProvider {
 
@@ -34,7 +35,18 @@ public class IdMExternalResourceProvider implements 
ExternalResourceProvider {
     }
 
     @Override
-    public List<String> get() {
-        return 
resourceRestClient.list().stream().map(ResourceTO::getKey).collect(Collectors.toList());
+    public List<String> get(final String anyType) {
+        return resourceRestClient.list().stream().
+                filter(r -> AnyTypeKind.GROUP.name().equals(anyType) || 
r.getProvision(anyType).isPresent()).
+                map(ResourceTO::getKey).
+                collect(Collectors.toList());
+    }
+
+    @Override
+    public List<String> getForRealms() {
+        return resourceRestClient.list().stream().
+                filter(r -> r.getOrgUnit() != null).
+                map(ResourceTO::getKey).
+                collect(Collectors.toList());
     }
 }
diff --git 
a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
 
b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
index ac1d1e131c..db2aeec635 100644
--- 
a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
+++ 
b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
@@ -47,10 +47,10 @@ public class Resources extends AbstractResources {
     public boolean evaluate() {
         if (SyncopeWebApplication.get().getSecuritySettings().
                 getAuthorizationStrategy().isActionAuthorized(this, RENDER)) {
-            
available.setObject(SyncopeWebApplication.get().getResourceProvider().get());
+
+            
available.setObject(SyncopeWebApplication.get().getResourceProvider().get(anyTO.getType()));
             return !available.getObject().isEmpty();
-        } else {
-            return false;
         }
+        return false;
     }
 }
diff --git 
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/layout/AbstractAnyFormLayout.java
 
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/layout/AbstractAnyFormLayout.java
index f998039384..2a7b6df727 100644
--- 
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/layout/AbstractAnyFormLayout.java
+++ 
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/layout/AbstractAnyFormLayout.java
@@ -28,10 +28,20 @@ public abstract class AbstractAnyFormLayout<A extends 
AnyTO, F extends AnyForm<A
 
     private static final long serialVersionUID = -6061683026789976508L;
 
+    private boolean relationships = true;
+
     private final List<String> whichPlainAttrs = new ArrayList<>();
 
     private final List<String> whichDerAttrs = new ArrayList<>();
 
+    public boolean isRelationships() {
+        return relationships;
+    }
+
+    public void setRelationships(final boolean relationships) {
+        this.relationships = relationships;
+    }
+
     public List<String> getWhichPlainAttrs() {
         return whichPlainAttrs;
     }
diff --git 
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
 
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
index ad1107db3f..f6fde2dd45 100644
--- 
a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
+++ 
b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/wizards/any/AbstractResources.java
@@ -34,15 +34,17 @@ public abstract class AbstractResources extends WizardStep 
implements ICondition
 
     private static final long serialVersionUID = 552437609667518888L;
 
+    protected final AnyTO anyTO;
+
     protected final ListModel<String> available;
 
     public <T extends AnyTO> AbstractResources(final AnyWrapper<T> 
modelObject) {
-        final T entityTO = modelObject.getInnerObject();
+        anyTO = modelObject.getInnerObject();
 
-        if (modelObject instanceof UserWrapper
-                && UserWrapper.class.cast(modelObject).getPreviousUserTO() != 
null
+        if (modelObject instanceof UserWrapper userWrapper
+                && userWrapper.getPreviousUserTO() != null
                 && !modelObject.getInnerObject().getResources().equals(
-                        
UserWrapper.class.cast(modelObject).getPreviousUserTO().getResources())) {
+                        userWrapper.getPreviousUserTO().getResources())) {
 
             add(new LabelInfo("changed", StringUtils.EMPTY));
         } else {
@@ -52,19 +54,19 @@ public abstract class AbstractResources extends WizardStep 
implements ICondition
         this.setOutputMarkupId(true);
         this.available = new ListModel<>(List.of());
 
-        add(new AjaxPalettePanel.Builder<String>().build("resources", new 
PropertyModel<>(entityTO, "resources") {
+        add(new AjaxPalettePanel.Builder<String>().build("resources", new 
PropertyModel<>(anyTO, "resources") {
 
             private static final long serialVersionUID = 3799387950428254072L;
 
             @Override
             public List<String> getObject() {
-                return new ArrayList<>(entityTO.getResources());
+                return new ArrayList<>(anyTO.getResources());
             }
 
             @Override
             public void setObject(final List<String> object) {
-                entityTO.getResources().clear();
-                entityTO.getResources().addAll(object);
+                anyTO.getResources().clear();
+                anyTO.getResources().addAll(object);
             }
         }, available).hideLabel().setOutputMarkupId(true));
     }
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ExternalResourceProvider.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ExternalResourceProvider.java
index fc419cff9f..0b86069239 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ExternalResourceProvider.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ExternalResourceProvider.java
@@ -21,8 +21,9 @@ package org.apache.syncope.client.console.commons;
 import java.io.Serializable;
 import java.util.List;
 
-@FunctionalInterface
 public interface ExternalResourceProvider extends Serializable {
 
-    List<String> get();
+    List<String> get(String anyType);
+
+    List<String> getForRealms();
 }
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoExternalResourceProvider.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoExternalResourceProvider.java
index e21f6225bc..5c0a5e776a 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoExternalResourceProvider.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoExternalResourceProvider.java
@@ -25,7 +25,12 @@ public class IdRepoExternalResourceProvider implements 
ExternalResourceProvider
     private static final long serialVersionUID = 3002474783308961295L;
 
     @Override
-    public List<String> get() {
+    public List<String> get(final String anyType) {
+        return List.of();
+    }
+
+    @Override
+    public List<String> getForRealms() {
         return List.of();
     }
 }
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
index 22e7e89980..4c9d233619 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/layout/UserFormLayoutInfo.java
@@ -31,8 +31,6 @@ public class UserFormLayoutInfo extends 
AbstractAnyFormLayout<UserTO, UserForm>
 
     private boolean roles = true;
 
-    private boolean relationships = true;
-
     @Override
     protected Class<? extends UserForm> getDefaultFormClass() {
         return UserWizardBuilder.class;
@@ -53,12 +51,4 @@ public class UserFormLayoutInfo extends 
AbstractAnyFormLayout<UserTO, UserForm>
     public void setRoles(final boolean roles) {
         this.roles = roles;
     }
-
-    public boolean isRelationships() {
-        return relationships;
-    }
-
-    public void setRelationships(final boolean relationships) {
-        this.relationships = relationships;
-    }
 }
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
index 86bfecf495..5f57098eb8 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
@@ -88,7 +88,7 @@ public class RealmDetails extends Panel {
 
         @Override
         protected List<String> load() {
-            return SyncopeWebApplication.get().getResourceProvider().get();
+            return 
SyncopeWebApplication.get().getResourceProvider().getForRealms();
         }
     };
 
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipViewPanel.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipViewPanel.java
index d979d2f96d..9272776b30 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipViewPanel.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RelationshipViewPanel.java
@@ -28,6 +28,7 @@ import 
org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.client.ui.commons.Constants;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyEntitlement;
@@ -56,8 +57,15 @@ public final class RelationshipViewPanel extends 
WizardMgtPanel<RelationshipTO>
             final AnyTO anyTO,
             final boolean reuseItem,
             final boolean wizardInModal) {
+
         super(id, wizardInModal);
-        addInnerObject(getHeader());
+
+        WebMarkupContainer header = new WebMarkupContainer("header");
+        header.add(new Label("header_left_end", getString("left.end")));
+        header.add(new Label("header_relationship", new 
ResourceModel("relationship")));
+        header.add(new Label("header_right_end", new 
ResourceModel("right.end")));
+        addInnerObject(header);
+
         relationshipsList = new ListView<>("relationships", relationships) {
 
             private static final long serialVersionUID = 4983556433071042668L;
@@ -101,9 +109,8 @@ public final class RelationshipViewPanel extends 
WizardMgtPanel<RelationshipTO>
                 if (togglePanel == null) {
                     relationshipItem.add(action);
                 } else {
-                    relationshipItem.add(new ActionsPanel<>("action", new 
Model<>(relationshipTO))
-                            .setVisible(false)
-                            .setEnabled(false));
+                    relationshipItem.add(new ActionsPanel<>("action", new 
Model<>(relationshipTO)).
+                            setVisible(false).setEnabled(false));
                 }
             }
         };
@@ -112,25 +119,20 @@ public final class RelationshipViewPanel extends 
WizardMgtPanel<RelationshipTO>
         relationshipsList.setRenderBodyOnly(true);
 
         addInnerObject(relationshipsList);
-
-    }
-
-    private WebMarkupContainer getHeader() {
-        WebMarkupContainer headerContainer = new WebMarkupContainer("header");
-        headerContainer.add(new Label("header_left_end", 
getString("left.end")));
-        headerContainer.add(new Label("header_relationship", new 
ResourceModel("relationship")));
-        headerContainer.add(new Label("header_right_end", new 
ResourceModel("right.end")));
-        return headerContainer;
     }
 
-    private void buildRowLabels(
+    private static void buildRowLabels(
             final ListItem<RelationshipTO> row,
             final RelationshipTO relationshipTO,
             final AnyTO anyTO) {
+
         boolean isLeftRelation = relationshipTO.getEnd() == 
RelationshipTO.End.LEFT;
-        String anyName = anyTO instanceof UserTO
-                ? UserTO.class.cast(anyTO).getUsername()
-                : AnyObjectTO.class.cast(anyTO).getName();
+
+        String anyName = anyTO instanceof UserTO userTO
+                ? userTO.getUsername()
+                : anyTO instanceof GroupTO groupTO
+                        ? groupTO.getName()
+                        : AnyObjectTO.class.cast(anyTO).getName();
 
         row.add(new Label("relationship", relationshipTO.getType()));
         Label leftEnd = new Label("left_end", isLeftRelation
@@ -149,7 +151,7 @@ public final class RelationshipViewPanel extends 
WizardMgtPanel<RelationshipTO>
         row.add(leftEnd, rightEnd);
     }
 
-    private void setBold(final Label... labels) {
+    private static void setBold(final Label... labels) {
         for (Label label : labels) {
             label.add(new AttributeModifier("style", "font-weight: bold;"));
         }
@@ -176,7 +178,6 @@ public final class RelationshipViewPanel extends 
WizardMgtPanel<RelationshipTO>
             return this;
         }
 
-
         public RelationshipViewPanel.Builder setRelationships(final 
List<RelationshipTO> relationships) {
             this.relationships = relationships;
             return this;
@@ -204,8 +205,5 @@ public final class RelationshipViewPanel extends 
WizardMgtPanel<RelationshipTO>
         protected WizardMgtPanel<RelationshipTO> newInstance(final String id, 
final boolean wizardInModal) {
             return new RelationshipViewPanel(id, relationships, anyTO, 
reuseItem, wizardInModal);
         }
-
     }
-
 }
-
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
index bbe164e84e..fb71837ce0 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
@@ -87,7 +87,7 @@ public abstract class AbstractSearchPanel extends Panel {
 
     protected final AnyTypeKind typeKind;
 
-    protected final String type;
+    protected final String anyType;
 
     public abstract static class Builder<T extends AbstractSearchPanel> 
implements Serializable {
 
@@ -150,7 +150,7 @@ public abstract class AbstractSearchPanel extends Panel {
 
         this.model = builder.model;
         this.typeKind = kind;
-        this.type = type;
+        this.anyType = type;
 
         setOutputMarkupId(true);
 
@@ -233,8 +233,8 @@ public abstract class AbstractSearchPanel extends Panel {
     protected abstract String getFIQLQueryTarget();
 
     protected void updateFIQL(final AjaxRequestTarget target, final String 
fiql) {
-        model.setObject(SearchUtils.getSearchClauses(
-                
fiql.replaceAll(SearchUtils.getTypeConditionPattern(type).pattern(), "")));
+        
model.setObject(SearchUtils.getSearchClauses(fiql.replaceAll(SearchUtils.getTypeConditionPattern(anyType).
+                pattern(), "")));
         target.add(searchFormContainer);
     }
 
@@ -275,17 +275,17 @@ public abstract class AbstractSearchPanel extends Panel {
 
             @Override
             protected List<String> load() {
-                return SyncopeWebApplication.get().getResourceProvider().get();
+                return 
SyncopeWebApplication.get().getResourceProvider().get(anyType);
             }
         };
     }
 
     public IModel<List<SearchClause>> getModel() {
-        return this.model;
+        return model;
     }
 
-    public String getBackObjectType() {
-        return this.type;
+    public String getAnyType() {
+        return anyType;
     }
 
     public Map<String, PlainSchemaTO> getAvailableSchemaTypes() {
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
index 908168830c..4045b8f03a 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
@@ -77,12 +77,12 @@ public class AnyObjectSearchPanel extends 
AbstractSearchPanel {
 
     @Override
     protected AbstractFiqlSearchConditionBuilder<?, ?, ?> 
getSearchConditionBuilder() {
-        return SyncopeClient.getAnyObjectSearchConditionBuilder(type);
+        return SyncopeClient.getAnyObjectSearchConditionBuilder(anyType);
     }
 
     @Override
     protected String getFIQLQueryTarget() {
-        return type;
+        return anyType;
     }
 
     @Override
@@ -121,8 +121,8 @@ public class AnyObjectSearchPanel extends 
AbstractSearchPanel {
 
             @Override
             protected Map<String, PlainSchemaTO> load() {
-                return 
schemaRestClient.<PlainSchemaTO>getSchemas(SchemaType.PLAIN, null, 
anyTypeRestClient.read(type).
-                        getClasses().toArray(String[]::new)).
+                return schemaRestClient.<PlainSchemaTO>getSchemas(
+                        SchemaType.PLAIN, null, 
anyTypeRestClient.read(anyType).getClasses().toArray(String[]::new)).
                         stream().collect(Collectors.toMap(SchemaTO::getKey, 
Function.identity()));
             }
         };
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
index 66251893dd..22da0fad1a 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
@@ -110,7 +110,7 @@ public class GroupSearchPanel extends AbstractSearchPanel {
             @Override
             protected Map<String, PlainSchemaTO> load() {
                 return schemaRestClient.<PlainSchemaTO>getSchemas(
-                        SchemaType.PLAIN, null, 
anyTypeRestClient.read(type).getClasses().toArray(String[]::new)).
+                        SchemaType.PLAIN, null, 
anyTypeRestClient.read(anyType).getClasses().toArray(String[]::new)).
                         stream().collect(Collectors.toMap(SchemaTO::getKey, 
Function.identity()));
             }
         };
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
index 6101b96b5f..c45c38b550 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
@@ -246,14 +246,14 @@ public final class SearchUtils implements Serializable {
 
                 switch (clause.getType()) {
                     case GROUP_MEMBER:
-                        if (builder instanceof 
GroupFiqlSearchConditionBuilder) {
+                        if (builder instanceof final 
GroupFiqlSearchConditionBuilder gbuilder) {
                             switch (clause.getComparator()) {
                                 case EQUALS:
-                                    condition = 
((GroupFiqlSearchConditionBuilder) builder).withMembers(value);
+                                    condition = gbuilder.withMembers(value);
                                     break;
 
                                 case NOT_EQUALS:
-                                    condition = 
((GroupFiqlSearchConditionBuilder) builder).withoutMembers(value);
+                                    condition = gbuilder.withoutMembers(value);
                                     break;
 
                                 default:
@@ -265,14 +265,14 @@ public final class SearchUtils implements Serializable {
                         if (StringUtils.isNotBlank(clause.getProperty())) {
                             String groupKey = clause.getProperty();
 
-                            if (builder instanceof final 
UserFiqlSearchConditionBuilder conditionBuilder) {
+                            if (builder instanceof final 
UserFiqlSearchConditionBuilder ubuilder) {
                                 condition = clause.getComparator() == 
SearchClause.Comparator.EQUALS
-                                        ? conditionBuilder.inGroups(groupKey)
-                                        : 
conditionBuilder.notInGroups(groupKey);
-                            } else {
+                                        ? ubuilder.inGroups(groupKey)
+                                        : ubuilder.notInGroups(groupKey);
+                            } else if (builder instanceof final 
AnyObjectFiqlSearchConditionBuilder abuilder) {
                                 condition = clause.getComparator() == 
SearchClause.Comparator.EQUALS
-                                        ? 
((AnyObjectFiqlSearchConditionBuilder) builder).inGroups(groupKey)
-                                        : 
((AnyObjectFiqlSearchConditionBuilder) builder).notInGroups(groupKey);
+                                        ? abuilder.inGroups(groupKey)
+                                        : abuilder.notInGroups(groupKey);
                             }
                         }
                         break;
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
index cedd20287e..bf322d4b3b 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
@@ -26,7 +26,6 @@ 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 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;
@@ -127,8 +126,7 @@ public abstract class AnyWizardBuilder<A extends AnyTO> 
extends AbstractAnyWizar
 
         // attributes panel steps
         if (formLayoutInfo.isPlainAttrs()) {
-            wizardModel.add(
-                    new PlainAttrs(modelObject, mode, anyTypeClasses, 
formLayoutInfo.getWhichPlainAttrs()) {
+            wizardModel.add(new PlainAttrs(modelObject, mode, anyTypeClasses, 
formLayoutInfo.getWhichPlainAttrs()) {
 
                 private static final long serialVersionUID = 
8167894751609598306L;
 
@@ -151,12 +149,7 @@ public abstract class AnyWizardBuilder<A extends AnyTO> 
extends AbstractAnyWizar
             wizardModel.add(new Roles(userWrapper));
         }
 
-        // 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())) {
-
+        if (formLayoutInfo.isRelationships()) {
             wizardModel.add(new Relationships(modelObject, pageRef));
         }
 
diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
index 13df8494e2..608130945a 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
@@ -20,7 +20,9 @@ package org.apache.syncope.client.console.wizards.any;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -32,8 +34,6 @@ import 
org.apache.syncope.client.console.panels.search.AnySelectionDirectoryPane
 import org.apache.syncope.client.console.panels.search.SearchClausePanel;
 import org.apache.syncope.client.console.panels.search.SearchUtils;
 import org.apache.syncope.client.console.rest.AnyObjectRestClient;
-import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
-import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.RelationshipTypeRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import 
org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
@@ -44,16 +44,15 @@ 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.ajax.markup.html.LabelInfo;
 import 
org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import 
org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 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.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.AnyTypeTO;
-import org.apache.syncope.common.lib.to.GroupableRelatableTO;
+import org.apache.syncope.common.lib.to.RelatableTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.RelationshipTypeTO;
 import org.apache.syncope.common.lib.types.AnyEntitlement;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.wicket.Component;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -63,10 +62,8 @@ import 
org.apache.wicket.extensions.wizard.WizardModel.ICondition;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.markup.html.panel.Fragment;
 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;
@@ -80,12 +77,6 @@ public class Relationships extends WizardStep implements 
ICondition {
     @SpringBean
     protected RelationshipTypeRestClient relationshipTypeRestClient;
 
-    @SpringBean
-    protected AnyTypeRestClient anyTypeRestClient;
-
-    @SpringBean
-    protected AnyTypeClassRestClient anyTypeClassRestClient;
-
     @SpringBean
     protected AnyObjectRestClient anyObjectRestClient;
 
@@ -158,18 +149,19 @@ public class Relationships extends WizardStep implements 
ICondition {
     }
 
     protected List<RelationshipTO> getCurrentRelationships() {
-        return anyTO instanceof GroupableRelatableTO
-                ? GroupableRelatableTO.class.cast(anyTO).getRelationships()
+        return anyTO instanceof RelatableTO relatableTO
+                ? relatableTO.getRelationships()
                 : List.of();
     }
 
-    protected void addNewRelationships(final RelationshipTO... rels) {
-        getCurrentRelationships().addAll(List.of(rels));
+    protected void addNewRelationship(final RelationshipTO relaltionship) {
+        if (anyTO instanceof RelatableTO relatableTO) {
+            relatableTO.getRelationships().add(relaltionship);
+        }
     }
 
     @Override
     public boolean evaluate() {
-        // [SYNCOPE-1171] - skip current step when the are no relationships 
types in Syncope
         return !relationshipTypeRestClient.list().isEmpty();
     }
 
@@ -179,10 +171,6 @@ public class Relationships extends WizardStep implements 
ICondition {
 
         protected final RelationshipTO rel;
 
-        protected final AjaxDropDownChoicePanel<String> type;
-
-        protected final AjaxDropDownChoicePanel<AnyTypeTO> otherType;
-
         protected final WebMarkupContainer container;
 
         protected final Fragment emptyFragment;
@@ -198,60 +186,18 @@ public class Relationships extends WizardStep implements 
ICondition {
             rel = new RelationshipTO();
             rel.setEnd(RelationshipTO.End.LEFT);
 
-            List<String> availableRels = 
relationshipTypeRestClient.list().stream().
-                    
map(RelationshipTypeTO::getKey).collect(Collectors.toList());
-
-            type = new AjaxDropDownChoicePanel<>("type", "type", new 
PropertyModel<>(rel, "type"));
-            type.setChoices(availableRels);
+            Map<String, RelationshipTypeTO> relationshipTypes = 
relationshipTypeRestClient.list().stream().
+                    filter(relationshipType -> 
relationshipType.getLeftEndAnyType().equals(anyTO.getType())).
+                    collect(Collectors.toMap(RelationshipTypeTO::getKey, 
Function.identity()));
+            AjaxDropDownChoicePanel<String> type = new 
AjaxDropDownChoicePanel<>(
+                    "type", "type", new PropertyModel<>(rel, "type"), false);
+            
type.setChoices(relationshipTypes.keySet().stream().sorted().toList());
+            type.setNullValid(false);
             
add(type.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).setRenderBodyOnly(true));
 
-            List<AnyTypeTO> availableTypes = 
anyTypeRestClient.listAnyTypes().stream().
-                    filter(anyType -> anyType.getKind() != AnyTypeKind.GROUP
-                    && anyType.getKind() != 
AnyTypeKind.USER).collect(Collectors.toList());
-
-            otherType = new AjaxDropDownChoicePanel<>("otherType", 
"otherType", new PropertyModel<>(rel, "otherType") {
-
-                private static final long serialVersionUID = 
-5861057041758169508L;
-
-                @Override
-                public AnyTypeTO getObject() {
-                    for (AnyTypeTO obj : availableTypes) {
-                        if (obj.getKey().equals(rel.getOtherEndType())) {
-                            return obj;
-                        }
-                    }
-                    return null;
-                }
-
-                @Override
-                public void setObject(final AnyTypeTO object) {
-                    
rel.setOtherEndType(Optional.ofNullable(object).map(AnyTypeTO::getKey).orElse(null));
-                }
-            }, false);
-            otherType.setChoices(availableTypes);
-            otherType.setChoiceRenderer(new IChoiceRenderer<>() {
-
-                private static final long serialVersionUID = 
-734743540442190178L;
-
-                @Override
-                public Object getDisplayValue(final AnyTypeTO object) {
-                    return object.getKey();
-                }
-
-                @Override
-                public String getIdValue(final AnyTypeTO object, final int 
index) {
-                    return object.getKey();
-                }
-
-                @Override
-                public AnyTypeTO getObject(final String id, final IModel<? 
extends List<? extends AnyTypeTO>> choices) {
-                    return choices.getObject().stream().
-                            filter(anyTypeTO -> 
id.equals(anyTypeTO.getKey())).findAny().orElse(null);
-                }
-            });
-            // enable "otherType" dropdown only if "type" option is selected - 
SYNCOPE-1140
-            otherType.setEnabled(false);
-            
add(otherType.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
+            AjaxTextFieldPanel otherEndType = new AjaxTextFieldPanel(
+                    "otherType", "otherType", new PropertyModel<>(rel, 
"otherEndType"));
+            
add(otherEndType.setEnabled(false).setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
 
             container = new WebMarkupContainer("searchPanelContainer");
             add(container.setOutputMarkupId(true));
@@ -268,35 +214,29 @@ public class Relationships extends WizardStep implements 
ICondition {
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
                     
container.addOrReplace(emptyFragment.setRenderBodyOnly(true));
-                    otherType.setModelObject(null);
-                    // enable "otherType" dropdown only if "type" option is 
selected - SYNCOPE-1140
-                    otherType.setEnabled(type.getModelObject() != null && 
!type.getModelObject().isEmpty());
-                    target.add(otherType);
-                    target.add(container);
-                }
-            });
 
-            otherType.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                private static final long serialVersionUID = 
-1107858522700306810L;
-
-                @Override
-                protected void onUpdate(final AjaxRequestTarget target) {
-                    AnyTypeTO anyType = otherType.getModelObject();
-                    if (anyType == null) {
-                        
container.addOrReplace(emptyFragment.setRenderBodyOnly(true));
+                    if (type.getModelObject() == null) {
+                        otherEndType.setModelObject(null);
                     } else {
-                        setupFragment(anyType);
-                        
container.addOrReplace(fragment.setRenderBodyOnly(true));
+                        
Optional.ofNullable(relationshipTypes.get(type.getModelObject())).
+                                
map(RelationshipTypeTO::getRightEndAnyType).ifPresent(
+                                oet -> {
+                                    otherEndType.setModelObject(oet);
+
+                                    setupFragment(oet);
+                                    
container.addOrReplace(fragment.setRenderBodyOnly(true));
+                                });
                     }
+
+                    target.add(otherEndType);
                     target.add(container);
                 }
             });
         }
 
-        protected void setupFragment(final AnyTypeTO anyType) {
+        protected void setupFragment(final String anyType) {
             anyObjectSearchPanel = new AnyObjectSearchPanel.Builder(
-                    anyType.getKey(),
+                    anyType,
                     new ListModel<>(new ArrayList<>()),
                     pageRef).
                     enableSearch(Specification.this).
@@ -304,11 +244,11 @@ public class Relationships extends WizardStep implements 
ICondition {
             
fragment.addOrReplace(anyObjectSearchPanel.setRenderBodyOnly(true));
 
             anyObjectDirectoryPanel = new 
AnyObjectSelectionDirectoryPanel.Builder(
-                    anyTypeClassRestClient.list(anyType.getClasses()),
+                    List.of(),
                     anyObjectRestClient,
-                    anyType.getKey(),
+                    anyType,
                     pageRef).
-                    
setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType.getKey()).
+                    
setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType).
                             
is(Constants.KEY_FIELD_NAME).notNullValue().query()).
                     setWizardInModal(true).build("searchResultPanel");
             
fragment.addOrReplace(anyObjectDirectoryPanel.setRenderBodyOnly(true));
@@ -320,8 +260,8 @@ public class Relationships extends WizardStep implements 
ICondition {
                 AjaxRequestTarget target =
                         
SearchClausePanel.SearchEvent.class.cast(event.getPayload()).getTarget();
                 String fiql = 
SearchUtils.buildFIQL(anyObjectSearchPanel.getModel().getObject(),
-                        
SyncopeClient.getAnyObjectSearchConditionBuilder(anyObjectSearchPanel.getBackObjectType()));
-                
AnyDirectoryPanel.class.cast(Specification.this.anyObjectDirectoryPanel).search(fiql,
 target);
+                        
SyncopeClient.getAnyObjectSearchConditionBuilder(anyObjectSearchPanel.getAnyType()));
+                
AnyDirectoryPanel.class.cast(anyObjectDirectoryPanel).search(fiql, target);
             } else if (event.getPayload() instanceof 
AnySelectionDirectoryPanel.ItemSelection) {
                 AjaxRequestTarget target =
                         
AnySelectionDirectoryPanel.ItemSelection.class.cast(event.getPayload()).getTarget();
@@ -330,7 +270,7 @@ public class Relationships extends WizardStep implements 
ICondition {
                 rel.setOtherEndKey(right.getKey());
                 rel.setOtherEndName(AnyObjectTO.class.cast(right).getName());
 
-                Relationships.this.addNewRelationships(rel);
+                Relationships.this.addNewRelationship(rel);
 
                 
Relationships.this.addOrReplace(getViewFragment().setRenderBodyOnly(true));
                 target.add(Relationships.this);
diff --git 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships$Specification.html
 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships$Specification.html
index c58eb6f595..18e2b52189 100644
--- 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships$Specification.html
+++ 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/Relationships$Specification.html
@@ -19,7 +19,7 @@ under the License.
 <html xmlns="http://www.w3.org/1999/xhtml"; 
xmlns:wicket="http://wicket.apache.org";>
   <wicket:panel>
     <div class="form-group">
-      <span wicket:id="type" />
+      <span wicket:id="type"/>
     </div>
 
     <div class="form-group">
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
index 7fd3ed1227..9ea7ca0b85 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
@@ -175,7 +175,7 @@ public final class AnyOperations {
                 
EntityTOUtils.buildRelationshipMap(original.getRelationships());
 
         updatedRels.entrySet().stream().
-                filter(entry -> (!originalRels.containsKey(entry.getKey()))).
+                filter(entry -> !originalRels.containsKey(entry.getKey())).
                 forEach(entry -> result.getRelationships().add(new 
RelationshipUR.Builder(entry.getValue()).
                 operation(PatchOperation.ADD_REPLACE).build()));
 
@@ -277,7 +277,7 @@ public final class AnyOperations {
                 
EntityTOUtils.buildRelationshipMap(original.getRelationships());
 
         updatedRels.entrySet().stream().
-                filter(entry -> (!originalRels.containsKey(entry.getKey()))).
+                filter(entry -> !originalRels.containsKey(entry.getKey())).
                 forEach(entry -> result.getRelationships().add(new 
RelationshipUR.Builder(entry.getValue()).
                 operation(PatchOperation.ADD_REPLACE).build()));
 
@@ -358,6 +358,23 @@ public final class AnyOperations {
         // 4. type extensions
         result.getTypeExtensions().addAll(updated.getTypeExtensions());
 
+        // 5. relationships
+        Map<Pair<String, String>, RelationshipTO> updatedRels =
+                EntityTOUtils.buildRelationshipMap(updated.getRelationships());
+        Map<Pair<String, String>, RelationshipTO> originalRels =
+                
EntityTOUtils.buildRelationshipMap(original.getRelationships());
+
+        updatedRels.entrySet().stream().
+                filter(entry -> !originalRels.containsKey(entry.getKey())).
+                forEach(entry -> result.getRelationships().add(new 
RelationshipUR.Builder(entry.getValue()).
+                operation(PatchOperation.ADD_REPLACE).build()));
+
+        if (!incremental) {
+            originalRels.keySet().stream().filter(relationship -> 
!updatedRels.containsKey(relationship)).
+                    forEach(key -> result.getRelationships().add(new 
RelationshipUR.Builder(originalRels.get(key)).
+                    operation(PatchOperation.DELETE).build()));
+        }
+
         return result;
     }
 
@@ -367,10 +384,11 @@ public final class AnyOperations {
 
         if (updated instanceof UserTO updatedUserTO && original instanceof 
UserTO originalUserTO) {
             return (P) diff(updatedUserTO, originalUserTO, incremental);
-        } else if (updated instanceof GroupTO updatedGroupTO && original 
instanceof GroupTO originalGroupTO) {
+        }
+        if (updated instanceof GroupTO updatedGroupTO && original instanceof 
GroupTO originalGroupTO) {
             return (P) diff(updatedGroupTO, originalGroupTO, incremental);
-        } else if (updated instanceof AnyObjectTO updatedAnyObjectTO
-                && original instanceof AnyObjectTO originalObjectTO) {
+        }
+        if (updated instanceof AnyObjectTO updatedAnyObjectTO && original 
instanceof AnyObjectTO originalObjectTO) {
             return (P) diff(updatedAnyObjectTO, originalObjectTO, incremental);
         }
 
diff --git 
a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/RelationshipValidator.java
 
b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/RelationshipValidator.java
index 38fc2a2666..15f414a304 100644
--- 
a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/RelationshipValidator.java
+++ 
b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/RelationshipValidator.java
@@ -33,7 +33,9 @@ public class RelationshipValidator extends 
AbstractValidator<RelationshipCheck,
 
         RelationshipType relationshipType = relationship.getType();
 
-        if 
(!relationshipType.getLeftEndAnyType().equals(relationship.getLeftEnd().getType()))
 {
+        if (relationship.getLeftEnd() != null
+                && 
!relationshipType.getLeftEndAnyType().equals(relationship.getLeftEnd().getType()))
 {
+
             context.buildConstraintViolationWithTemplate(
                     getTemplate(EntityViolationType.InvalidAnyType, 
relationship.getLeftEnd().getType().getKey())).
                     addPropertyNode("leftEnd").addConstraintViolation();
@@ -41,7 +43,9 @@ public class RelationshipValidator extends 
AbstractValidator<RelationshipCheck,
             isValid = false;
         }
 
-        if 
(!relationshipType.getRightEndAnyType().equals(relationship.getRightEnd().getType()))
 {
+        if (relationship.getRightEnd() != null
+                && 
!relationshipType.getRightEndAnyType().equals(relationship.getRightEnd().getType()))
 {
+
             context.buildConstraintViolationWithTemplate(
                     getTemplate(EntityViolationType.InvalidAnyType, 
relationship.getRightEnd().getType().getKey())).
                     addPropertyNode("rightEnd").addConstraintViolation();
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
index 901ccbf10b..fcae9ee53e 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/UsersITCase.java
@@ -108,103 +108,6 @@ public class UsersITCase extends AbstractConsoleITCase {
         formTester.submit("buttons:cancel");
     }
 
-    @Test
-    public void editRelationships() {
-        TESTER.clickLink("body:realmsLI:realms", false);
-        
TESTER.clickLink("body:content:body:container:content:tabbedPanel:tabs-container:tabs:1:link");
-
-        Component component = findComponentByProp("username", CONTAINER
-                + 
":searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", 
"puccini");
-        assertNotNull(component);
-
-        TESTER.executeAjaxEvent(component.getPageRelativePath(), 
Constants.ON_CLICK);
-        TESTER.clickLink(TAB_PANEL
-                + 
"outerObjectsRepeater:1:outer:container:content:togglePanelContainer:container:"
-                + "actions:actions:actionRepeater:0:action:action");
-
-        TESTER.assertComponent(TAB_PANEL
-                + 
"outerObjectsRepeater:0:outer:form:content:form:view:username:textField",
-                TextField.class);
-
-        FormTester formTester = TESTER.newFormTester(TAB_PANEL
-                + "outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-
-        formTester.submit("buttons:next");
-
-        formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-        formTester.submit("buttons:next");
-
-        formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-        formTester.submit("buttons:next");
-
-        formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-        formTester.submit("buttons:next");
-
-        formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-        formTester.submit("buttons:next");
-
-        formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-        formTester.submit("buttons:next");
-
-        // Add first RELATIONSHIP
-        addRelationship("Canon MF 8030cn");
-        component = TESTER.getComponentFromLastRenderedPage(TAB_PANEL + 
"outerObjectsRepeater:0:outer"
-                + 
":form:content:form:view:relationships:relationships:container:content:relationships:0:right_end");
-        assertNotNull(component);
-        assertEquals("PRINTER Canon MF 8030cn", 
component.getDefaultModel().getObject());
-
-        // Add second RELATIONSHIP
-        addRelationship("HP LJ 1300n");
-        component = TESTER.getComponentFromLastRenderedPage(TAB_PANEL + 
"outerObjectsRepeater:0:outer"
-                + 
":form:content:form:view:relationships:relationships:container:content:relationships:1:right_end");
-        assertNotNull(component);
-        assertEquals("PRINTER HP LJ 1300n", 
component.getDefaultModel().getObject());
-
-        formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-        formTester.submit("buttons:cancel");
-    }
-
-    // issue SYNCOPE-1846
-    private void addRelationship(final String printerName) {
-        TESTER.executeAjaxEvent(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form:view:relationships:actions:"
-                + "actionRepeater:0:action:action", Constants.ON_CLICK);
-        FormTester formTester = TESTER.newFormTester(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form");
-        assertNotNull(formTester);
-
-        
formTester.setValue("view:relationships:specification:type:dropDownChoiceField",
 "neighborhood");
-        TESTER.executeAjaxEvent(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form:view:relationships:"
-                + "specification:type:dropDownChoiceField", 
Constants.ON_CHANGE);
-         
formTester.setValue("view:relationships:specification:type:dropDownChoiceField",
 "neighborhood");
-        // The ON_CHANGE above should enable this component, but it doesn't; 
doing it by hand
-        Component otherType = findComponentById(
-                TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form:view:relationships:specification",
-                "otherType");
-        assertNotNull(otherType);
-        otherType.setEnabled(true);
-
-        
formTester.setValue("view:relationships:specification:otherType:dropDownChoiceField",
 "PRINTER");
-        TESTER.executeAjaxEvent(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form:view:relationships:"
-                + "specification:otherType:dropDownChoiceField", 
Constants.ON_CHANGE);
-
-        Component component = findComponentByProp("name", TAB_PANEL + 
"outerObjectsRepeater:"
-                + 
"0:outer:form:content:form:view:relationships:specification:searchPanelContainer:searchPanel:"
-                + 
"searchResultPanel:container:content:searchContainer:resultTable:tablePanel:groupForm:checkgroup:"
-                + "dataTable:body:rows:1:cells:2:cell", printerName);
-        assertNotNull(component);
-        TESTER.executeAjaxEvent(component, Constants.ON_CLICK);
-        TESTER.clickLink(TAB_PANEL + 
"outerObjectsRepeater:0:outer:form:content:form:view:relationships:specification:"
-                + "searchPanelContainer:searchPanel:searchResultPanel:"
-                + 
"outerObjectsRepeater:1:outer:container:content:togglePanelContainer:container:"
-                + "actions:actions:actionRepeater:0:action:action");
-    }
-
     @Test
     public void editUser() {
         TESTER.clickLink("body:realmsLI:realms", false);
diff --git a/pom.xml b/pom.xml
index 4d97f0d090..81f2087f1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -447,7 +447,7 @@ under the License.
     <cas-client.version>4.0.4</cas-client.version>
 
     <swagger-core.version>2.2.36</swagger-core.version>
-    <swagger-ui.version>5.27.1</swagger-ui.version>
+    <swagger-ui.version>5.28.0</swagger-ui.version>
 
     <jquery-slimscroll.version>1.3.8</jquery-slimscroll.version>
     <jquery-cookie.version>1.4.1-1</jquery-cookie.version>
@@ -505,7 +505,7 @@ under the License.
 
     <tomcat.version>11.0.10</tomcat.version>
     <wildfly.version>37.0.0.Final</wildfly.version>
-    <payara.version>6.2025.8</payara.version>
+    <payara.version>6.2025.9</payara.version>
     <jakarta.faces.version>4.1.3</jakarta.faces.version>
 
     <docker.postgresql.version>17-alpine</docker.postgresql.version>

Reply via email to