1 package liquibase.ext.spatial.preconditions;
2
3 import java.util.Arrays;
4 import java.util.LinkedHashSet;
5 import java.util.Set;
6
7 import liquibase.changelog.ChangeSet;
8 import liquibase.changelog.DatabaseChangeLog;
9 import liquibase.database.Database;
10 import liquibase.database.core.DerbyDatabase;
11 import liquibase.database.core.H2Database;
12 import liquibase.exception.PreconditionErrorException;
13 import liquibase.exception.PreconditionFailedException;
14 import liquibase.exception.UnexpectedLiquibaseException;
15 import liquibase.exception.ValidationErrors;
16 import liquibase.exception.Warnings;
17 import liquibase.ext.spatial.xml.XmlConstants;
18 import liquibase.parser.core.ParsedNode;
19 import liquibase.parser.core.ParsedNodeException;
20 import liquibase.precondition.AbstractPrecondition;
21 import liquibase.precondition.Precondition;
22 import liquibase.precondition.core.IndexExistsPrecondition;
23 import liquibase.precondition.core.TableExistsPrecondition;
24 import liquibase.resource.ResourceAccessor;
25 import liquibase.structure.DatabaseObject;
26 import liquibase.structure.core.Column;
27 import liquibase.structure.core.Index;
28 import liquibase.structure.core.Schema;
29 import liquibase.structure.core.Table;
30 import liquibase.util.StringUtils;
31
32
33
34
35
36 public class SpatialIndexExistsPrecondition extends AbstractPrecondition {
37 private String catalogName;
38 private String schemaName;
39 private String tableName;
40 private String columnNames;
41 private String indexName;
42
43 public String getCatalogName() {
44 return this.catalogName;
45 }
46
47 public void setCatalogName(final String catalogName) {
48 this.catalogName = catalogName;
49 }
50
51 public String getSchemaName() {
52 return this.schemaName;
53 }
54
55 public void setSchemaName(final String schemaName) {
56 this.schemaName = schemaName;
57 }
58
59 public String getTableName() {
60 return this.tableName;
61 }
62
63 public void setTableName(final String tableName) {
64 this.tableName = tableName;
65 }
66
67 public String getIndexName() {
68 return this.indexName;
69 }
70
71 public void setIndexName(final String indexName) {
72 this.indexName = indexName;
73 }
74
75 public String getColumnNames() {
76 return this.columnNames;
77 }
78
79 public void setColumnNames(final String columnNames) {
80 this.columnNames = columnNames;
81 }
82
83 @Override
84 public String getName() {
85 return "spatialIndexExists";
86 }
87
88 @Override
89 public Warnings warn(final Database database) {
90 return new Warnings();
91 }
92
93 @Override
94 public ValidationErrors validate(final Database database) {
95 final ValidationErrors validationErrors;
96
97 if ((database instanceof DerbyDatabase || database instanceof H2Database)
98 && getTableName() == null) {
99 validationErrors = new ValidationErrors();
100 validationErrors
101 .addError("tableName is required for " + database.getDatabaseProductName());
102 } else {
103 final IndexExistsPrecondition precondition = new IndexExistsPrecondition();
104 precondition.setCatalogName(getCatalogName());
105 precondition.setSchemaName(getSchemaName());
106 precondition.setTableName(getTableName());
107 precondition.setIndexName(getIndexName());
108 precondition.setColumnNames(getColumnNames());
109 validationErrors = precondition.validate(database);
110 }
111 return validationErrors;
112 }
113
114 @Override
115 public void check(final Database database, final DatabaseChangeLog changeLog,
116 final ChangeSet changeSet) throws PreconditionFailedException, PreconditionErrorException {
117 Precondition delegatedPrecondition;
118 if (database instanceof DerbyDatabase || database instanceof H2Database) {
119 final TableExistsPrecondition precondition = new TableExistsPrecondition();
120 precondition.setCatalogName(getCatalogName());
121 precondition.setSchemaName(getSchemaName());
122 final String tableName = getHatboxTableName();
123 precondition.setTableName(tableName);
124 delegatedPrecondition = precondition;
125 } else {
126 final IndexExistsPrecondition precondition = new IndexExistsPrecondition();
127 precondition.setCatalogName(getCatalogName());
128 precondition.setSchemaName(getSchemaName());
129 precondition.setTableName(getTableName());
130 precondition.setIndexName(getIndexName());
131 precondition.setColumnNames(getColumnNames());
132 delegatedPrecondition = precondition;
133 }
134 delegatedPrecondition.check(database, changeLog, changeSet);
135 }
136
137
138
139
140
141
142 protected String getHatboxTableName() {
143 final String tableName;
144 if (!StringUtils.hasUpperCase(getTableName())) {
145 tableName = getTableName() + "_hatbox";
146 } else {
147 tableName = getTableName() + "_HATBOX";
148 }
149 return tableName;
150 }
151
152
153
154
155
156
157
158
159
160
161 public DatabaseObject getExample(final Database database, final String tableName) {
162 final Schema schema = new Schema(getCatalogName(), getSchemaName());
163 final DatabaseObject example;
164
165
166 if (database instanceof DerbyDatabase || database instanceof H2Database) {
167 final String correctedTableName = database.correctObjectName(getHatboxTableName(),
168 Table.class);
169 example = new Table().setName(correctedTableName).setSchema(schema);
170 } else {
171 example = getIndexExample(database, schema, tableName);
172 }
173 return example;
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187 protected Index getIndexExample(final Database database, final Schema schema,
188 final String tableName) {
189 final Index example = new Index();
190 if (tableName != null) {
191 example.setTable((Table) new Table().setName(
192 database.correctObjectName(getTableName(), Table.class)).setSchema(schema));
193 }
194 example.setName(database.correctObjectName(getIndexName(), Index.class));
195 if (StringUtils.trimToNull(getColumnNames()) != null) {
196 for (final String columnName : getColumnNames().split("\\s*,\\s*")) {
197 final Column column = new Column(database.correctObjectName(columnName, Column.class));
198 example.getColumns().add(column);
199 }
200 }
201 return example;
202 }
203
204
205
206
207 @Override
208 public String getSerializedObjectName() {
209 return "spatialIndexExists";
210 }
211
212
213
214
215 @Override
216 public Set<String> getSerializableFields() {
217 return new LinkedHashSet<String>(Arrays.asList("catalogName", "schemaName", "tableName",
218 "columnNames", "indexName"));
219 }
220
221
222
223
224 @Override
225 public Object getSerializableFieldValue(final String field) {
226 final Object value;
227 if ("catalogName".equals(field)) {
228 value = getCatalogName();
229 } else if ("schemaName".equals(field)) {
230 value = getSchemaName();
231 } else if ("tableName".equals(field)) {
232 value = getTableName();
233 } else if ("columnNames".equals(field)) {
234 value = getColumnNames();
235 } else if ("indexName".equals(field)) {
236 value = getIndexName();
237 } else {
238 throw new UnexpectedLiquibaseException("Unexpected field request on "
239 + getSerializedObjectName() + ": " + field);
240 }
241 return value;
242 }
243
244
245
246
247 @Override
248 public SerializationType getSerializableFieldType(final String field) {
249 return SerializationType.NAMED_FIELD;
250 }
251
252
253
254
255 @Override
256 public String getSerializedObjectNamespace() {
257 return XmlConstants.SPATIAL_CHANGELOG_NAMESPACE;
258 }
259
260
261
262
263 @Override
264 public ParsedNode serialize() throws ParsedNodeException {
265 final String namespace = getSerializedObjectNamespace();
266 final ParsedNode node = new ParsedNode(namespace, getSerializedObjectName());
267 for (final String field : getSerializableFields()) {
268 final Object value = getSerializableFieldValue(field);
269 node.addChild(namespace, field, value);
270 }
271 return node;
272 }
273
274
275
276
277
278 @Override
279 public void load(final ParsedNode parsedNode, final ResourceAccessor resourceAccessor)
280 throws ParsedNodeException {
281 final String namespace = null;
282 this.catalogName = parsedNode.getChildValue(namespace, "catalogName", String.class);
283 this.schemaName = parsedNode.getChildValue(namespace, "schemaName", String.class);
284 this.tableName = parsedNode.getChildValue(namespace, "tableName", String.class);
285 this.columnNames = parsedNode.getChildValue(namespace, "columnNames", String.class);
286 this.indexName = parsedNode.getChildValue(namespace, "indexName", String.class);
287 }
288 }