11package org .ngbsn .generator ;
22
3- import org .apache .commons .text .CaseUtils ;
4- import org .apache .commons .text .WordUtils ;
53import org .ngbsn .model .Column ;
6- import org .ngbsn .model .EmbeddableClass ;
74import org .ngbsn .model .ForeignKeyConstraint ;
85import org .ngbsn .model .Table ;
9- import org .ngbsn .model .annotations .fieldAnnotations .*;
106
11- import java .util .HashSet ;
127import java .util .List ;
138import java .util .Optional ;
14- import java .util .Set ;
15- import java .util .stream .Collectors ;
16- import java .util .stream .Stream ;
179
18- import static org .ngbsn .generator .ModelGenerator .tablesMap ;
10+ import static org .ngbsn .generator .BiDirectionalMappingsGenerator .addBiDirectionalMappings ;
11+ import static org .ngbsn .generator .UniDirectionalMappingsGenerator .addBothSideUniDirectionalMappings ;
1912
2013/**
2114 * This class contains logic for generating all the association mappings
@@ -29,7 +22,7 @@ public static void generateMappings(final Table table) {
2922 //Case: There is only 1 Foreign key or 1 Composite Foreign Key
3023 //Treat this as a regular table and add a new column with for parent field with @ManyToOne
3124 //and add a new column in ReferencedTable for child field with @OneToMany
32- addBothUnidirectionalMappings (table , foreignKeyConstraintList .get (0 ));
25+ addBothSideUniDirectionalMappings (table , foreignKeyConstraintList .get (0 ));
3326
3427 } else {
3528 //Case: There are multiple Foreign Keys or multiple Composite Foreign Keys
@@ -39,146 +32,17 @@ public static void generateMappings(final Table table) {
3932 if (optionalKey .isEmpty () && foreignKeyConstraintList .size () == 2 ) {
4033 //Case: All fields are foreign keys. Also, the relation exits between 2 entities only
4134 //Remove this link entity from the tablesMap as separate entity is not needed to track Link Table. Use @ManyToMany on other 2 entities
42- tablesMap .remove (table .getTableName ());
43- Table table1 = tablesMap .get (foreignKeyConstraintList .get (0 ).getReferencedTableName ());
44- Table table2 = tablesMap .get (foreignKeyConstraintList .get (1 ).getReferencedTableName ());
45-
46- //Adding @ManyToMany and @JoinTable to table1
47- Column column1 = new Column ();
48- column1 .setFieldName (CaseUtils .toCamelCase (table2 .getTableName (), false , '_' ));
49- column1 .setType (table2 .getClassName ());
50- column1 .getAnnotations ().add (ManyToManyAnnotation .builder ().build ().toString ());
51- Set <JoinColumnAnnotation > joinColumnAnnotations = new HashSet <>();
52- for (String column : foreignKeyConstraintList .get (0 ).getColumns ()) {
53- joinColumnAnnotations .add (JoinColumnAnnotation .builder ().name (column ).build ());
54- }
55- Set <JoinColumnAnnotation > joinInverseColumnAnnotations = new HashSet <>();
56- for (String column : foreignKeyConstraintList .get (1 ).getColumns ()) {
57- joinInverseColumnAnnotations .add (JoinColumnAnnotation .builder ().name (column ).build ());
58- }
59- column1 .getAnnotations ().add (JoinTableAnnotation .builder ().tableName (table .getTableName ()).joinColumns (joinColumnAnnotations ).inverseJoinColumns (joinInverseColumnAnnotations ).build ().toString ());
60- table1 .getColumns ().add (column1 );
61-
62- //Adding @ManyToMany(mappedBy) to table2
63- Column column2 = new Column ();
64- column2 .setFieldName (CaseUtils .toCamelCase (table1 .getTableName (), false , '_' ));
65- column2 .setType (table1 .getClassName ());
66- column2 .getAnnotations ().add (ManyToManyAnnotation .builder ().mappedBy (column1 .getFieldName ()).build ().toString ());
67- table2 .getColumns ().add (column2 );
35+ addBiDirectionalMappings (table , foreignKeyConstraintList );
6836
6937 } else {
7038 //Case1: There are some fields that are not foreign keys. So separate entity is needed to track Link Table
7139 //Case2: All fields are foreign keys. But, the relation exits between 2 or more entities
7240 //Add @ManyToOne for each foreignKey and corresponding @OneToMany in referenced Table
7341 foreignKeyConstraintList .forEach (foreignKeyConstraint -> {
74- addBothUnidirectionalMappings (table , foreignKeyConstraint );
42+ addBothSideUniDirectionalMappings (table , foreignKeyConstraint );
7543 });
7644 }
7745 }
7846
7947 }
80-
81- /**
82- * This method will handle each foreign key constraint in the table.
83- *
84- * @param table table
85- * @param foreignKeyConstraint foreignKeyConstraint
86- */
87- private static void addBothUnidirectionalMappings (Table table , ForeignKeyConstraint foreignKeyConstraint ) {
88- Table referencedTable = tablesMap .get (foreignKeyConstraint .getReferencedTableName ());
89- //In the Child table, create a new column having field name as Parent(Referenced) Table.
90- Column parentTableField = new Column ();
91- parentTableField .setFieldName (CaseUtils .toCamelCase (referencedTable .getTableName (), false , '_' ));
92- parentTableField .setType (referencedTable .getClassName ());
93- parentTableField .getAnnotations ().add (new ManyToOneAnnotation ().toString ());
94- table .getColumns ().add (parentTableField );
95-
96- //In the Parent(Referenced) table, create a new column having field name as child Table.
97- Column childTableField = new Column ();
98- childTableField .setFieldName (CaseUtils .toCamelCase (table .getTableName (), false , '_' ));
99- childTableField .setType ("Set<" + table .getClassName () + ">" );
100- childTableField .getAnnotations ().add (OneToManyAnnotation .builder ().mappedBy (parentTableField .getFieldName ()).build ().toString ());
101- referencedTable .getColumns ().add (childTableField );
102-
103- //get EmbeddedId for this table
104- Optional <EmbeddableClass > optionalEmbeddableId = table .getEmbeddableClasses ().stream ().filter (EmbeddableClass ::isEmbeddedId ).findFirst ();
105- EmbeddableClass embeddableId = optionalEmbeddableId .orElse (null );
106- Set <Column > allPrimaryKeyColumns = getAllPrimaryKeys (table , embeddableId ); //get all primary keys
107-
108- //Case: Composite Foreign key
109- if (foreignKeyConstraint .getColumns ().size () > 1 ) {
110- Set <Column > setOfForeignKeyColumns = setOfForeignKeys (table , foreignKeyConstraint );
111- //If composite foreign key is inside the composite primary key, don't remove them from table.
112- //This case assumes there is a primary composite key
113- //Add a @MapsId annotation to the referenced table field
114- if (embeddableId != null && allPrimaryKeyColumns .containsAll (setOfForeignKeyColumns )) {
115- EmbeddableClass foreignCompositeKeyEmbedded = new EmbeddableClass (); //Create a new embeddable for this foreign composite key
116- String embeddableName = setOfForeignKeyColumns .stream ().map (Column ::getFieldName ).collect (Collectors .joining ());
117- foreignCompositeKeyEmbedded .setClassName (WordUtils .capitalize (embeddableName ));
118- foreignCompositeKeyEmbedded .setFieldName (embeddableName );
119- table .getEmbeddableClasses ().add (foreignCompositeKeyEmbedded ); //add new embeddable to the Table list of Embeddables
120- setOfForeignKeyColumns .forEach (column -> {
121- //add the individual foreign keys columns the newly created embeddable
122- foreignCompositeKeyEmbedded .getColumns ().add (column );
123- //Remove the individual foreign keys from EmbeddedId and add the newly created embeddable into EmbeddedId
124- embeddableId .getColumns ().remove (column );
125- });
126- Column foreignCompositeField = new Column ();
127- foreignCompositeField .setType (foreignCompositeKeyEmbedded .getClassName ());
128- foreignCompositeField .setFieldName (foreignCompositeKeyEmbedded .getFieldName ());
129- embeddableId .getColumns ().add (foreignCompositeField );
130-
131- if (embeddableId .getFieldName () != null )
132- parentTableField .getAnnotations ().add (MapsIdAnnotation .builder ().fieldName (foreignCompositeField .getFieldName ()).build ().toString ());
133- } else {
134- //There is no primary Composite key
135- //If composite foreign key is not inside the composite primary key, then remove it from the table
136- setOfForeignKeyColumns .forEach (column -> table .getColumns ().remove (column ));
137- }
138-
139- Set <JoinColumnAnnotation > joinColumns = new HashSet <>();
140- //Create the @JoinColumn annotations for the parentTableField
141- for (int i = 0 ; i < foreignKeyConstraint .getColumns ().size (); i ++) {
142- JoinColumnAnnotation joinColumnAnnotation = JoinColumnAnnotation .builder ().name (foreignKeyConstraint .getColumns ().get (i )).referencedColumnName (foreignKeyConstraint .getReferencedColumns ().get (i )).build ();
143- joinColumns .add (joinColumnAnnotation );
144- }
145- parentTableField .getAnnotations ().add (JoinColumnsAnnotation .builder ().joinColumns (joinColumns ).build ().toString ());
146-
147- }
148- //Case: Single Foreign Key
149- else {
150- //Get the foreign key column from the table
151- Optional <Column > optionalColumn = table .getColumns ().stream ().filter (column -> column .getColumnName () != null && column .getColumnName ().equals (foreignKeyConstraint .getReferencedColumns ().get (0 ))).findFirst ();
152- if (optionalColumn .isPresent ()) {
153- Column foreignKeyColumn = optionalColumn .get ();
154- //Check if foreign key is also a primary key, by iterating through the primary key list
155- Optional <Column > optionalColumnPrimaryForeign = allPrimaryKeyColumns .stream ().filter (column -> column .getColumnName () != null && column .getColumnName ().equals (foreignKeyColumn .getColumnName ())).findFirst ();
156- optionalColumnPrimaryForeign .ifPresentOrElse (column -> {
157- //If foreign key is a primary key, don't remove it from table.
158- //Add a @MapsId annotation to the referenced table field
159- parentTableField .getAnnotations ().add (MapsIdAnnotation .builder ().fieldName (column .getFieldName ()).build ().toString ());
160- }, () -> {
161- //If foreign key is not a primary key, then remove it from the table
162- optionalColumn .ifPresent (column -> table .getColumns ().remove (column ));
163- });
164- }
165- //Add a @JoinColumn annotation for the referenced table field
166- parentTableField .getAnnotations ().add (JoinColumnAnnotation .builder ().name (foreignKeyConstraint .getReferencedColumns ().get (0 )).referencedColumnName (foreignKeyConstraint .getReferencedColumns ().get (0 )).build ().toString ());
167- }
168- }
169-
170- private static Set <Column > setOfForeignKeys (Table table , ForeignKeyConstraint foreignKeyConstraint ) {
171- Stream <Column > allTableForeignKeyColumns = table .getColumns ().stream ();
172- Stream <Column > allEmbeddedForeignKeyColumns = table .getEmbeddableClasses ().stream ().flatMap (embeddableClass -> embeddableClass .getColumns ().stream ());
173- return Stream .concat (allTableForeignKeyColumns , allEmbeddedForeignKeyColumns ).filter (column -> foreignKeyConstraint .getColumns ().stream ().anyMatch (s -> s .equals (column .getColumnName ()))).collect (Collectors .toSet ());
174- }
175-
176- private static Set <Column > getAllPrimaryKeys (Table table , EmbeddableClass embeddableId ) {
177- //Get set of primary Keys
178- if (embeddableId != null ){
179- return embeddableId .getColumns ().stream ().filter (Column ::isPrimaryKey ).collect (Collectors .toSet ());
180- }else {
181- return table .getColumns ().stream ().filter (Column ::isPrimaryKey ).collect (Collectors .toSet ());
182- }
183- }
18448}
0 commit comments