From: Toine Siebelink Date: Thu, 4 May 2023 14:14:08 +0000 (+0000) Subject: Merge "Sensible equals and hashCode for FragmentEntity (CPS-1664 #1)" X-Git-Tag: 3.3.2~35 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=61e8551cf91c95844963f0e52cefddb6a7477d38;hp=d3a2b33cf99e1ae334c0690e7f5dc1a299f39fb7;p=cps.git Merge "Sensible equals and hashCode for FragmentEntity (CPS-1664 #1)" --- diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java index b893428278..b59150f2e4 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Pantheon.tech + * Modifications Copyright (C) 2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +33,7 @@ import javax.persistence.Table; import javax.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -46,6 +48,7 @@ import lombok.Setter; @Builder @Entity @Table(name = "anchor") +@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class AnchorEntity implements Serializable { private static final long serialVersionUID = -8049987915308262518L; @@ -56,6 +59,7 @@ public class AnchorEntity implements Serializable { @NotNull @Column + @EqualsAndHashCode.Include private String name; @NotNull @@ -66,5 +70,6 @@ public class AnchorEntity implements Serializable { @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dataspace_id") + @EqualsAndHashCode.Include private DataspaceEntity dataspace; } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java index 593746d94f..4d97054d9e 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/DataspaceEntity.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020-2021 Nordix Foundation. + * Copyright (C) 2020-2023 Nordix Foundation. * Modifications Copyright (C) 2020-2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +30,7 @@ import javax.persistence.Id; import javax.persistence.Table; import javax.validation.constraints.NotNull; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -44,6 +45,7 @@ import lombok.Setter; @AllArgsConstructor @NoArgsConstructor @Table(name = "dataspace") +@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class DataspaceEntity implements Serializable { private static final long serialVersionUID = 8395254649813051882L; @@ -54,6 +56,7 @@ public class DataspaceEntity implements Serializable { @NotNull @Column(columnDefinition = "text") + @EqualsAndHashCode.Include private String name; /** diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java index 05befc8711..e696a4064a 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntity.java @@ -88,6 +88,7 @@ public class FragmentEntity implements Serializable { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "anchor_id") + @EqualsAndHashCode.Include private AnchorEntity anchor; @ToString.Exclude diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy index 204b93442f..c8e3283a91 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy @@ -50,7 +50,7 @@ class CpsDataPersistenceServiceSpec extends Specification { def objectUnderTest = Spy(new CpsDataPersistenceServiceImpl(mockDataspaceRepository, mockAnchorRepository, mockFragmentRepository, jsonObjectMapper, mockSessionManager)) - def anchorEntity = new AnchorEntity(id: 123, dataspace: new DataspaceEntity(id: 1)) + static def anchorEntity = new AnchorEntity(id: 123, dataspace: new DataspaceEntity(id: 1)) def setup() { mockAnchorRepository.getByDataspaceAndName(_, _) >> anchorEntity @@ -198,12 +198,12 @@ class CpsDataPersistenceServiceSpec extends Specification { where: 'the following Data Type is passed' scenario | dataNodes || expectedFragmentEntities 'empty data node list' | [] || [] - 'one data node in list' | [new DataNode(xpath: '/test/xpath', leaves: ['id': 'testId'], childDataNodes: [])] || [new FragmentEntity(xpath: '/test/xpath', attributes: '{"id":"testId"}', childFragments: [])] + 'one data node in list' | [new DataNode(xpath: '/test/xpath', leaves: ['id': 'testId'], childDataNodes: [])] || [new FragmentEntity(xpath: '/test/xpath', attributes: '{"id":"testId"}', anchor: anchorEntity, childFragments: [])] } def 'update data nodes and descendants'() { given: 'the fragment repository returns fragment entities related to the xpath inputs' - mockFragmentRepository.findExtractsWithDescendants(123, ['/test/xpath1', '/test/xpath2'] as Set, _) >> [ + mockFragmentRepository.findExtractsWithDescendants(_, ['/test/xpath1', '/test/xpath2'] as Set, _) >> [ mockFragmentExtract(1, null, 123, '/test/xpath1', null), mockFragmentExtract(2, null, 123, '/test/xpath2', null) ] @@ -211,14 +211,13 @@ class CpsDataPersistenceServiceSpec extends Specification { def dataNode1 = new DataNode(xpath: '/test/xpath1', leaves: ['id': 'testId1'], childDataNodes: [new DataNode(xpath: '/test/xpath1/child', leaves: ['id': 'childTestId1'])]) def dataNode2 = new DataNode(xpath: '/test/xpath2', leaves: ['id': 'testId2'], childDataNodes: [new DataNode(xpath: '/test/xpath2/child', leaves: ['id': 'childTestId2'])]) when: 'the fragment entities are update by the data nodes' - objectUnderTest.updateDataNodesAndDescendants('dataspaceName', 'anchorName', [dataNode1, dataNode2]) + objectUnderTest.updateDataNodesAndDescendants('dataspace', 'anchor', [dataNode1, dataNode2]) then: 'call fragment repository save all method is called with the updated fragments' 1 * mockFragmentRepository.saveAll({fragmentEntities -> { - fragmentEntities.containsAll([ - new FragmentEntity(xpath: '/test/xpath1', attributes: '{"id":"testId1"}', childFragments: [new FragmentEntity(xpath: '/test/xpath1/child', attributes: '{"id":"childTestId1"}', childFragments: [])]), - new FragmentEntity(xpath: '/test/xpath2', attributes: '{"id":"testId2"}', childFragments: [new FragmentEntity(xpath: '/test/xpath2/child', attributes: '{"id":"childTestId2"}', childFragments: [])]) - ]) assert fragmentEntities.size() == 2 + def fragmentEntityPerXpath = fragmentEntities.collectEntries { [it.xpath, it] } + assert fragmentEntityPerXpath.get('/test/xpath1').childFragments.first().attributes == '{"id":"childTestId1"}' + assert fragmentEntityPerXpath.get('/test/xpath2').childFragments.first().attributes == '{"id":"childTestId2"}' }}) } @@ -241,10 +240,9 @@ class CpsDataPersistenceServiceSpec extends Specification { def scenario = it.value def dataNode = new DataNodeBuilder().withXpath(xpath).build() dataNodes.add(dataNode) - def fragmentExtract = mockFragmentExtract(fragmentId, null, null, xpath, null) + def fragmentExtract = mockFragmentExtract(fragmentId, null, 123, xpath, null) fragmentExtracts.add(fragmentExtract) - def fragmentEntity = new FragmentEntity(id: fragmentId, xpath: xpath, childFragments: []) - mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, xpath) >> fragmentEntity + def fragmentEntity = new FragmentEntity(id: fragmentId, anchor: anchorEntity, xpath: xpath, childFragments: []) if ('EXCEPTION' == scenario) { mockFragmentRepository.save(fragmentEntity) >> { throw new StaleStateException("concurrent updates") } }