001package io.ebeaninternal.dbmigration.model; 002 003import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp; 004import io.ebeaninternal.dbmigration.migration.AlterForeignKey; 005import io.ebeaninternal.dbmigration.migration.ForeignKey; 006 007import java.util.ArrayList; 008import java.util.List; 009import java.util.Objects; 010 011/** 012 * A unique constraint for multiple columns. 013 * <p> 014 * Note that unique constraint on a single column is instead 015 * a boolean flag on the associated MColumn. 016 * </p> 017 */ 018public class MCompoundForeignKey { 019 020 private String name; 021 private final String referenceTable; 022 private final List<String> columns = new ArrayList<>(); 023 private final List<String> referenceColumns = new ArrayList<>(); 024 private String indexName; 025 026 public MCompoundForeignKey(String name, String referenceTable, String indexName) { 027 this.name = name; 028 this.referenceTable = referenceTable; 029 this.indexName = indexName; 030 } 031 032 /** 033 * Add a column pair of local and referenced column. 034 */ 035 public void addColumnPair(String dbCol, String refColumn) { 036 columns.add(dbCol); 037 referenceColumns.add(refColumn); 038 } 039 040 /** 041 * Create and return an ForeignKey migration element. 042 */ 043 public ForeignKey createForeignKey() { 044 ForeignKey fk = new ForeignKey(); 045 fk.setName(name); 046 fk.setIndexName(indexName); 047 fk.setColumnNames(toColumnNames(columns)); 048 fk.setRefColumnNames(toColumnNames(referenceColumns)); 049 fk.setRefTableName(referenceTable); 050 return fk; 051 } 052 053 /** 054 * Create and return an AlterForeignKey migration element. 055 */ 056 public AlterForeignKey addForeignKey(String tableName) { 057 AlterForeignKey fk = new AlterForeignKey(); 058 fk.setName(name); 059 fk.setIndexName(indexName); 060 fk.setColumnNames(toColumnNames(columns)); 061 fk.setRefColumnNames(toColumnNames(referenceColumns)); 062 fk.setRefTableName(referenceTable); 063 fk.setTableName(tableName); 064 return fk; 065 } 066 067 /** 068 * Create and return an AlterForeignKey migration element. 069 */ 070 public AlterForeignKey dropForeignKey(String tableName) { 071 AlterForeignKey fk = new AlterForeignKey(); 072 fk.setName(name); 073 fk.setIndexName(indexName); 074 fk.setColumnNames(DdlHelp.DROP_FOREIGN_KEY); 075 fk.setTableName(tableName); 076 return fk; 077 } 078 079 /** 080 * Add a counter to the foreign key and index names to avoid duplication. 081 */ 082 public void addNameSuffix(int counter) { 083 this.name = name + "_" + counter; 084 this.indexName = indexName + "_" + counter; 085 } 086 087 /** 088 * Return the foreign key name. 089 */ 090 public String getName() { 091 return name; 092 } 093 094 /** 095 * Return the index name. 096 */ 097 public String getIndexName() { 098 return indexName; 099 } 100 101 /** 102 * Return the columns making up the foreign key in order. 103 */ 104 public List<String> getColumns() { 105 return columns; 106 } 107 108 /** 109 * Set the associated index name. Note that setting to null has the effect 110 * of indicating an associated index should not be created for this foreign key. 111 */ 112 public void setIndexName(String indexName) { 113 this.indexName = indexName; 114 } 115 116 /** 117 * Return as an array of string column names. 118 */ 119 private String toColumnNames(List<String> columns) { 120 121 StringBuilder sb = new StringBuilder(40); 122 for (int i = 0; i < columns.size(); i++) { 123 if (i > 0) { 124 sb.append(","); 125 } 126 sb.append(columns.get(i)); 127 } 128 return sb.toString(); 129 } 130 131 @Override 132 public int hashCode() { 133 return Objects.hash(columns, indexName, name, referenceColumns, referenceTable); 134 } 135 136 @Override 137 public boolean equals(Object obj) { 138 if (this == obj) 139 return true; 140 if (!(obj instanceof MCompoundForeignKey)) 141 return false; 142 143 MCompoundForeignKey other = (MCompoundForeignKey) obj; 144 return Objects.equals(columns, other.columns) 145 && Objects.equals(indexName, other.indexName) 146 && Objects.equals(name, other.name) 147 && Objects.equals(referenceColumns, other.referenceColumns) 148 && Objects.equals(referenceTable, other.referenceTable); 149 } 150 151}