fc33adc18ed5006dec41bd77e755dcb6db2d5e7f
[smo/teiv.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2024 Ericsson
4  *  Modifications Copyright (C) 2024 OpenInfra Foundation Europe
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21 package org.oran.smo.teiv.pgsqlgenerator.schema.data;
22
23 import java.util.List;
24
25 import org.junit.jupiter.api.Assertions;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.mockito.MockitoAnnotations;
29 import org.springframework.beans.factory.annotation.Autowired;
30 import org.springframework.boot.test.context.SpringBootTest;
31
32 import org.oran.smo.teiv.pgsqlgenerator.Attribute;
33 import org.oran.smo.teiv.pgsqlgenerator.Column;
34 import org.oran.smo.teiv.pgsqlgenerator.Entity;
35 import org.oran.smo.teiv.pgsqlgenerator.UniqueConstraint;
36 import org.oran.smo.teiv.pgsqlgenerator.PrimaryKeyConstraint;
37 import org.oran.smo.teiv.pgsqlgenerator.ForeignKeyConstraint;
38 import org.oran.smo.teiv.pgsqlgenerator.Relationship;
39 import org.oran.smo.teiv.pgsqlgenerator.Table;
40 import org.oran.smo.teiv.pgsqlgenerator.TestHelper;
41 import org.oran.smo.teiv.pgsqlgenerator.schema.model.HashInfoDataGenerator;
42 import lombok.extern.slf4j.Slf4j;
43
44 import static org.oran.smo.teiv.pgsqlgenerator.Constants.CLASSIFIERS;
45 import static org.oran.smo.teiv.pgsqlgenerator.Constants.DECORATORS;
46 import static org.oran.smo.teiv.pgsqlgenerator.Constants.JSONB;
47
48 @Slf4j
49 @SpringBootTest(classes = { TableBuilder.class, HashInfoDataGenerator.class })
50 class TableBuilderTest {
51     @Autowired
52     private TableBuilder tableBuilder;
53
54     @BeforeEach
55     void setUp() {
56
57         //mocks
58         MockitoAnnotations.openMocks(this);
59
60     }
61
62     //spotless:off
63     List<Entity> entities = List.of(
64         Entity.builder().entityName("EntityA").storedAt("module-a_EntityA").attributes(
65                 List.of(
66                     Attribute.builder().name("azimuth").dataType("DECIMAL").build(),
67                     Attribute.builder().name("id").dataType("TEXT").constraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_Sector_id")
68                             .tableName("Sector").columnToAddConstraintTo("id").build())).build(),
69                     Attribute.builder().name("geo-location").dataType("geography").build(),
70                     Attribute.builder().name("sectorId").dataType("jsonb").build()))
71             .moduleReferenceName("")
72             .build(),
73
74         Entity.builder().entityName("EntityB").storedAt("module-b_EntityB").attributes(
75                 List.of(
76                     Attribute.builder().name("id").dataType("TEXT").constraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_Namespace_id")
77                             .tableName("Namespace").columnToAddConstraintTo("id").build())).build(),
78                     Attribute.builder().name("name").dataType("TEXT").build()))
79             .build());
80
81     List<List<Relationship>> relationships = List.of(
82         List.of(Relationship.builder().name("oneToOne")
83             .aSideAssociationName("used-EntityB")
84             .aSideMOType("EntityA")
85             .aSideModule("module-a")
86             .aSideMinCardinality(0)
87             .aSideMaxCardinality(1)
88             .bSideAssociationName("used-by-EntityA")
89             .bSideMOType("EntityB")
90             .bSideModule("module-b")
91             .bSideMinCardinality(0)
92             .bSideMaxCardinality(1)
93             .relationshipDataLocation("A_SIDE")
94             .associationKind("BI_DIRECTIONAL")
95             .connectSameEntity(false)
96             .storedAt("module-a_EntityA")
97             .aSideStoredAt("module-a_EntityA")
98             .bSideStoredAt("module-b_EntityB")
99             .moduleReferenceName("").build()),
100         List.of(Relationship.builder().name("oneToMany")
101             .aSideAssociationName("used-EntityB")
102             .aSideMOType("EntityA")
103             .aSideModule("module-a")
104             .aSideMinCardinality(0)
105             .aSideMaxCardinality(1)
106             .bSideAssociationName("used-by-EntityA")
107             .bSideMOType("EntityB")
108             .bSideModule("module-b")
109             .bSideMinCardinality(0)
110             .bSideMaxCardinality(100)
111             .relationshipDataLocation("A_SIDE")
112             .associationKind("BI_DIRECTIONAL")
113             .connectSameEntity(false)
114             .storedAt("module-b_EntityB")
115             .aSideStoredAt("module-a_EntityA")
116             .bSideStoredAt("module-b_EntityB")
117             .moduleReferenceName("").build()),
118         List.of(Relationship.builder().name("ManyToOne")
119             .aSideAssociationName("used-EntityB")
120             .aSideMOType("EntityA")
121             .aSideModule("module-a")
122             .aSideMinCardinality(0)
123             .aSideMaxCardinality(100)
124             .bSideAssociationName("used-by-EntityA")
125             .bSideMOType("EntityB")
126             .bSideModule("module-b")
127             .bSideMinCardinality(0)
128             .bSideMaxCardinality(1)
129             .relationshipDataLocation("A_SIDE")
130             .associationKind("BI_DIRECTIONAL")
131             .connectSameEntity(false)
132             .storedAt("module-a_EntityA")
133             .aSideStoredAt("module-a_EntityA")
134             .bSideStoredAt("module-b_EntityB")
135             .moduleReferenceName("").build()),
136         List.of(Relationship.builder().name("ManyToMany")
137             .aSideAssociationName("used-EntityB")
138             .aSideMOType("EntityA")
139             .aSideModule("module-a")
140             .aSideMinCardinality(0)
141             .aSideMaxCardinality(100)
142             .bSideAssociationName("used-by-EntityA")
143             .bSideMOType("EntityB")
144             .bSideModule("module-b")
145             .bSideMinCardinality(0)
146             .bSideMaxCardinality(100)
147             .relationshipDataLocation("RELATION")
148             .associationKind("BI_DIRECTIONAL")
149             .connectSameEntity(false)
150             .storedAt("module-a-b_ManyToMany")
151             .aSideStoredAt("module-a_EntityA")
152             .bSideStoredAt("module-b_EntityB")
153             .moduleReferenceName("module-a-b").build()),
154         // Relationship connecting same entity 1:1
155         List.of(Relationship.builder().name("relationshipConnectingSameEntity")
156             .aSideAssociationName("used-EntityA")
157             .aSideMOType("EntityA")
158             .aSideModule("module-a")
159             .aSideMinCardinality(0)
160             .aSideMaxCardinality(1)
161             .bSideAssociationName("used-by-EntityA")
162             .bSideMOType("EntityA")
163             .bSideModule("module-a")
164             .bSideMinCardinality(0)
165             .bSideMaxCardinality(1)
166             .relationshipDataLocation("RELATION")
167             .associationKind("BI_DIRECTIONAL")
168             .connectSameEntity(false)
169             .storedAt("module-a_relationshipConnectingSameEntity")
170             .aSideStoredAt("module-a_EntityA")
171             .bSideStoredAt("module-a_EntityA")
172             .moduleReferenceName("module-a").build()),
173         // Relationship connecting same entity 1:N
174         List.of(Relationship.builder().name("relationshipConnectingSameEntity")
175             .aSideAssociationName("used-EntityA")
176             .aSideMOType("EntityA")
177             .aSideModule("module-a")
178             .aSideMinCardinality(0)
179             .aSideMaxCardinality(1)
180             .bSideAssociationName("used-by-EntityA")
181             .bSideMOType("EntityA")
182             .bSideModule("module-a")
183             .bSideMinCardinality(0)
184             .bSideMaxCardinality(100)
185             .relationshipDataLocation("RELATION")
186             .associationKind("BI_DIRECTIONAL")
187             .connectSameEntity(false)
188             .storedAt("module-a_relationshipConnectingSameEntity")
189             .aSideStoredAt("module-a_EntityA")
190             .bSideStoredAt("module-a_EntityA")
191             .moduleReferenceName("module-a").build()),
192         // Relationship connecting same entity N:1
193         List.of(Relationship.builder().name("relationshipConnectingSameEntity")
194             .aSideAssociationName("used-EntityA")
195             .aSideMOType("EntityA")
196             .aSideModule("module-a")
197             .aSideMinCardinality(0)
198             .aSideMaxCardinality(100)
199             .bSideAssociationName("used-by-EntityA")
200             .bSideMOType("EntityA")
201             .bSideModule("module-a")
202             .bSideMinCardinality(0)
203             .bSideMaxCardinality(1)
204             .relationshipDataLocation("RELATION")
205             .associationKind("BI_DIRECTIONAL")
206             .connectSameEntity(false)
207             .storedAt("module-a_relationshipConnectingSameEntity")
208             .aSideStoredAt("module-a_EntityA")
209             .bSideStoredAt("module-a_EntityA")
210             .moduleReferenceName("module-a").build()),
211         // Relationship connecting same entity N:M
212         List.of(Relationship.builder().name("relationshipConnectingSameEntity")
213             .aSideAssociationName("used-EntityA")
214             .aSideMOType("EntityA")
215             .aSideModule("module-a")
216             .aSideMinCardinality(0)
217             .aSideMaxCardinality(100)
218             .bSideAssociationName("used-by-EntityA")
219             .bSideMOType("EntityA")
220             .bSideModule("module-a")
221             .bSideMinCardinality(0)
222             .bSideMaxCardinality(100)
223             .relationshipDataLocation("RELATION")
224             .associationKind("BI_DIRECTIONAL")
225             .connectSameEntity(false)
226             .storedAt("module-a_relationshipConnectingSameEntity")
227             .aSideStoredAt("module-a_EntityA")
228             .bSideStoredAt("module-a_EntityA")
229             .moduleReferenceName("module-a").build()));
230     //spotless:on
231
232     @Test
233     void checkOneToOneRelationshipMappingTest() {
234
235         //spotless:off
236
237         // Given
238         List<Table> expectedResult = List.of(Table.builder().name("module-a_EntityA").columns(
239                 List.of(
240                     Column.builder().name("azimuth").dataType("DECIMAL").build(),
241                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-a_EntityA_id")
242                         .tableName("module-a_EntityA").columnToAddConstraintTo("id").build())).build(),
243                     Column.builder().name("sectorId").dataType("jsonb").build(),
244                     Column.builder().name("geo-location").dataType("geography").build(),
245                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
246                     Column.builder().name("REL_FK_used-EntityB").dataType("TEXT")
247                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_MODULE-A_ENTITYA_REL_FK_USED-ENTITYB").tableName("module-a_EntityA")
248                             .referencedTable("module-b_EntityB").columnToAddConstraintTo("REL_FK_used-EntityB").build())).build(),
249                     Column.builder().name("REL_ID_oneToOne").dataType("TEXT")
250                         .postgresConstraints(List.of(UniqueConstraint.builder().constraintName("UNIQUE_MODULE-A_ENTITYA_REL_ID_ONETOONE").tableName("module-a_EntityA")
251                             .columnToAddConstraintTo("REL_ID_oneToOne").build())).build(),
252                     Column.builder().name("REL_CD_sourceIds_oneToOne").dataType("jsonb").defaultValue("[]").build(),
253                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType(JSONB).defaultValue("[]").build(),
254                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType(JSONB).defaultValue("{}").build(),
255                     Column.builder().name(String.format("REL_CD_%s_oneToOne", CLASSIFIERS)).dataType(JSONB).defaultValue("[]").build(),
256                     Column.builder().name(String.format("REL_CD_%s_oneToOne", DECORATORS)).dataType(JSONB).defaultValue("{}").build())).build(),
257
258             Table.builder().name("module-b_EntityB").columns(
259                 List.of(
260                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-b_EntityB_id")
261                         .tableName("module-b_EntityB").columnToAddConstraintTo("id").build())).build(),
262                     Column.builder().name("name").dataType("TEXT").build(),
263                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
264                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
265                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build());
266
267         //spotless:on
268
269         // When
270         List<Table> actualResult = tableBuilder.getTables(entities, relationships.get(0));
271
272         // Then
273         runTest(actualResult, expectedResult);
274     }
275
276     @Test
277     void checkOneToManyRelationshipMappingTest() {
278
279         //spotless:off
280
281         // Given
282         List<Table> expectedResult = List.of(Table.builder().name("module-a_EntityA").columns(
283                 List.of(
284                     Column.builder().name("azimuth").dataType("DECIMAL").build(),
285                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-a_EntityA_id")
286                         .tableName("module-a_EntityA").columnToAddConstraintTo("id").build())).build(),
287                     Column.builder().name("sectorId").dataType("jsonb").build(),
288                     Column.builder().name("geo-location").dataType("geography").build(),
289                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
290                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
291                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build(),
292
293             Table.builder().name("module-b_EntityB").columns(
294                 List.of(
295                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-b_EntityB_id")
296                         .tableName("module-b_EntityB").columnToAddConstraintTo("id").build())).build(),
297                     Column.builder().name("name").dataType("TEXT").build(),
298                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
299                     Column.builder().name("REL_FK_used-by-EntityA").dataType("TEXT")
300                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_module-b_EntityB_REL_FK_used-by-EntityA")
301                             .tableName("module-b_EntityB").referencedTable("module-a_EntityA").columnToAddConstraintTo("REL_FK_used-by-EntityA").build())).build(),
302                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
303                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build(),
304                     Column.builder().name("REL_ID_oneToMany").dataType("TEXT")
305                         .postgresConstraints(List.of(UniqueConstraint.builder().constraintName("UNIQUE_module-b_EntityB_REL_ID_oneToMany").tableName("module-b_EntityB")
306                             .columnToAddConstraintTo("REL_ID_oneToMany").build())).build(),
307                     Column.builder().name("REL_CD_sourceIds_oneToMany").dataType("jsonb").defaultValue("[]").build(),
308                     Column.builder().name(String.format("REL_CD_%s_oneToMany", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
309                     Column.builder().name(String.format("REL_CD_%s_oneToMany", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build());
310         //spotless:on
311
312         // When
313         List<Table> actualResult = tableBuilder.getTables(entities, relationships.get(1));
314
315         // Then
316         runTest(actualResult, expectedResult);
317
318     }
319
320     @Test
321     void checkManyToOneRelationshipMappingTest() {
322
323         //spotless:off
324
325         // Given
326         List<Table> expectedResult = List.of(Table.builder().name("module-a_EntityA").columns(
327
328                 List.of(
329                     Column.builder().name("azimuth").dataType("DECIMAL").build(),
330                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-a_EntityA_id")
331                         .tableName("module-a_EntityA").columnToAddConstraintTo("id").build())).build(),
332                     Column.builder().name("sectorId").dataType("jsonb").build(),
333                     Column.builder().name("geo-location").dataType("geography").build(),
334                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
335                     Column.builder().name("REL_FK_used-EntityB").dataType("TEXT")
336                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_MODULE-A_ENTITYA_REL_FK_USED-ENTITYB").tableName("module-a_EntityA")
337                             .referencedTable("module-b_EntityB").columnToAddConstraintTo("REL_FK_used-EntityB").build())).build(),
338                     Column.builder().name("REL_ID_ManyToOne").dataType("TEXT")
339                         .postgresConstraints(List.of(UniqueConstraint.builder().constraintName("UNIQUE_MODULE-A_ENTITYA_REL_ID_MANYTOONE").tableName("module-a_EntityA")
340                             .columnToAddConstraintTo("REL_ID_ManyToOne").build())).build(),
341                     Column.builder().name("REL_CD_sourceIds_ManyToOne").dataType("jsonb").defaultValue("[]").build(),
342                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType(JSONB).defaultValue("[]").build(),
343                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType(JSONB).defaultValue("{}").build(),
344                     Column.builder().name(String.format("REL_CD_%s_ManyToOne", CLASSIFIERS)).dataType(JSONB).defaultValue("[]").build(),
345                     Column.builder().name(String.format("REL_CD_%s_ManyToOne", DECORATORS)).dataType(JSONB).defaultValue("{}").build())).build(),
346
347             Table.builder().name("module-b_EntityB").columns(
348                 List.of(
349                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-b_EntityB_id")
350                         .tableName("module-b_EntityB").columnToAddConstraintTo("id").build())).build(),
351                     Column.builder().name("name").dataType("TEXT").build(),
352                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
353                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
354                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build());
355         //spotless:on
356
357         // When
358         List<Table> actualResult = tableBuilder.getTables(entities, relationships.get(2));
359
360         // Then
361         runTest(actualResult, expectedResult);
362
363     }
364
365     @Test
366     void checkManyToManyRelationshipMappingTest() {
367         //spotless:off
368         // Given
369         List<Table> expectedResult = List.of(Table.builder().name("module-a_EntityA").columns(
370                 List.of(
371                     Column.builder().name("azimuth").dataType("DECIMAL").build(),
372                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-a_EntityA_id")
373                         .tableName("module-a_EntityA").columnToAddConstraintTo("id").build())).build(),
374                     Column.builder().name("sectorId").dataType("jsonb").build(),
375                     Column.builder().name("geo-location").dataType("geography").build(),
376                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
377                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
378                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build(),
379
380             Table.builder().name("module-b_EntityB").columns(
381                 List.of(
382                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-b_EntityB_id")
383                         .tableName("module-b_EntityB").columnToAddConstraintTo("id").build())).build(),
384                     Column.builder().name("name").dataType("TEXT").build(),
385                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
386                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
387                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build(),
388
389             Table.builder().name("module-a-b_ManyToMany").columns(
390                 List.of(
391                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-a-b_ManyToMany_id")
392                         .tableName("module-a-b_ManyToMany").columnToAddConstraintTo("id").build())).build(),
393                     Column.builder().name("aSide_EntityA").dataType("TEXT")
394                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_module-a-b_ManyToMany_aSide_EntityA")
395                             .tableName("module-a-b_ManyToMany").referencedTable("module-a_EntityA").columnToAddConstraintTo("aSide_EntityA").build())).build(),
396                     Column.builder().name("bSide_EntityB").dataType("TEXT")
397                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_module-a-b_manyToMany_bSide_EntityB")
398                             .tableName("module-a-b_ManyToMany").referencedTable("module-b_EntityB").columnToAddConstraintTo("bSide_EntityB").build())).build(),
399                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
400                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
401                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build());
402         //spotless:on
403
404         // When
405         List<Table> actualResult = tableBuilder.getTables(entities, relationships.get(3));
406
407         // Then
408         runTest(actualResult, expectedResult);
409     }
410
411     @Test
412     void checkRelationshipConnectingSameEntityMappingTest() {
413         //spotless:off
414         List<Entity> sameEntities = List.of(
415
416             Entity.builder().entityName("EntityA").storedAt("module-a_EntityA").attributes(
417                     List.of(
418                         Attribute.builder().name("azimuth").dataType("DECIMAL").build(),
419                         Attribute.builder().name("id").dataType("TEXT").constraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_Sector_id")
420                             .tableName("Sector").columnToAddConstraintTo("id").build())).build(),
421                         Attribute.builder().name("geo-location").dataType("geography").build(),
422                         Attribute.builder().name("sectorId").dataType("jsonb").build()))
423                 .moduleReferenceName("")
424                 .build());
425
426         // Given
427         List<Table> expectedResult = List.of(Table.builder().name("module-a_EntityA").columns(
428                 List.of(
429                     Column.builder().name("azimuth").dataType("DECIMAL").build(),
430                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder().constraintName("PK_module-a_EntityA_id")
431                         .tableName("module-a_EntityA").columnToAddConstraintTo("id").build())).build(),
432                     Column.builder().name("sectorId").dataType("jsonb").build(),
433                     Column.builder().name("geo-location").dataType("geography").build(),
434                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
435                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
436                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build(),
437
438             Table.builder().name("module-a_relationshipConnectingSameEntity").columns(
439                 List.of(
440                     Column.builder().name("id").dataType("TEXT").postgresConstraints(List.of(PrimaryKeyConstraint.builder()
441                         .constraintName("PK_module-a_relationshipConnectingSameEntity_id").tableName("module-a_relationshipConnectingSameEntity").columnToAddConstraintTo("id")
442                         .build())).build(),
443                     Column.builder().name("aSide_EntityA").dataType("TEXT")
444                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_module-a_relationshipConnectingSameEntity_aSide_EntityA")
445                             .tableName("module-a_relationshipConnectingSameEntity").referencedTable("module-a_EntityA").columnToAddConstraintTo("aSide_EntityA").build())).build(),
446                     Column.builder().name("bSide_EntityA").dataType("TEXT")
447                         .postgresConstraints(List.of(ForeignKeyConstraint.builder().constraintName("FK_module-a_relationshipConnectingSameEntity_bSide_EntityA")
448                             .tableName("module-a_relationshipConnectingSameEntity").referencedTable("module-a_EntityA").columnToAddConstraintTo("bSide_EntityA").build())).build(),
449                     Column.builder().name("CD_sourceIds").dataType("jsonb").defaultValue("[]").build(),
450                     Column.builder().name(String.format("CD_%s", CLASSIFIERS)).dataType("jsonb").defaultValue("[]").build(),
451                     Column.builder().name(String.format("CD_%s", DECORATORS)).dataType("jsonb").defaultValue("{}").build())).build());
452         //spotless:on
453
454         // When
455         List<Table> actualResultOneToOne = tableBuilder.getTables(sameEntities, relationships.get(4));
456         List<Table> actualResultOneToMany = tableBuilder.getTables(sameEntities, relationships.get(5));
457         List<Table> actualResultManyToOne = tableBuilder.getTables(sameEntities, relationships.get(6));
458         List<Table> actualResultManyToMany = tableBuilder.getTables(sameEntities, relationships.get(7));
459
460         // Then
461         // Test relationship connecting same entity (one to one)
462         runTest(actualResultOneToOne, expectedResult);
463
464         // Test relationship connecting same entity (one to many)
465         runTest(actualResultOneToMany, expectedResult);
466
467         // Test relationship connecting same entity (many to one)
468         runTest(actualResultManyToOne, expectedResult);
469
470         // Test relationship connecting same entity (many to many)
471         runTest(actualResultManyToMany, expectedResult);
472
473     }
474
475     void runTest(List<Table> generatedTables, List<Table> expectedTables) {
476
477         List<String> allTableNamesFromGeneratedResult = TestHelper.extractTableNames(generatedTables);
478         List<String> allTableNamesFromExpectedResult = TestHelper.extractTableNames(expectedTables);
479
480         // Check if generatedResult contains all tables
481         Assertions.assertEquals(allTableNamesFromExpectedResult, allTableNamesFromGeneratedResult);
482
483         //spotless:off
484         expectedTables.forEach(expectedTable -> {
485             generatedTables.stream().filter(generatedTable -> generatedTable.getName().equals(expectedTable.getName())).findFirst()
486                 .ifPresent(generatedTable -> {
487                     List<Column> columnsInExpected = expectedTable.getColumns();
488                     List<Column> columnsInGenerated = generatedTable.getColumns();
489
490                     // Check if all columns for each table were added correctly
491                     Assertions.assertEquals(columnsInExpected.size(), columnsInGenerated.size());
492
493                     List<String> allColumnNamesForATableInGeneratedResult = TestHelper.extractColumnNames(columnsInGenerated);
494                     List<String> allColumnNamesForATableInExpectedResult = TestHelper.extractColumnNames(columnsInExpected);
495
496                     // Check if generatedResult contains all columns for a table
497                     Assertions.assertEquals(allColumnNamesForATableInExpectedResult, allColumnNamesForATableInGeneratedResult);
498
499                     columnsInExpected.forEach(columnInExpected -> {
500                         columnsInGenerated.stream().filter(columnInGenerated -> columnInGenerated.getName().equals(columnInExpected.getName()))
501                             .findFirst().ifPresent(columnInGenerated -> {
502
503                                 if (columnInExpected.getName().equals("id")) {
504                                     Assertions.assertEquals("TEXT", columnInGenerated.getDataType());
505                                     Assertions.assertTrue(TestHelper.checkIfColumnIsPrimaryKey(columnInGenerated.getPostgresConstraints()));
506                                 }
507
508                                 // Check if each attributes' datatype is picked correctly
509                                 Assertions.assertEquals(columnInExpected.getDataType().replace("\"", ""), columnInGenerated.getDataType());
510
511                                 // Check if each attributes' default value is picked correctly
512                                 Assertions.assertEquals(columnInExpected.getDefaultValue(), columnInGenerated.getDefaultValue());
513
514                                 if (!columnInExpected.getPostgresConstraints().isEmpty()) {
515
516                                     Assertions.assertEquals(columnInExpected.getPostgresConstraints().size(), columnInGenerated.getPostgresConstraints().size());
517
518                                     List<String> expectedConstraintNames = TestHelper.extractConstraintName(columnInExpected.getPostgresConstraints());
519                                     List<String> actualConstraintNames = TestHelper.extractConstraintName(columnInGenerated.getPostgresConstraints());
520
521                                     // Check if constraint names in expected result match with those in actual result
522                                     Assertions.assertEquals(expectedConstraintNames, actualConstraintNames);
523
524                                     columnInExpected.getPostgresConstraints().forEach(constraint -> {
525                                         columnInGenerated.getPostgresConstraints().stream()
526                                             .filter(constraint1 -> constraint1.getConstraintName().equals(constraint.getConstraintName())).findFirst()
527                                             .ifPresent(constraint1 -> {
528
529                                                 // Check table name where constraint is to be added
530                                                 Assertions.assertEquals(constraint.getTableToAddConstraintTo(), constraint1.getTableToAddConstraintTo());
531
532                                                 // Check column where constraint is to be added
533                                                 Assertions.assertEquals(constraint.getColumnToAddConstraintTo(), constraint1.getColumnToAddConstraintTo());
534
535                                                 if (constraint instanceof ForeignKeyConstraint expectedFk) {
536                                                     ForeignKeyConstraint actualFK = (ForeignKeyConstraint) constraint1;
537
538                                                     Assertions.assertEquals(expectedFk.getReferencedTable(), actualFK.getReferencedTable());
539                                                 }
540                                             });
541                                     });
542                                 }
543                             });
544                     });
545                 });
546         });
547         //spotless:on
548     }
549 }