From 1843c3bba68bb75dd7532ae637880e503a2fa1ee Mon Sep 17 00:00:00 2001 From: Ivan Yakubenko <42006970+YakubenkoIv@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:06:24 +0200 Subject: [PATCH] Add caching hashcode to artefact references (#81) Co-authored-by: Ivan Yakubenko --- .../IdentifiableArtefactReferenceImpl.java | 35 +++++++-- .../sdmx30/MaintainableArtefactReference.java | 72 +++++++++++++++++-- 2 files changed, 94 insertions(+), 13 deletions(-) diff --git a/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/IdentifiableArtefactReferenceImpl.java b/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/IdentifiableArtefactReferenceImpl.java index 5a05d55..d5e5425 100644 --- a/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/IdentifiableArtefactReferenceImpl.java +++ b/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/IdentifiableArtefactReferenceImpl.java @@ -5,16 +5,12 @@ import java.util.Map; import java.util.Objects; -import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; import org.apache.commons.lang3.StringUtils; @NoArgsConstructor @Getter -@Setter -@EqualsAndHashCode(callSuper = true) public class IdentifiableArtefactReferenceImpl extends MaintainableArtefactReference implements ArtefactReference { @@ -76,6 +72,18 @@ public IdentifiableArtefactReferenceImpl(ArtefactReference from) { this.itemId = Objects.requireNonNull(from.getItemId()); } + public void setItemId(String itemId) { + this.itemId = itemId; + invalidateHashCode(); + } + + @Override + protected int computeHashCode() { + int result = super.computeHashCode(); + result = 31 * result + Objects.hashCode(itemId); + return result; + } + @Override public boolean isItemReference() { return StringUtils.isNotEmpty(itemId); @@ -92,6 +100,7 @@ public StructureClass getMaintainableStructureClass() { return parentType(); } + @Override public String getUrn() { final String urn = super.getUrn(); if (itemId != null) { @@ -100,6 +109,7 @@ public String getUrn() { return urn; } + @Override public ArtefactReference getMaintainableArtefactReference() { return new MaintainableArtefactReference( getId(), @@ -121,7 +131,18 @@ public IdentifiableArtefactReferenceImpl clone() { @Override public String toString() { - String superString = super.toString(); - return superString + "." + itemId; + return super.toString() + "." + itemId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof IdentifiableArtefactReferenceImpl that)) { + return false; + } + return super.equals(o) + && Objects.equals(itemId, that.itemId); } -} +} \ No newline at end of file diff --git a/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/MaintainableArtefactReference.java b/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/MaintainableArtefactReference.java index 16623e7..45fc8d2 100644 --- a/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/MaintainableArtefactReference.java +++ b/sdmx30-infomodel/src/main/java/com/epam/jsdmx/infomodel/sdmx30/MaintainableArtefactReference.java @@ -4,14 +4,12 @@ import java.util.Optional; import java.util.function.Function; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; -@Data +@Getter @NoArgsConstructor -@EqualsAndHashCode(callSuper = false) public class MaintainableArtefactReference implements ArtefactReference { protected String id; @@ -19,6 +17,9 @@ public class MaintainableArtefactReference implements ArtefactReference { protected StructureClass structureClass; protected VersionReference version; + private transient int cachedHashCode; + private transient boolean hashCodeComputed; + public MaintainableArtefactReference(String id, String organisationId, VersionReference version, StructureClass structureClass) { this.id = id; this.organisationId = organisationId; @@ -96,6 +97,65 @@ public boolean isItemReference() { @Override public String toString() { - return (structureClass != null ? structureClass.getSimpleName() : "null") + "=" + organisationId + ":" + id + "(" + getVersionString() + ")"; + return (structureClass != null ? structureClass.getSimpleName() : "null") + + "=" + organisationId + ":" + id + "(" + getVersionString() + ")"; + } + + public void setId(String id) { + this.id = id; + invalidateHashCode(); + } + + public void setOrganisationId(String organisationId) { + this.organisationId = organisationId; + invalidateHashCode(); + } + + public void setStructureClass(StructureClass structureClass) { + this.structureClass = structureClass; + invalidateHashCode(); + } + + public void setVersion(VersionReference version) { + this.version = version; + invalidateHashCode(); + } + + protected void invalidateHashCode() { + this.cachedHashCode = 0; + this.hashCodeComputed = false; + } + + protected int computeHashCode() { + int result = Objects.hashCode(id); + result = 31 * result + Objects.hashCode(organisationId); + result = 31 * result + Objects.hashCode(structureClass); + result = 31 * result + Objects.hashCode(version); + return result; + } + + @Override + public int hashCode() { + if (hashCodeComputed) { + return cachedHashCode; + } + + cachedHashCode = computeHashCode(); + hashCodeComputed = true; + return cachedHashCode; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof MaintainableArtefactReference that)) { + return false; + } + return Objects.equals(id, that.id) + && Objects.equals(organisationId, that.organisationId) + && Objects.equals(structureClass, that.structureClass) + && Objects.equals(version, that.version); } -} +} \ No newline at end of file