1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Set;
29
30 import com.healthmarketscience.jackcess.impl.DatabaseImpl;
31 import com.healthmarketscience.jackcess.impl.PropertyMapImpl;
32 import com.healthmarketscience.jackcess.impl.TableCreator;
33 import com.healthmarketscience.jackcess.impl.ToStringBuilder;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class TableBuilder {
56
57
58 private static final String ESCAPE_PREFIX = "x";
59
60
61 private static final class ReservedWords {
62
63
64
65
66 private static final Set<String> VALUES =
67 new HashSet<>(Arrays.asList(
68 "add", "all", "alphanumeric", "alter", "and", "any", "application", "as",
69 "asc", "assistant", "autoincrement", "avg", "between", "binary", "bit",
70 "boolean", "by", "byte", "char", "character", "column", "compactdatabase",
71 "constraint", "container", "count", "counter", "create", "createdatabase",
72 "createfield", "creategroup", "createindex", "createobject", "createproperty",
73 "createrelation", "createtabledef", "createuser", "createworkspace",
74 "currency", "currentuser", "database", "date", "datetime", "delete",
75 "desc", "description", "disallow", "distinct", "distinctrow", "document",
76 "double", "drop", "echo", "else", "end", "eqv", "error", "exists", "exit",
77 "false", "field", "fields", "fillcache", "float", "float4", "float8",
78 "foreign", "form", "forms", "from", "full", "function", "general",
79 "getobject", "getoption", "gotopage", "group", "group by", "guid", "having",
80 "idle", "ieeedouble", "ieeesingle", "if", "ignore", "imp", "in", "index",
81 "indexes", "inner", "insert", "inserttext", "int", "integer", "integer1",
82 "integer2", "integer4", "into", "is", "join", "key", "lastmodified", "left",
83 "level", "like", "logical", "logical1", "long", "longbinary", "longtext",
84 "macro", "match", "max", "min", "mod", "memo", "module", "money", "move",
85 "name", "newpassword", "no", "not", "null", "number", "numeric", "object",
86 "oleobject", "off", "on", "openrecordset", "option", "or", "order", "outer",
87 "owneraccess", "parameter", "parameters", "partial", "percent", "pivot",
88 "primary", "procedure", "property", "queries", "query", "quit", "real",
89 "recalc", "recordset", "references", "refresh", "refreshlink",
90 "registerdatabase", "relation", "repaint", "repairdatabase", "report",
91 "reports", "requery", "right", "screen", "section", "select", "set",
92 "setfocus", "setoption", "short", "single", "smallint", "some", "sql",
93 "stdev", "stdevp", "string", "sum", "table", "tabledef", "tabledefs",
94 "tableid", "text", "time", "timestamp", "top", "transform", "true", "type",
95 "union", "unique", "update", "user", "value", "values", "var", "varp",
96 "varbinary", "varchar", "where", "with", "workspace", "xor", "year", "yes",
97 "yesno"));
98 }
99
100
101
102 private String _name;
103
104 private final List<ColumnBuilder> _columns = new ArrayList<>();
105
106 private final List<IndexBuilder> _indexes = new ArrayList<>();
107
108 private boolean _escapeIdentifiers;
109
110 private Map<String,PropertyMap.Property> _props;
111
112
113 public TableBuilder(String name) {
114 this(name, false);
115 }
116
117 public TableBuilder(String name, boolean escapeIdentifiers) {
118 _name = name;
119 _escapeIdentifiers = escapeIdentifiers;
120 if(_escapeIdentifiers) {
121 _name = escapeIdentifier(_name);
122 }
123 }
124
125 public String getName() {
126 return _name;
127 }
128
129
130
131
132 public TableBuilder addColumn(ColumnBuilder column) {
133 if(_escapeIdentifiers) {
134 column.escapeName();
135 }
136 _columns.add(column);
137 return this;
138 }
139
140
141
142
143 public TableBuilder addColumns(Collection<? extends ColumnBuilder> columns) {
144 if(columns != null) {
145 for(ColumnBuilder col : columns) {
146 addColumn(col);
147 }
148 }
149 return this;
150 }
151
152 public List<ColumnBuilder> getColumns() {
153 return _columns;
154 }
155
156
157
158
159 public TableBuilder addIndex(IndexBuilder index) {
160 if(_escapeIdentifiers) {
161 index.setName(escapeIdentifier(index.getName()));
162 for(IndexBuilder.Column col : index.getColumns()) {
163 col.setName(escapeIdentifier(col.getName()));
164 }
165 }
166 _indexes.add(index);
167 return this;
168 }
169
170
171
172
173 public TableBuilder addIndexes(Collection<? extends IndexBuilder> indexes) {
174 if(indexes != null) {
175 for(IndexBuilder col : indexes) {
176 addIndex(col);
177 }
178 }
179 return this;
180 }
181
182 public List<IndexBuilder> getIndexes() {
183 return _indexes;
184 }
185
186
187
188
189
190 public TableBuilder setEscapeIdentifiers(boolean escapeIdentifiers) {
191 _escapeIdentifiers = escapeIdentifiers;
192 return this;
193 }
194
195
196
197
198
199 public TableBuilder setPrimaryKey(String... colNames) {
200 addIndex(new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME)
201 .addColumns(colNames).setPrimaryKey());
202 return this;
203 }
204
205
206
207
208 public TableBuilder escapeName() {
209 _name = escapeIdentifier(_name);
210 return this;
211 }
212
213
214
215
216
217
218
219 public TableBuilder putProperty(String name, Object value) {
220 return putProperty(name, null, value);
221 }
222
223
224
225
226 public TableBuilder putProperty(String name, DataType type, Object value) {
227 if(_props == null) {
228 _props = new HashMap<>();
229 }
230 _props.put(name, PropertyMapImpl.createProperty(name, type, value));
231 return this;
232 }
233
234 public Map<String,PropertyMap.Property> getProperties() {
235 return _props;
236 }
237
238
239
240
241
242 public Table toTable(Database db) throws IOException {
243 return new TableCreator(((DatabaseImpl)db)).createTable(this);
244 }
245
246 @Override
247 public String toString() {
248 return ToStringBuilder.builder(this)
249 .append("name", _name)
250 .append("escapeIdentifiers", _escapeIdentifiers)
251 .append("columns", _columns)
252 .append("indexes", _indexes)
253 .appendIfNotNull("props", _props)
254 .toString();
255 }
256
257
258
259
260
261 public static String escapeIdentifier(String s) {
262 if (isReservedWord(s)) {
263 return ESCAPE_PREFIX + s;
264 }
265 return s;
266 }
267
268
269
270
271
272
273 public static boolean isReservedWord(String s) {
274 return ReservedWords.VALUES.contains(s.toLowerCase(Locale.ROOT));
275 }
276
277 }