1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.common.impex.model.util;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.apache.commons.lang3.StringUtils;
24 import org.kuali.common.impex.model.Column;
25 import org.kuali.common.impex.model.ForeignKey;
26 import org.kuali.common.impex.model.Index;
27 import org.kuali.common.impex.model.NamedElement;
28 import org.kuali.common.impex.model.Schema;
29 import org.kuali.common.impex.model.Sequence;
30 import org.kuali.common.impex.model.Table;
31 import org.kuali.common.impex.model.UniqueConstraint;
32 import org.kuali.common.impex.model.View;
33 import org.kuali.common.impex.model.compare.ColumnDifference;
34 import org.kuali.common.impex.model.compare.ForeignKeyDifference;
35 import org.kuali.common.impex.model.compare.ForeignKeyDifferenceType;
36 import org.kuali.common.impex.model.compare.IndexDifference;
37 import org.kuali.common.impex.model.compare.MissingColumn;
38 import org.kuali.common.impex.model.compare.MissingForeignKey;
39 import org.kuali.common.impex.model.compare.MissingIndex;
40 import org.kuali.common.impex.model.compare.MissingSequence;
41 import org.kuali.common.impex.model.compare.MissingTable;
42 import org.kuali.common.impex.model.compare.MissingUniqueConstraint;
43 import org.kuali.common.impex.model.compare.MissingView;
44 import org.kuali.common.impex.model.compare.SequenceDifference;
45 import org.kuali.common.impex.model.compare.SequenceDifferenceType;
46 import org.kuali.common.impex.model.compare.TableDifference;
47 import org.kuali.common.impex.model.compare.TableDifferenceType;
48 import org.kuali.common.impex.model.compare.UniqueConstraintDifference;
49 import org.kuali.common.impex.model.compare.ViewDifference;
50 import org.kuali.common.impex.model.compare.ViewDifferenceType;
51
52 public class CompareUtils {
53
54 public static final int EXPECTED_MISSING_ELEMENTS_SET_COUNT = 2;
55
56 public static Collection<ColumnDifference> compareColumns(Schema schema1, Table table1, Column col1, Schema schema2, Table table2, Column col2) {
57 Collection<ColumnDifference> results = new ArrayList<ColumnDifference>();
58
59
60 if (col1.getType() != col2.getType()) {
61 ColumnDifference dataTypeDiff = new ColumnDifference(schema1, table1, col1, schema2, table2, col2);
62 dataTypeDiff.setType(TableDifferenceType.COLUMN_DATA_TYPE);
63 results.add(dataTypeDiff);
64 }
65
66
67 if (col1.isPrimaryKey() != col2.isPrimaryKey()) {
68 ColumnDifference pkDiff = new ColumnDifference(schema1, table1, col1, schema2, table2, col2);
69 pkDiff.setType(TableDifferenceType.COLUMN_PRIMARY_KEY);
70 results.add(pkDiff);
71 }
72
73
74 if (col1.isNullable() != col2.isNullable()) {
75 ColumnDifference nullableDiff = new ColumnDifference(schema1, table1, col1, schema2, table2, col2);
76 nullableDiff.setType(TableDifferenceType.COLUMN_NULLABLE);
77 results.add(nullableDiff);
78 }
79
80
81 if(!objectsEqual(col1.getSize(), col2.getSize())) {
82 ColumnDifference sizeDiff = new ColumnDifference(schema1, table1, col1, schema2, table2, col2);
83 sizeDiff.setType(TableDifferenceType.COLUMN_DATA_TYPE_SIZE);
84 results.add(sizeDiff);
85 }
86
87
88 if(!StringUtils.equals(col1.getDescription(), col2.getDescription())) {
89 ColumnDifference descDiff = new ColumnDifference(schema1, table1, col1, schema2, table2, col2);
90 descDiff.setType(TableDifferenceType.COLUMN_DESCRIPTION);
91 results.add(descDiff);
92 }
93
94
95 if (!StringUtils.equals(col1.getDefaultValue(), col2.getDefaultValue())) {
96 ColumnDifference defaultDiff = new ColumnDifference(schema1, table1, col1, schema2, table2, col2);
97 defaultDiff.setType(TableDifferenceType.COLUMN_DEFAULT_VALUE);
98 }
99
100 return results;
101 }
102
103
104 public static <T extends NamedElement> MissingElements<T> determineMissingElements(List<List<T>> sets) {
105
106 MissingElements<T> results = new MissingElements<T>();
107
108 if (sets.size() != EXPECTED_MISSING_ELEMENTS_SET_COUNT) {
109 throw new IllegalArgumentException("Map of sets is expected to have exactly " + EXPECTED_MISSING_ELEMENTS_SET_COUNT + " entries");
110 }
111
112 List<T> set1Elements = sets.get(0);
113 List<T> set2Elements = sets.get(1);
114
115
116 Map<String, T> set2NameMap = ModelUtils.buildNameMap(set2Elements);
117
118
119
120
121 Collection<String> namesInSet2Only = set2NameMap.keySet();
122
123
124 for (T n : set1Elements) {
125
126 if (set2NameMap.containsKey(n.getName())) {
127
128 results.getBoth().add(new MatchingElement<T>(n, set2NameMap.get(n.getName())));
129
130
131 namesInSet2Only.remove(n.getName());
132 }
133
134 else {
135 results.getSet1Only().add(n);
136 }
137 }
138
139
140 for (String name : namesInSet2Only) {
141 results.getSet2Only().add(set2NameMap.get(name));
142 }
143
144 return results;
145 }
146
147
148 public static Collection<UniqueConstraintDifference> compareUniqueConstraints(Schema schema1, Table table1, UniqueConstraint uniqueConstraint1, Schema schema2, Table table2, UniqueConstraint uniqueConstraint2) {
149 Collection<UniqueConstraintDifference> results = new ArrayList<UniqueConstraintDifference>();
150
151 if (!uniqueConstraint1.getColumnNames().equals(uniqueConstraint2.getColumnNames())) {
152 UniqueConstraintDifference diff = new UniqueConstraintDifference(schema1, table1, uniqueConstraint1, schema2, table2, uniqueConstraint2);
153 diff.setType(TableDifferenceType.UNIQUE_CONSTRAINT_COLUMNS);
154 results.add(diff);
155 }
156
157 return results;
158 }
159
160 public static Collection<IndexDifference> compareIndices(Schema schema1, Table table1, Index index1, Schema schema2, Table table2, Index index2) {
161 Collection<IndexDifference> results = new ArrayList<IndexDifference>();
162
163 if (!index1.getColumnNames().equals(index2.getColumnNames())) {
164 IndexDifference diff = new IndexDifference(schema1, table1, index1, schema2, table2, index2);
165 diff.setType(TableDifferenceType.INDEX_COLUMNS);
166 results.add(diff);
167 }
168
169 if (index1.isUnique() != index2.isUnique()) {
170 IndexDifference diff = new IndexDifference(schema1, table1, index1, schema2, table2, index2);
171 diff.setType(TableDifferenceType.INDEX_UNIQUE);
172 results.add(diff);
173 }
174
175 return results;
176 }
177
178 public static Collection<ForeignKeyDifference> compareForeignKeys(Schema schema1, ForeignKey foreignKey1, Schema schema2, ForeignKey foreignKey2) {
179
180 Collection<ForeignKeyDifference> results = new ArrayList<ForeignKeyDifference>();
181
182 if (!StringUtils.equals(foreignKey1.getLocalTableName(), foreignKey2.getLocalTableName())) {
183 ForeignKeyDifference diff = new ForeignKeyDifference(schema1, foreignKey1, schema2, foreignKey2);
184 diff.setType(ForeignKeyDifferenceType.LOCAL_TABLE);
185 results.add(diff);
186 }
187
188 if (!StringUtils.equals(foreignKey1.getForeignTableName(), foreignKey2.getForeignTableName())) {
189 ForeignKeyDifference diff = new ForeignKeyDifference(schema1, foreignKey1, schema2, foreignKey2);
190 diff.setType(ForeignKeyDifferenceType.FOREIGN_TABLE);
191 results.add(diff);
192 }
193
194 if (!objectsEqual(foreignKey1.getLocalColumnNames(), foreignKey2.getLocalColumnNames())) {
195 ForeignKeyDifference diff = new ForeignKeyDifference(schema1, foreignKey1, schema2, foreignKey2);
196 diff.setType(ForeignKeyDifferenceType.LOCAL_COLUMNS);
197 results.add(diff);
198 }
199
200 if (!objectsEqual(foreignKey1.getForeignColumnNames(), foreignKey2.getForeignColumnNames())) {
201 ForeignKeyDifference diff = new ForeignKeyDifference(schema1, foreignKey1, schema2, foreignKey2);
202 diff.setType(ForeignKeyDifferenceType.FOREIGN_COLUMNS);
203 results.add(diff);
204 }
205
206 if (!objectsEqual(foreignKey1.getOnDelete(), foreignKey2.getOnDelete())) {
207 ForeignKeyDifference diff = new ForeignKeyDifference(schema1, foreignKey1, schema2, foreignKey2);
208 diff.setType(ForeignKeyDifferenceType.ON_DELETE);
209 results.add(diff);
210 }
211
212 if (!objectsEqual(foreignKey1.getOnUpdate(), foreignKey2.getOnUpdate())) {
213 ForeignKeyDifference diff = new ForeignKeyDifference(schema1, foreignKey1, schema2, foreignKey2);
214 diff.setType(ForeignKeyDifferenceType.ON_UPDATE);
215 results.add(diff);
216 }
217
218 return results;
219 }
220
221 public static Collection<ViewDifference> compareViews(Schema schema1, View view1, Schema schema2, View view2) {
222 Collection<ViewDifference> results = new ArrayList<ViewDifference>();
223
224 if(!StringUtils.equals(view1.getQueryString(), view2.getQueryString())) {
225 ViewDifference diff = new ViewDifference(schema1, view1, schema2, view2);
226 diff.setType(ViewDifferenceType.QUERY_STRING);
227 results.add(diff);
228 }
229
230 return results;
231 }
232
233 public static Collection<SequenceDifference> compareSequences(Schema schema1, Sequence seq1, Schema schema2, Sequence seq2) {
234 Collection<SequenceDifference> results = new ArrayList<SequenceDifference>();
235
236 if (!StringUtils.equals(seq1.getStartValue(), seq2.getStartValue())) {
237 SequenceDifference diff = new SequenceDifference(schema1, seq1, schema2, seq2);
238 diff.setType(SequenceDifferenceType.START_VALUE);
239 results.add(diff);
240 }
241
242 return results;
243 }
244
245 private static boolean objectsEqual(Object o1, Object o2) {
246 if(o1 == null) {
247 return o2 == null;
248 }
249
250 return o1.equals(o2);
251 }
252
253 public static String tableDifferenceToString(TableDifference t) {
254 switch (t.getType()) {
255 case MISSING_TABLE:{
256 MissingTable missing = (MissingTable) t;
257 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getTable().getName();
258 String notFoundToken = missing.getMissingSchema().getName();
259 return DifferenceUtils.buildMissingElementToken(t.getType().getLabel(), foundToken, notFoundToken);
260 }
261 case MISSING_COLUMN: {
262 MissingColumn missing = (MissingColumn) t;
263 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getSourceTable().getName() + DifferenceUtils.DOT + missing.getColumn().getName();
264 String notFoundToken = missing.getMissingSchema().getName() + DifferenceUtils.DOT + missing.getMissingTable().getName();
265 return DifferenceUtils.buildMissingElementToken(t.getType().getLabel(), foundToken, notFoundToken);
266 }
267 case MISSING_INDEX: {
268 MissingIndex missing = (MissingIndex) t;
269 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getSourceTable().getName() + DifferenceUtils.DOT + missing.getIndex().getName();
270 String notFoundToken = missing.getMissingSchema().getName() + DifferenceUtils.DOT + missing.getMissingTable().getName();
271 return DifferenceUtils.buildMissingElementToken(t.getType().getLabel(), foundToken, notFoundToken);
272 }
273 case MISSING_UNIQUE_CONSTRAINT: {
274 MissingUniqueConstraint missing = (MissingUniqueConstraint) t;
275 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getSourceTable().getName() + DifferenceUtils.DOT + missing.getUniqueConstraint().getName();
276 String notFoundToken = missing.getMissingSchema().getName() + DifferenceUtils.DOT + missing.getMissingTable().getName();
277 return DifferenceUtils.buildMissingElementToken(t.getType().getLabel(), foundToken, notFoundToken);
278 }
279 default: {
280 return DifferenceUtils.buildDifferenceToken(t.getType().getLabel(), t);
281 }
282 }
283 }
284
285 public static String foreignKeyDifferenceToString(ForeignKeyDifference f) {
286 switch (f.getType()) {
287 case MISSING_FOREIGN_KEY: {
288 MissingForeignKey missing = (MissingForeignKey) f;
289 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getForeignKey().getName();
290 String notFoundToken = missing.getMissingSchema().getName();
291 return DifferenceUtils.buildMissingElementToken(f.getType().getLabel(), foundToken, notFoundToken);
292 }
293 default: {
294 return DifferenceUtils.buildDifferenceToken(f.getType().getLabel(), f);
295 }
296 }
297 }
298
299 public static String viewDifferenceToString(ViewDifference v) {
300 switch (v.getType()) {
301 case MISSING_VIEW: {
302 MissingView missing = (MissingView) v;
303 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getView().getName();
304 String notFoundToken = missing.getMissingSchema().getName();
305 return DifferenceUtils.buildMissingElementToken(v.getType().getLabel(), foundToken, notFoundToken);
306 }
307 default: {
308 return DifferenceUtils.buildDifferenceToken(v.getType().getLabel(), v);
309 }
310 }
311 }
312
313 public static String sequenceDifferenceToString(SequenceDifference s) {
314 switch (s.getType()) {
315 case MISSING_SEQUENCE: {
316 MissingSequence missing = (MissingSequence) s;
317 String foundToken = missing.getSourceSchema().getName() + DifferenceUtils.DOT + missing.getSequence().getName();
318 String notFoundToken = missing.getMissingSchema().getName();
319 return DifferenceUtils.buildMissingElementToken(s.getType().getLabel(), foundToken, notFoundToken);
320 }
321 default: {
322 return DifferenceUtils.buildDifferenceToken(s.getType().getLabel(), s);
323 }
324 }
325 }
326
327 }