You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2021/08/14 17:33:11 UTC

[syncope] branch 2_1_X updated: [SYNCOPE-1639] Replacing HashSet with TreeSet + Comparable

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

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


The following commit(s) were added to refs/heads/2_1_X by this push:
     new b46d4ab  [SYNCOPE-1639] Replacing HashSet with TreeSet + Comparable
b46d4ab is described below

commit b46d4ab71a75e8ad2a7eaaf0482409a35c07ef08
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Sat Aug 14 19:32:57 2021 +0200

    [SYNCOPE-1639] Replacing HashSet with TreeSet + Comparable
---
 .../client/console/audit/AuditHistoryDetails.java  | 80 +++++++++++++++++++++-
 .../wicket/markup/html/form/JsonDiffPanel.java     | 14 ++--
 .../org/apache/syncope/common/lib/to/AnyTO.java    | 10 +--
 .../org/apache/syncope/common/lib/to/AttrTO.java   | 13 +++-
 .../apache/syncope/common/lib/to/ConnObjectTO.java |  4 +-
 .../apache/syncope/common/lib/to/DelegationTO.java |  4 +-
 .../syncope/common/lib/to/LinkedAccountTO.java     |  6 +-
 .../apache/syncope/common/lib/to/MembershipTO.java | 14 ++--
 .../syncope/common/lib/to/NotificationTaskTO.java  |  4 +-
 .../org/apache/syncope/common/lib/to/RealmTO.java  |  6 +-
 .../org/apache/syncope/common/lib/to/RoleTO.java   |  6 +-
 .../org/apache/syncope/common/lib/to/UserTO.java   |  4 +-
 12 files changed, 123 insertions(+), 42 deletions(-)

