Decouple anchor from fragment in persistence module 22/116722/5
authorRuslan Kashapov <ruslan.kashapov@pantheon.tech>
Mon, 11 Jan 2021 14:44:32 +0000 (16:44 +0200)
committerRishi Chail <rishi.chail@est.tech>
Wed, 13 Jan 2021 10:18:31 +0000 (10:18 +0000)
Issue-ID: CPS-161
Change-Id: Ia446b26ee4eca9281e86bd2be3dd6836aa201597
Signed-off-by: Ruslan Kashapov <ruslan.kashapov@pantheon.tech>
cps-ri/src/main/java/org/onap/cps/spi/entities/AnchorEntity.java [new file with mode: 0644]
cps-ri/src/main/java/org/onap/cps/spi/entities/Fragment.java
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java [new file with mode: 0644]
cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
cps-ri/src/main/resources/schema.sql
cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java
cps-ri/src/test/resources/data/anchor.sql
cps-ri/src/test/resources/data/clear-all.sql

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 (file)
index 0000000..e7e9c97
--- /dev/null
@@ -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;
+}
index 2dbd6e9..053a223 100755 (executable)
@@ -46,10 +46,10 @@ import org.hibernate.annotations.TypeDefs;
  */\r
 @Getter\r
 @Setter\r
-@Entity\r
 @AllArgsConstructor\r
 @NoArgsConstructor\r
 @Builder\r
