001package io.ebeaninternal.dbmigration.model; 002 003import io.ebeaninternal.dbmigration.migration.CreateIndex; 004import io.ebeaninternal.dbmigration.migration.DropIndex; 005 006import java.util.ArrayList; 007import java.util.Collections; 008import java.util.List; 009import java.util.Objects; 010 011/** 012 * Index as part of the logical model. 013 */ 014public class MIndex { 015 016 private String tableName; 017 private String indexName; 018 private String platforms; 019 private List<String> columns = new ArrayList<>(); 020 private boolean unique; 021 private boolean concurrent; 022 private String definition; 023 024 /** 025 * Create a single column non unique index. 026 */ 027 public MIndex(String indexName, String tableName, String columnName) { 028 this.tableName = tableName; 029 this.indexName = indexName; 030 this.columns.add(columnName); 031 } 032 033 /** 034 * Create a multi column non unique index. 035 */ 036 public MIndex(String indexName, String tableName, String[] columnNames) { 037 this.tableName = tableName; 038 this.indexName = indexName; 039 Collections.addAll(this.columns, columnNames); 040 } 041 042 public MIndex(String indexName, String tableName, String[] columnNames, String platforms, boolean unique, boolean concurrent, String definition) { 043 this(indexName, tableName, columnNames); 044 this.platforms = platforms; 045 this.unique = unique; 046 this.concurrent = concurrent; 047 this.definition = emptyToNull(definition); 048 } 049 050 public MIndex(CreateIndex createIndex) { 051 this.indexName = createIndex.getIndexName(); 052 this.tableName = createIndex.getTableName(); 053 this.columns = split(createIndex.getColumns()); 054 this.platforms = createIndex.getPlatforms(); 055 this.unique = Boolean.TRUE.equals(createIndex.isUnique()); 056 this.concurrent = Boolean.TRUE.equals(createIndex.isConcurrent()); 057 this.definition = emptyToNull(createIndex.getDefinition()); 058 } 059 060 public String getKey() { 061 // currently indexName should be unique (not indexName + platforms) 062 return indexName; 063 } 064 065 /** 066 * Return the index name. 067 */ 068 public String getIndexName() { 069 return indexName; 070 } 071 072 /** 073 * Return the table this index is on. 074 */ 075 public String getTableName() { 076 return tableName; 077 } 078 079 /** 080 * Return the columns in the index (in order). 081 */ 082 public List<String> getColumns() { 083 return columns; 084 } 085 086 /** 087 * Return a CreateIndex migration for this index. 088 */ 089 public CreateIndex createIndex() { 090 CreateIndex create = new CreateIndex(); 091 create.setIndexName(indexName); 092 create.setTableName(tableName); 093 create.setColumns(join()); 094 create.setPlatforms(platforms); 095 if (Boolean.TRUE.equals(unique)) { 096 create.setUnique(Boolean.TRUE); 097 } 098 if (Boolean.TRUE.equals(concurrent)) { 099 create.setConcurrent(Boolean.TRUE); 100 } 101 create.setDefinition(emptyToNull(definition)); 102 return create; 103 } 104 105 private String emptyToNull(String val) { 106 if (val == null || val.isEmpty()) { 107 return null; 108 } 109 return val; 110 } 111 112 /** 113 * Create a DropIndex migration for this index. 114 */ 115 public DropIndex dropIndex() { 116 DropIndex dropIndex = new DropIndex(); 117 dropIndex.setIndexName(indexName); 118 dropIndex.setTableName(tableName); 119 dropIndex.setPlatforms(platforms); 120 if (Boolean.TRUE.equals(concurrent)) { 121 dropIndex.setConcurrent(Boolean.TRUE); 122 } 123 return dropIndex; 124 } 125 126 /** 127 * Compare with an index of the same name. 128 */ 129 public void compare(ModelDiff modelDiff, MIndex newIndex) { 130 if (changed(newIndex)) { 131 // drop and recreate the index 132 modelDiff.addDropIndex(dropIndex()); 133 modelDiff.addCreateIndex(newIndex.createIndex()); 134 } 135 } 136 137 /** 138 * Return true if the index has changed. 139 */ 140 private boolean changed(MIndex newIndex) { 141 if (!tableName.equals(newIndex.getTableName())) { 142 return true; 143 } 144 if (unique != newIndex.unique) { 145 return true; 146 } 147 if (!Objects.equals(definition, newIndex.definition)) { 148 return true; 149 } 150 List<String> newColumns = newIndex.getColumns(); 151 if (columns.size() != newColumns.size()) { 152 return true; 153 } 154 for (int i = 0; i < columns.size(); i++) { 155 if (!columns.get(i).equals(newColumns.get(i))) { 156 return true; 157 } 158 } 159 return false; 160 } 161 162 163 private List<String> split(String columns) { 164 if (columns.isEmpty()) { 165 return Collections.emptyList(); 166 } 167 String[] cols = columns.split(","); 168 List<String> colList = new ArrayList<>(cols.length); 169 Collections.addAll(colList, cols); 170 return colList; 171 } 172 173 private String join() { 174 StringBuilder sb = new StringBuilder(50); 175 for (int i = 0; i < columns.size(); i++) { 176 if (i > 0) { 177 sb.append(","); 178 } 179 sb.append(columns.get(i)); 180 } 181 return sb.toString(); 182 } 183 184}