diff --git a/client/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
index 4b58d90..766f699 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
@@ -18,10 +18,23 @@
  */
 package org.apache.syncope.client.console.audit;
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.Date;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonDiffPanel;
@@ -45,7 +58,68 @@ public abstract class AuditHistoryDetails<T extends Serializable> extends Multil
 
     private static final Logger LOG = LoggerFactory.getLogger(AuditHistoryDetails.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static class SortingNodeFactory extends JsonNodeFactory {
+
+        private static final long serialVersionUID = 1870252010670L;
+
+        @Override
+        public ObjectNode objectNode() {
+            return new ObjectNode(this, new TreeMap<>());
+        }
+    }
+
+    private static class SortedSetJsonSerializer extends StdSerializer<Set<?>> {
+
+        private static final long serialVersionUID = 3849059774309L;
+
+        SortedSetJsonSerializer(final Class<Set<?>> clazz) {
+            super(clazz);
+        }
+
+        @Override
+        public void serialize(
+                final Set<?> set,
+                final JsonGenerator gen,
+                final SerializerProvider sp) throws IOException {
+
+            if (set == null) {
+                gen.writeNull();
+                return;
+            }
+
+            gen.writeStartArray();
+
+            if (!set.isEmpty()) {
+                Set<?> sorted = set;
+
+                // create sorted set only if it itself is not already SortedSet
+                if (!SortedSet.class.isAssignableFrom(set.getClass())) {
+                    Object item = set.iterator().next();
+                    if (Comparable.class.isAssignableFrom(item.getClass())) {
+                        // and only if items are Comparable
+                        sorted = new TreeSet<>(set);
+                    } else {
+                        LOG.debug("Cannot sort items of type {}", item.getClass());
+                    }
+                }
+
+                for (Object item : sorted) {
+                    gen.writeObject(item);
+                }
+            }
+
+            gen.writeEndArray();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Class<T> cast(final Class<?> aClass) {
+        return (Class<T>) aClass;
+    }
+
+    private static final ObjectMapper MAPPER = JsonMapper.builder().
+            nodeFactory(new SortingNodeFactory()).build().
+            registerModule(new SimpleModule().addSerializer(new SortedSetJsonSerializer(cast(Set.class))));
 
     public AuditHistoryDetails(
             final MultilevelPanel mlp,
@@ -116,7 +190,9 @@ public abstract class AuditHistoryDetails<T extends Serializable> extends Multil
                     ? MAPPER.readTree(auditEntry.getOutput()).get("entity").toPrettyString()
                     : auditEntry.getBefore();
 
-            T entity = MAPPER.readValue(content, reference);
+            T entity = MAPPER.reader().
+                    with(StreamReadFeature.STRICT_DUPLICATE_DETECTION).
+                    readValue(content, reference);
             if (entity instanceof UserTO) {
                 UserTO userTO = (UserTO) entity;
                 userTO.setPassword(null);
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java
index 8c5b80e..2ebc7bc 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java
@@ -30,10 +30,6 @@ public class JsonDiffPanel extends AbstractModalPanel<String> {
 
     private static final long serialVersionUID = -5110368813584745668L;
 
-    private final IModel<String> first;
-
-    private final IModel<String> second;
-
     public JsonDiffPanel(
             final BaseModal<String> modal,
             final IModel<String> first,
@@ -41,13 +37,13 @@ public class JsonDiffPanel extends AbstractModalPanel<String> {
             final PageReference pageRef) {
 
         super(modal, pageRef);
-        this.second = second;
-        this.first = first;
-        TextArea<String> jsonEditorInfoDefArea1 = new TextArea<>("jsonEditorInfo1", this.first);
-        TextArea<String> jsonEditorInfoDefArea2 = new TextArea<>("jsonEditorInfo2", this.second);
+
+        TextArea<String> jsonEditorInfoDefArea1 = new TextArea<>("jsonEditorInfo1", first);
         jsonEditorInfoDefArea1.setMarkupId("jsonEditorInfo1").setOutputMarkupPlaceholderTag(true);
-        jsonEditorInfoDefArea2.setMarkupId("jsonEditorInfo2").setOutputMarkupPlaceholderTag(true);
         add(jsonEditorInfoDefArea1);
+
+        TextArea<String> jsonEditorInfoDefArea2 = new TextArea<>("jsonEditorInfo2", second);
+        jsonEditorInfoDefArea2.setMarkupId("jsonEditorInfo2").setOutputMarkupPlaceholderTag(true);
         add(jsonEditorInfoDefArea2);
     }
 
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index d8bd896..51123ee 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -24,10 +24,10 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlSeeAlso;
@@ -61,13 +61,13 @@ public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, A
 
     private final List<String> auxClasses = new ArrayList<>();
 
-    private final Set<AttrTO> plainAttrs = new HashSet<>();
+    private final Set<AttrTO> plainAttrs = new TreeSet<>();
 
-    private final Set<AttrTO> derAttrs = new HashSet<>();
+    private final Set<AttrTO> derAttrs = new TreeSet<>();
 
-    private final Set<AttrTO> virAttrs = new HashSet<>();
+    private final Set<AttrTO> virAttrs = new TreeSet<>();
 
-    private final Set<String> resources = new HashSet<>();
+    private final Set<String> resources = new TreeSet<>();
 
     @Schema(name = "@class", required = true)
     public abstract String getDiscriminator();
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
index 570d91f..5152564 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
@@ -29,12 +29,13 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.lang3.builder.CompareToBuilder;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 
 @XmlRootElement(name = "attribute")
 @XmlType
-public class AttrTO implements Serializable {
+public class AttrTO implements Comparable<AttrTO>, Serializable {
 
     private static final long serialVersionUID = 4941691338796323623L;
 
@@ -106,6 +107,16 @@ public class AttrTO implements Serializable {
     }
 
     @Override
+    public int compareTo(final AttrTO other) {
+        return equals(other)
+                ? 0
+                : new CompareToBuilder().
+                        append(schema, other.schema).
+                        append(values, other.values).
+                        toComparison();
+    }
+
+    @Override
     public int hashCode() {
         return new HashCodeBuilder().
                 append(schema).
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
index fc0df8c..6c63bbc 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
@@ -21,9 +21,9 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.io.Serializable;
-import java.util.LinkedHashSet;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -39,7 +39,7 @@ public class ConnObjectTO implements Serializable {
 
     private String fiql;
 
-    private final Set<AttrTO> attrs = new LinkedHashSet<>();
+    private final Set<AttrTO> attrs = new TreeSet<>();
 
     public String getFiql() {
         return fiql;
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
index 322bc98..260516a 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
@@ -21,8 +21,8 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.ws.rs.PathParam;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
@@ -43,7 +43,7 @@ public class DelegationTO extends AbstractStartEndBean implements EntityTO {
 
     private String delegated;
 
-    private final Set<String> roles = new HashSet<>();
+    private final Set<String> roles = new TreeSet<>();
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
     @Override
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java
index fade911..c2d4673 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java
@@ -20,9 +20,9 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -82,9 +82,9 @@ public class LinkedAccountTO implements EntityTO {
 
     private boolean suspended;
 
-    private final Set<AttrTO> plainAttrs = new HashSet<>();
+    private final Set<AttrTO> plainAttrs = new TreeSet<>();
 
-    private final Set<String> privileges = new HashSet<>();
+    private final Set<String> privileges = new TreeSet<>();
 
     @Override
     public String getKey() {
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
index 361b40d..7d40a98 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
@@ -21,9 +21,9 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.io.Serializable;
-import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -63,11 +63,11 @@ public class MembershipTO implements Serializable, AttributableTO {
 
     private String groupName;
 
-    private final Set<AttrTO> plainAttrs = new HashSet<>();
+    private final Set<AttrTO> plainAttrs = new TreeSet<>();
 
-    private final Set<AttrTO> derAttrs = new HashSet<>();
+    private final Set<AttrTO> derAttrs = new TreeSet<>();
 
-    private final Set<AttrTO> virAttrs = new HashSet<>();
+    private final Set<AttrTO> virAttrs = new TreeSet<>();
 
     public String getGroupKey() {
         return groupKey;
@@ -162,8 +162,8 @@ public class MembershipTO implements Serializable, AttributableTO {
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).
-            append(this.groupKey).
-            append(this.groupName).
-            build();
+                append(this.groupKey).
+                append(this.groupName).
+                build();
     }
 }
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java
index 5ea6618..4a03cc0 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java
@@ -20,8 +20,8 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.HashSet;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -45,7 +45,7 @@ public class NotificationTaskTO extends TaskTO {
 
     private String entityKey;
 
-    private final Set<String> recipients = new HashSet<>();
+    private final Set<String> recipients = new TreeSet<>();
 
     private String sender;
 
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
index 1f31580..35eb5d4 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
@@ -21,10 +21,8 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import javax.ws.rs.PathParam;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
@@ -59,7 +57,7 @@ public class RealmTO extends BaseBean implements EntityTO, TemplatableTO {
     @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
     private final Map<String, AnyTO> templates = new HashMap<>();
 
-    private final Set<String> resources = new HashSet<>();
+    private final List<String> resources = new ArrayList<>();
 
     @Override
     public String getKey() {
@@ -128,7 +126,7 @@ public class RealmTO extends BaseBean implements EntityTO, TemplatableTO {
     @XmlElementWrapper(name = "resources")
     @XmlElement(name = "resource")
     @JsonProperty("resources")
-    public Set<String> getResources() {
+    public List<String> getResources() {
         return resources;
     }
 
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
index 97a764f..7935118 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
@@ -20,9 +20,9 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.ws.rs.PathParam;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
@@ -39,7 +39,7 @@ public class RoleTO implements EntityTO {
 
     private String key;
 
-    private final Set<String> entitlements = new HashSet<>();
+    private final Set<String> entitlements = new TreeSet<>();
 
     private final List<String> realms = new ArrayList<>();
 
@@ -47,7 +47,7 @@ public class RoleTO implements EntityTO {
 
     private String dynMembershipCond;
 
-    private final Set<String> privileges = new HashSet<>();
+    private final Set<String> privileges = new TreeSet<>();
 
     @Override
     public String getKey() {
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
index 5c3d17b..4d1a73d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
@@ -23,10 +23,10 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -48,7 +48,7 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
 
     private final List<String> dynRoles = new ArrayList<>();
 
-    private final Set<String> privileges = new HashSet<>();
+    private final Set<String> privileges = new TreeSet<>();
 
     private String token;