+@Entity\r
 @TypeDefs({@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)})\r
 public class Fragment implements Serializable {\r
 \r
@@ -67,9 +67,6 @@ public class Fragment implements Serializable {
     @Column(columnDefinition = "jsonb")\r
     private String attributes;\r
 \r
-    @Column(columnDefinition = "text")\r
-    private String anchorName;\r
-\r
     @NotNull\r
     @ManyToOne(fetch = FetchType.LAZY)\r
     @JoinColumn(name = "dataspace_id")\r
@@ -77,13 +74,9 @@ public class Fragment implements Serializable {
 \r
     @OneToOne(fetch = FetchType.LAZY)\r
     @JoinColumn(name = "anchor_id")\r
-    private Fragment anchorFragment;\r
+    private AnchorEntity anchor;\r
 \r
     @OneToOne(fetch = FetchType.LAZY)\r
     @JoinColumn(name = "parent_id")\r
     private Fragment parentFragment;\r
-\r
-    @OneToOne(fetch = FetchType.LAZY)\r
-    @JoinColumn(name = "schema_set_id")\r
-    private SchemaSet schemaSet;\r
 }\r
index d6579bd..fdb446c 100644 (file)
@@ -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<Anchor> getAnchors(final String dataspaceName) {
         final Dataspace dataspace = dataspaceRepository.getByName(dataspaceName);
-        final Collection<Fragment> 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<AnchorEntity> 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 (file)
index 0000000..df665f9
--- /dev/null
@@ -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<AnchorEntity, Integer> {
+    Optional<AnchorEntity> findByDataspaceAndName(@NotNull Dataspace dataspace, @NotNull String name);
+
+    Collection<AnchorEntity> findAllByDataspace(@NotNull Dataspace dataspace);
+}
index 2ee76cc..4521d09 100755 (executable)
 \r
 package org.onap.cps.spi.repository;\r
 \r
-import java.util.Collection;\r
-import java.util.Optional;\r
-import javax.validation.constraints.NotNull;\r
-import org.onap.cps.spi.entities.Dataspace;\r
 import org.onap.cps.spi.entities.Fragment;\r
 import org.springframework.data.jpa.repository.JpaRepository;\r
 import org.springframework.stereotype.Repository;\r
 \r
 @Repository\r
-public interface FragmentRepository extends JpaRepository<Fragment, Integer> {\r
+public interface FragmentRepository extends JpaRepository<Fragment, Long> {\r
 \r
-    Optional<Fragment> findByDataspaceAndAnchorName(@NotNull Dataspace dataspace, @NotNull String anchorName);\r
-\r
-    default Collection<Fragment> findFragmentsThatAreAnchorsByDataspace(Dataspace dataspace) {\r
-        return findFragmentsByDataspaceAndParentFragmentIsNull(dataspace);\r
-    }\r
-\r
-    Collection<Fragment> findFragmentsByDataspaceAndParentFragmentIsNull(Dataspace dataspace);\r
 }
\ No newline at end of file
index 58b3c63..d37d932 100755 (executable)
@@ -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\r
 );\r
 \r
+CREATE TABLE IF NOT EXISTS ANCHOR\r
+(\r
+    ID BIGSERIAL PRIMARY KEY,\r
+    NAME TEXT,\r
+    SCHEMA_SET_ID INTEGER REFERENCES SCHEMA_SET(ID),\r
+    DATASPACE_ID INTEGER NOT NULL REFERENCES DATASPACE(ID),\r
+    UNIQUE (DATASPACE_ID, NAME)\r
+);\r
+\r
 CREATE TABLE IF NOT EXISTS FRAGMENT\r
 (\r
     ID BIGSERIAL PRIMARY KEY,\r
     XPATH TEXT NOT NULL,\r
     ATTRIBUTES JSONB,\r
-    ANCHOR_NAME TEXT,\r
-    ANCHOR_ID BIGINT REFERENCES FRAGMENT(ID),\r
+    ANCHOR_ID BIGINT REFERENCES ANCHOR(ID),\r
     PARENT_ID BIGINT REFERENCES FRAGMENT(ID),\r
-    SCHEMA_SET_ID INTEGER REFERENCES SCHEMA_SET(ID),\r
     DATASPACE_ID INTEGER NOT NULL REFERENCES DATASPACE(ID),\r
     SCHEMA_NODE_ID INTEGER REFERENCES SCHEMA_NODE(ID),\r
-    UNIQUE (DATASPACE_ID, ANCHOR_NAME, XPATH)\r
+    UNIQUE (DATASPACE_ID, ANCHOR_ID, XPATH)\r
 );\r
 \r
 CREATE TABLE IF NOT EXISTS RELATION\r
@@ -78,9 +85,9 @@ CREATE TABLE IF NOT EXISTS RELATION
 );\r
 \r
 CREATE INDEX  IF NOT EXISTS "FKI_FRAGMENT_DATASPACE_ID_FK"     ON FRAGMENT USING BTREE(DATASPACE_ID) ;\r
-CREATE INDEX  IF NOT EXISTS "FKI_FRAGMENT_SCHEMA_SET_ID_FK"    ON FRAGMENT USING BTREE(SCHEMA_SET_ID) ;\r
 CREATE INDEX  IF NOT EXISTS "FKI_FRAGMENT_PARENT_ID_FK"        ON FRAGMENT USING BTREE(PARENT_ID) ;\r
 CREATE INDEX  IF NOT EXISTS "FKI_FRAGMENT_ANCHOR_ID_FK"        ON FRAGMENT USING BTREE(ANCHOR_ID) ;\r
+CREATE INDEX  IF NOT EXISTS "FKI_ANCHOR_SCHEMA_SET_ID_FK"      ON ANCHOR USING BTREE(SCHEMA_SET_ID) ;\r
 CREATE INDEX  IF NOT EXISTS "PERF_SCHEMA_NODE_SCHEMA_NODE_ID"  ON SCHEMA_NODE USING BTREE(SCHEMA_NODE_IDENTIFIER) ;\r
 CREATE INDEX  IF NOT EXISTS "FKI_SCHEMA_NODE_ID_TO_ID"         ON FRAGMENT USING BTREE(SCHEMA_NODE_ID) ;\r
 CREATE INDEX  IF NOT EXISTS "FKI_RELATION_TYPE_ID_FK"          ON RELATION USING BTREE(RELATION_TYPE_ID);\r
index 7497526..e5aac1e 100644 (file)
@@ -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)
index 5507559..1d9b4b1 100644 (file)
@@ -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
index 522f9e6..9aee604 100644 (file)
@@ -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;