1 package com.atlassian.dbexporter.importer;
2
3 import com.atlassian.dbexporter.Column;
4 import com.atlassian.dbexporter.Context;
5 import com.atlassian.dbexporter.DatabaseInformation;
6 import com.atlassian.dbexporter.EntityNameProcessor;
7 import com.atlassian.dbexporter.ForeignKey;
8 import com.atlassian.dbexporter.ImportExportErrorService;
9 import com.atlassian.dbexporter.Table;
10 import com.atlassian.dbexporter.node.NodeParser;
11 import com.atlassian.dbexporter.progress.ProgressMonitor;
12 import com.google.common.collect.Lists;
13
14 import java.util.Collection;
15 import java.util.List;
16
17 import static com.atlassian.dbexporter.importer.ImporterUtils.checkEndNode;
18 import static com.atlassian.dbexporter.importer.ImporterUtils.checkStartNode;
19 import static com.atlassian.dbexporter.importer.ImporterUtils.isNodeNotClosed;
20 import static com.atlassian.dbexporter.importer.TableDefinitionImporter.DatabaseCleanerAroundImporter.newCleaner;
21 import static com.atlassian.dbexporter.node.NodeBackup.ColumnDefinitionNode;
22 import static com.atlassian.dbexporter.node.NodeBackup.ForeignKeyDefinitionNode;
23 import static com.atlassian.dbexporter.node.NodeBackup.TableDefinitionNode;
24 import static com.atlassian.dbexporter.progress.ProgressMonitor.Task;
25 import static com.google.common.base.Preconditions.checkNotNull;
26 import static com.google.common.collect.Lists.newArrayList;
27
28 public final class TableDefinitionImporter extends AbstractSingleNodeImporter {
29 private final TableCreator tableCreator;
30
31 public TableDefinitionImporter(ImportExportErrorService errorService, TableCreator tableCreator, final DatabaseCleaner databaseCleaner) {
32 super(errorService, Lists.<AroundImporter>newArrayList(newCleaner(databaseCleaner)));
33 this.tableCreator = checkNotNull(tableCreator);
34 }
35
36 @Override
37 protected void doImportNode(NodeParser node, ImportConfiguration configuration, Context context) {
38 final ProgressMonitor monitor = configuration.getProgressMonitor();
39 monitor.begin(Task.TABLE_DEFINITION);
40
41 final List<Table> tables = newArrayList();
42 while (isNodeNotClosed(node, getNodeName())) {
43 tables.add(readTable(node, configuration.getEntityNameProcessor()));
44 }
45
46 monitor.end(Task.TABLE_DEFINITION);
47 monitor.totalNumberOfTables(tables.size());
48
49 DatabaseInformation databaseInformation = context.get(DatabaseInformation.class);
50 tableCreator.create(databaseInformation, tables, configuration.getEntityNameProcessor(), monitor);
51 context.putAll(tables);
52 }
53
54 private Table readTable(NodeParser node, EntityNameProcessor entityNameProcessor) {
55 checkStartNode(node, TableDefinitionNode.NAME);
56
57 final String tableName = entityNameProcessor.tableName(TableDefinitionNode.getName(node));
58 node.getNextNode();
59
60 final List<Column> columns = readColumns(node, entityNameProcessor);
61 final Collection<ForeignKey> foreignKeys = readForeignKeys(node);
62
63 checkEndNode(node, TableDefinitionNode.NAME);
64
65 node.getNextNode();
66
67 return new Table(tableName, columns, foreignKeys);
68 }
69
70 private List<Column> readColumns(NodeParser node, EntityNameProcessor entityNameProcessor) {
71 final List<Column> columns = newArrayList();
72 while (node.getName().equals(ColumnDefinitionNode.NAME)) {
73 columns.add(readColumn(node, entityNameProcessor));
74 }
75 return columns;
76 }
77
78 private Column readColumn(NodeParser node, EntityNameProcessor entityNameProcessor) {
79 checkStartNode(node, ColumnDefinitionNode.NAME);
80
81 final String columnName = entityNameProcessor.columnName(ColumnDefinitionNode.getName(node));
82 final boolean isPk = ColumnDefinitionNode.isPrimaryKey(node);
83 final boolean isAi = ColumnDefinitionNode.isAutoIncrement(node);
84 final int sqlType = ColumnDefinitionNode.getSqlType(node);
85 final Integer precision = ColumnDefinitionNode.getPrecision(node);
86 final Integer scale = ColumnDefinitionNode.getScale(node);
87
88 checkEndNode(node.getNextNode(), ColumnDefinitionNode.NAME);
89 node.getNextNode();
90 return new Column(columnName, sqlType, isPk, isAi, precision, scale);
91 }
92
93 private Collection<ForeignKey> readForeignKeys(NodeParser node) {
94 final Collection<ForeignKey> fks = newArrayList();
95 while (node.getName().equals(ForeignKeyDefinitionNode.NAME)) {
96 fks.add(readForeignKey(node));
97 }
98 return fks;
99 }
100
101 private ForeignKey readForeignKey(NodeParser node) {
102 checkStartNode(node, ForeignKeyDefinitionNode.NAME);
103
104 final String fromTable = ForeignKeyDefinitionNode.getFromTable(node);
105 final String fromColumn = ForeignKeyDefinitionNode.getFromColumn(node);
106 final String toTable = ForeignKeyDefinitionNode.getToTable(node);
107 final String toColumn = ForeignKeyDefinitionNode.getToColumn(node);
108
109 checkEndNode(node.getNextNode(), ForeignKeyDefinitionNode.NAME);
110 node.getNextNode();
111 return new ForeignKey(fromTable, fromColumn, toTable, toColumn);
112 }
113
114 @Override
115 protected String getNodeName() {
116 return TableDefinitionNode.NAME;
117 }
118
119 static final class DatabaseCleanerAroundImporter extends NoOpAroundImporter {
120 private final DatabaseCleaner databaseCleaner;
121
122 private DatabaseCleanerAroundImporter(DatabaseCleaner databaseCleaner) {
123 this.databaseCleaner = checkNotNull(databaseCleaner);
124 }
125
126 @Override
127 public void before(NodeParser node, ImportConfiguration configuration, Context context) {
128 databaseCleaner.cleanup(configuration.getCleanupMode());
129 }
130
131 static DatabaseCleanerAroundImporter newCleaner(DatabaseCleaner cleaner) {
132 return new DatabaseCleanerAroundImporter(cleaner);
133 }
134 }
135 }