From 49fe075361e4f0f3b2a1a561bc01f831983a3efb Mon Sep 17 00:00:00 2001 From: Ruslan Kashapov Date: Mon, 11 Jan 2021 16:44:32 +0200 Subject: Decouple anchor from fragment in persistence module Issue-ID: CPS-161 Change-Id: Ia446b26ee4eca9281e86bd2be3dd6836aa201597 Signed-off-by: Ruslan Kashapov --- .../org/onap/cps/spi/entities/AnchorEntity.java | 70 ++++++++++++++++++++++ .../java/org/onap/cps/spi/entities/Fragment.java | 11 +--- .../spi/impl/CpsAdminPersistenceServiceImpl.java | 31 +++++----- .../onap/cps/spi/repository/AnchorRepository.java | 33 ++++++++++ .../cps/spi/repository/FragmentRepository.java | 13 +--- cps-ri/src/main/resources/schema.sql | 17 ++++-- .../spi/impl/CpsAdminPersistenceServiceTest.java | 18 +++--- cps-ri/src/test/resources/data/anchor.sql | 6 +- cps-ri/src/test/resources/data/clear-all.sql | 7 ++- 9 files changed, 150 insertions(+), 56 deletions(-) create mode 100644 cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java create mode 100644 cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java 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 new file mode 100644 index 000000000..e7e9c971d --- /dev/null +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java @@ -0,0 +1,70 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Pantheon.tech + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.entities; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * Entity to store an anchor. + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Entity +@Table(name = "anchor") +public class AnchorEntity implements Serializable { + + private static final long serialVersionUID = -8049987915308262518L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @NotNull + @Column + private String name; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "schema_set_id") + private SchemaSet schemaSet; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "dataspace_id") + private Dataspace dataspace; +} diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/Fragment.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/Fragment.java index 2dbd6e98f..053a22321 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/Fragment.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/Fragment.java @@ -46,10 +46,10 @@ import org.hibernate.annotations.TypeDefs; */ @Getter @Setter -@Entity @AllArgsConstructor @NoArgsConstructor @Builder +@Entity @TypeDefs({@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)}) public class Fragment implements Serializable { @@ -67,9 +67,6 @@ public class Fragment implements Serializable { @Column(columnDefinition = "jsonb") private String attributes; - @Column(columnDefinition = "text") - private String anchorName; - @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dataspace_id") @@ -77,13 +74,9 @@ public class Fragment implements Serializable { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "anchor_id") - private Fragment anchorFragment; + private AnchorEntity anchor; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_id") private Fragment parentFragment; - - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "schema_set_id") - private SchemaSet schemaSet; } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java index d6579bdbb..fdb446c84 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java @@ -24,14 +24,14 @@ package org.onap.cps.spi.impl; import java.util.Collection; import java.util.stream.Collectors; import org.onap.cps.spi.CpsAdminPersistenceService; +import org.onap.cps.spi.entities.AnchorEntity; import org.onap.cps.spi.entities.Dataspace; -import org.onap.cps.spi.entities.Fragment; import org.onap.cps.spi.entities.SchemaSet; import org.onap.cps.spi.exceptions.AnchorAlreadyDefinedException; import org.onap.cps.spi.exceptions.DataspaceAlreadyDefinedException; import org.onap.cps.spi.model.Anchor; +import org.onap.cps.spi.repository.AnchorRepository; import org.onap.cps.spi.repository.DataspaceRepository; -import org.onap.cps.spi.repository.FragmentRepository; import org.onap.cps.spi.repository.SchemaSetRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; @@ -44,7 +44,7 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic private DataspaceRepository dataspaceRepository; @Autowired - private FragmentRepository fragmentRepository; + private AnchorRepository anchorRepository; @Autowired private SchemaSetRepository schemaSetRepository; @@ -62,14 +62,13 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic public void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) { final Dataspace dataspace = dataspaceRepository.getByName(dataspaceName); final SchemaSet schemaSet = schemaSetRepository.getByDataspaceAndName(dataspace, schemaSetName); - final Fragment anchor = Fragment.builder() - .xpath(anchorName) - .anchorName(anchorName) + final AnchorEntity anchorEntity = AnchorEntity.builder() + .name(anchorName) .dataspace(dataspace) .schemaSet(schemaSet) .build(); try { - fragmentRepository.save(anchor); + anchorRepository.save(anchorEntity); } catch (final DataIntegrityViolationException e) { throw new AnchorAlreadyDefinedException(dataspaceName, anchorName, e); } @@ -78,13 +77,15 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic @Override public Collection getAnchors(final String dataspaceName) { final Dataspace dataspace = dataspaceRepository.getByName(dataspaceName); - final Collection fragments = fragmentRepository.findFragmentsThatAreAnchorsByDataspace(dataspace); - return fragments.stream().map( - entity -> Anchor.builder() - .name(entity.getAnchorName()) - .dataspaceName(dataspaceName) - .schemaSetName(entity.getSchemaSet().getName()) - .build() - ).collect(Collectors.toList()); + final Collection anchorEntities = anchorRepository.findAllByDataspace(dataspace); + return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toList()); + } + + private static Anchor toAnchor(final AnchorEntity anchorEntity) { + return Anchor.builder() + .name(anchorEntity.getName()) + .dataspaceName(anchorEntity.getDataspace().getName()) + .schemaSetName(anchorEntity.getSchemaSet().getName()) + .build(); } } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java new file mode 100644 index 000000000..df665f931 --- /dev/null +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Pantheon.tech + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.repository; + +import java.util.Collection; +import java.util.Optional; +import javax.validation.constraints.NotNull; +import org.onap.cps.spi.entities.AnchorEntity; +import org.onap.cps.spi.entities.Dataspace; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AnchorRepository extends JpaRepository { + Optional findByDataspaceAndName(@NotNull Dataspace dataspace, @NotNull String name); + + Collection findAllByDataspace(@NotNull Dataspace dataspace); +} diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java index 2ee76cc12..4521d091d 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java @@ -21,22 +21,11 @@ package org.onap.cps.spi.repository; -import java.util.Collection; -import java.util.Optional; -import javax.validation.constraints.NotNull; -import org.onap.cps.spi.entities.Dataspace; import org.onap.cps.spi.entities.Fragment; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository -public interface FragmentRepository extends JpaRepository { +public interface FragmentRepository extends JpaRepository { - Optional findByDataspaceAndAnchorName(@NotNull Dataspace dataspace, @NotNull String anchorName); - - default Collection findFragmentsThatAreAnchorsByDataspace(Dataspace dataspace) { - return findFragmentsByDataspaceAndParentFragmentIsNull(dataspace); - } - - Collection findFragmentsByDataspaceAndParentFragmentIsNull(Dataspace dataspace); } \ No newline at end of file diff --git a/cps-ri/src/main/resources/schema.sql b/cps-ri/src/main/resources/schema.sql index 58b3c63c8..d37d932aa 100755 --- a/cps-ri/src/main/resources/schema.sql +++ b/cps-ri/src/main/resources/schema.sql @@ -53,18 +53,25 @@ CREATE TABLE IF NOT EXISTS MODULE CONSTRAINT MODULE_DATASPACE FOREIGN KEY (DATASPACE_ID) REFERENCES DATASPACE (id) ON UPDATE CASCADE ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS ANCHOR +( + ID BIGSERIAL PRIMARY KEY, + NAME TEXT, + SCHEMA_SET_ID INTEGER REFERENCES SCHEMA_SET(ID), + DATASPACE_ID INTEGER NOT NULL REFERENCES DATASPACE(ID), + UNIQUE (DATASPACE_ID, NAME) +); + CREATE TABLE IF NOT EXISTS FRAGMENT ( ID BIGSERIAL PRIMARY KEY, XPATH TEXT NOT NULL, ATTRIBUTES JSONB, - ANCHOR_NAME TEXT, - ANCHOR_ID BIGINT REFERENCES FRAGMENT(ID), + ANCHOR_ID BIGINT REFERENCES ANCHOR(ID), PARENT_ID BIGINT REFERENCES FRAGMENT(ID), - SCHEMA_SET_ID INTEGER REFERENCES SCHEMA_SET(ID), DATASPACE_ID INTEGER NOT NULL REFERENCES DATASPACE(ID), SCHEMA_NODE_ID INTEGER REFERENCES SCHEMA_NODE(ID), - UNIQUE (DATASPACE_ID, ANCHOR_NAME, XPATH) + UNIQUE (DATASPACE_ID, ANCHOR_ID, XPATH) ); CREATE TABLE IF NOT EXISTS RELATION @@ -78,9 +85,9 @@ CREATE TABLE IF NOT EXISTS RELATION ); CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_DATASPACE_ID_FK" ON FRAGMENT USING BTREE(DATASPACE_ID) ; -CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_SCHEMA_SET_ID_FK" ON FRAGMENT USING BTREE(SCHEMA_SET_ID) ; CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_PARENT_ID_FK" ON FRAGMENT USING BTREE(PARENT_ID) ; CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_ANCHOR_ID_FK" ON FRAGMENT USING BTREE(ANCHOR_ID) ; +CREATE INDEX IF NOT EXISTS "FKI_ANCHOR_SCHEMA_SET_ID_FK" ON ANCHOR USING BTREE(SCHEMA_SET_ID) ; CREATE INDEX IF NOT EXISTS "PERF_SCHEMA_NODE_SCHEMA_NODE_ID" ON SCHEMA_NODE USING BTREE(SCHEMA_NODE_IDENTIFIER) ; CREATE INDEX IF NOT EXISTS "FKI_SCHEMA_NODE_ID_TO_ID" ON FRAGMENT USING BTREE(SCHEMA_NODE_ID) ; CREATE INDEX IF NOT EXISTS "FKI_RELATION_TYPE_ID_FK" ON RELATION USING BTREE(RELATION_TYPE_ID); diff --git a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java b/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java index 7497526f9..e5aac1eea 100644 --- a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java +++ b/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java @@ -29,15 +29,15 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.onap.cps.DatabaseTestContainer; import org.onap.cps.spi.CpsAdminPersistenceService; +import org.onap.cps.spi.entities.AnchorEntity; import org.onap.cps.spi.entities.Dataspace; -import org.onap.cps.spi.entities.Fragment; import org.onap.cps.spi.exceptions.AnchorAlreadyDefinedException; import org.onap.cps.spi.exceptions.DataspaceAlreadyDefinedException; import org.onap.cps.spi.exceptions.DataspaceNotFoundException; import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; import org.onap.cps.spi.model.Anchor; +import org.onap.cps.spi.repository.AnchorRepository; import org.onap.cps.spi.repository.DataspaceRepository; -import org.onap.cps.spi.repository.FragmentRepository; import org.onap.cps.spi.repository.SchemaSetRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -69,7 +69,7 @@ public class CpsAdminPersistenceServiceTest { private CpsAdminPersistenceService cpsAdminPersistenceService; @Autowired - private FragmentRepository fragmentRepository; + private AnchorRepository anchorRepository; @Autowired private DataspaceRepository dataspaceRepository; @@ -102,13 +102,13 @@ public class CpsAdminPersistenceServiceTest { // validate anchor persisted final Dataspace dataspace = dataspaceRepository.findByName(DATASPACE_NAME).orElseThrow(); - final Fragment anchor = - fragmentRepository.findByDataspaceAndAnchorName(dataspace, ANCHOR_NAME_NEW).orElseThrow(); + final AnchorEntity anchorEntity = + anchorRepository.findByDataspaceAndName(dataspace, ANCHOR_NAME_NEW).orElseThrow(); - assertNotNull(anchor.getId()); - assertEquals(ANCHOR_NAME_NEW, anchor.getAnchorName()); - assertEquals(DATASPACE_NAME, anchor.getDataspace().getName()); - assertEquals(SCHEMA_SET_NAME2, anchor.getSchemaSet().getName()); + assertNotNull(anchorEntity.getId()); + assertEquals(ANCHOR_NAME_NEW, anchorEntity.getName()); + assertEquals(DATASPACE_NAME, anchorEntity.getDataspace().getName()); + assertEquals(SCHEMA_SET_NAME2, anchorEntity.getSchemaSet().getName()); } @Test(expected = DataspaceNotFoundException.class) diff --git a/cps-ri/src/test/resources/data/anchor.sql b/cps-ri/src/test/resources/data/anchor.sql index 55075596b..1d9b4b1ec 100644 --- a/cps-ri/src/test/resources/data/anchor.sql +++ b/cps-ri/src/test/resources/data/anchor.sql @@ -4,6 +4,6 @@ INSERT INTO DATASPACE (ID, NAME) VALUES INSERT INTO SCHEMA_SET (ID, NAME, DATASPACE_ID) VALUES (2001, 'SCHEMA-SET-001', 1001), (2002, 'SCHEMA-SET-002', 1001); -INSERT INTO FRAGMENT (ID, XPATH, ANCHOR_NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES - (3001, 'ANCHOR-001', 'ANCHOR-001', 1001, 2001), - (3002, 'ANCHOR-002', 'ANCHOR-002', 1001, 2002); \ No newline at end of file +INSERT INTO ANCHOR (ID, NAME, DATASPACE_ID, SCHEMA_SET_ID) VALUES + (3001, 'ANCHOR-001', 1001, 2001), + (3002, 'ANCHOR-002', 1001, 2002); \ No newline at end of file diff --git a/cps-ri/src/test/resources/data/clear-all.sql b/cps-ri/src/test/resources/data/clear-all.sql index 522f9e617..9aee604a3 100644 --- a/cps-ri/src/test/resources/data/clear-all.sql +++ b/cps-ri/src/test/resources/data/clear-all.sql @@ -1,6 +1,7 @@ DELETE FROM FRAGMENT; --- clear all via dataspace table cleanup --- all other data will be removed by cascade +DELETE FROM ANCHOR; DELETE FROM DATASPACE; --- explicit clear +-- following tables are cleared by CASCADE constraint: +-- SCHEMA_SET +-- SCHEMA_SET_YANG_RESOURCES DELETE FROM YANG_RESOURCE; -- cgit 1.2.3-korg