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.File;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.UUID;
26
27 import static com.healthmarketscience.jackcess.Database.*;
28 import com.healthmarketscience.jackcess.InvalidValueException;
29 import com.healthmarketscience.jackcess.impl.DatabaseImpl;
30 import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
31 import com.healthmarketscience.jackcess.impl.PropertyMapImpl;
32 import com.healthmarketscience.jackcess.impl.PropertyMaps;
33 import com.healthmarketscience.jackcess.impl.TableImpl;
34 import junit.framework.TestCase;
35 import static com.healthmarketscience.jackcess.TestUtil.*;
36 import static com.healthmarketscience.jackcess.DatabaseBuilder.*;
37
38
39
40
41 public class PropertiesTest extends TestCase
42 {
43
44 public PropertiesTest(String name) throws Exception {
45 super(name);
46 }
47
48 public void testPropertyMaps() throws Exception
49 {
50 PropertyMaps maps = new PropertyMaps(10, null, null, null);
51 assertTrue(maps.isEmpty());
52 assertEquals(0, maps.getSize());
53 assertFalse(maps.iterator().hasNext());
54 assertEquals(10, maps.getObjectId());
55
56 PropertyMapImpl defMap = maps.getDefault();
57 assertTrue(defMap.isEmpty());
58 assertEquals(0, defMap.getSize());
59 assertFalse(defMap.iterator().hasNext());
60
61 PropertyMapImpl colMap = maps.get("testcol");
62 assertTrue(colMap.isEmpty());
63 assertEquals(0, colMap.getSize());
64 assertFalse(colMap.iterator().hasNext());
65
66 assertFalse(maps.isEmpty());
67 assertEquals(2, maps.getSize());
68
69 assertSame(defMap, maps.get(PropertyMaps.DEFAULT_NAME));
70 assertEquals(PropertyMaps.DEFAULT_NAME, defMap.getName());
71 assertSame(colMap, maps.get("TESTCOL"));
72 assertEquals("testcol", colMap.getName());
73
74 defMap.put("foo", DataType.TEXT, "bar", false);
75 defMap.put("baz", DataType.LONG, 13, true);
76
77 assertFalse(defMap.isEmpty());
78 assertEquals(2, defMap.getSize());
79 assertFalse(defMap.get("foo").isDdl());
80 assertTrue(defMap.get("baz").isDdl());
81
82 colMap.put("buzz", DataType.BOOLEAN, Boolean.TRUE, true);
83
84 assertFalse(colMap.isEmpty());
85 assertEquals(1, colMap.getSize());
86
87 assertEquals("bar", defMap.getValue("foo"));
88 assertEquals("bar", defMap.getValue("FOO"));
89 assertNull(colMap.getValue("foo"));
90 assertEquals(13, defMap.get("baz").getValue());
91 assertEquals(Boolean.TRUE, colMap.getValue("Buzz"));
92
93 assertEquals("bar", defMap.getValue("foo", "blah"));
94 assertEquals("blah", defMap.getValue("bogus", "blah"));
95
96 List<PropertyMap.Property> props = new ArrayList<PropertyMap.Property>();
97 for(PropertyMap map : maps) {
98 for(PropertyMap.Property prop : map) {
99 props.add(prop);
100 }
101 }
102
103 assertEquals(Arrays.asList(defMap.get("foo"), defMap.get("baz"),
104 colMap.get("buzz")), props);
105 }
106
107 public void testInferTypes() throws Exception
108 {
109 PropertyMaps maps = new PropertyMaps(10, null, null, null);
110 PropertyMap defMap = maps.getDefault();
111
112 assertEquals(DataType.TEXT,
113 defMap.put(PropertyMap.FORMAT_PROP, null).getType());
114 assertEquals(DataType.BOOLEAN,
115 defMap.put(PropertyMap.REQUIRED_PROP, null).getType());
116
117 assertEquals(DataType.TEXT,
118 defMap.put("strprop", "this is a string").getType());
119 assertEquals(DataType.BOOLEAN,
120 defMap.put("boolprop", true).getType());
121 assertEquals(DataType.LONG,
122 defMap.put("intprop", 37).getType());
123 }
124
125 public void testReadProperties() throws Exception
126 {
127 byte[] nameMapBytes = null;
128
129 for(TestDB testDb : SUPPORTED_DBS_TEST_FOR_READ) {
130 Database db = open(testDb);
131
132 TableImpl t = (TableImpl)db.getTable("Table1");
133 assertEquals(t.getTableDefPageNumber(),
134 t.getPropertyMaps().getObjectId());
135 PropertyMap tProps = t.getProperties();
136 assertEquals(PropertyMaps.DEFAULT_NAME, tProps.getName());
137 int expectedNumProps = 3;
138 if(db.getFileFormat() != Database.FileFormat.V1997) {
139 assertEquals("{5A29A676-1145-4D1A-AE47-9F5415CDF2F1}",
140 tProps.getValue(PropertyMap.GUID_PROP));
141 if(nameMapBytes == null) {
142 nameMapBytes = (byte[])tProps.getValue("NameMap");
143 } else {
144 assertTrue(Arrays.equals(nameMapBytes,
145 (byte[])tProps.getValue("NameMap")));
146 }
147 expectedNumProps += 2;
148 }
149 assertEquals(expectedNumProps, tProps.getSize());
150 assertEquals((byte)0, tProps.getValue("Orientation"));
151 assertEquals(Boolean.FALSE, tProps.getValue("OrderByOn"));
152 assertEquals((byte)2, tProps.getValue("DefaultView"));
153
154 PropertyMap colProps = t.getColumn("A").getProperties();
155 assertEquals("A", colProps.getName());
156 expectedNumProps = 9;
157 if(db.getFileFormat() != Database.FileFormat.V1997) {
158 assertEquals("{E9EDD90C-CE55-4151-ABE1-A1ACE1007515}",
159 colProps.getValue(PropertyMap.GUID_PROP));
160 ++expectedNumProps;
161 }
162 assertEquals(expectedNumProps, colProps.getSize());
163 assertEquals((short)-1, colProps.getValue("ColumnWidth"));
164 assertEquals((short)0, colProps.getValue("ColumnOrder"));
165 assertEquals(Boolean.FALSE, colProps.getValue("ColumnHidden"));
166 assertEquals(Boolean.FALSE,
167 colProps.getValue(PropertyMap.REQUIRED_PROP));
168 assertEquals(Boolean.FALSE,
169 colProps.getValue(PropertyMap.ALLOW_ZERO_LEN_PROP));
170 assertEquals((short)109, colProps.getValue("DisplayControl"));
171 assertEquals(Boolean.TRUE, colProps.getValue("UnicodeCompression"));
172 assertEquals((byte)0, colProps.getValue("IMEMode"));
173 assertEquals((byte)3, colProps.getValue("IMESentenceMode"));
174
175 PropertyMap dbProps = db.getDatabaseProperties();
176 assertTrue(((String)dbProps.getValue(PropertyMap.ACCESS_VERSION_PROP))
177 .matches("[0-9]{2}[.][0-9]{2}"));
178
179 PropertyMap sumProps = db.getSummaryProperties();
180 assertEquals(3, sumProps.getSize());
181 assertEquals("test", sumProps.getValue(PropertyMap.TITLE_PROP));
182 assertEquals("tmccune", sumProps.getValue(PropertyMap.AUTHOR_PROP));
183 assertEquals("Health Market Science", sumProps.getValue(PropertyMap.COMPANY_PROP));
184
185 PropertyMap userProps = db.getUserDefinedProperties();
186 assertEquals(1, userProps.getSize());
187 assertEquals(Boolean.TRUE, userProps.getValue("ReplicateProject"));
188
189 db.close();
190 }
191 }
192
193 public void testParseProperties() throws Exception
194 {
195 for(FileFormat ff : SUPPORTED_FILEFORMATS_FOR_READ) {
196 File[] dbFiles = new File(DIR_TEST_DATA, ff.name()).listFiles();
197 if(dbFiles == null) {
198 continue;
199 }
200 for(File f : dbFiles) {
201
202 if(!f.isFile()) {
203 continue;
204 }
205
206 Database db = open(ff, f);
207
208 PropertyMap dbProps = db.getDatabaseProperties();
209 assertFalse(dbProps.isEmpty());
210 assertTrue(((String)dbProps.getValue(PropertyMap.ACCESS_VERSION_PROP))
211 .matches("[0-9]{2}[.][0-9]{2}"));
212
213 for(Row row : ((DatabaseImpl)db).getSystemCatalog()) {
214 int id = row.getInt("Id");
215 byte[] propBytes = row.getBytes("LvProp");
216 PropertyMaps propMaps = ((DatabaseImpl)db).getPropertiesForObject(
217 id, null);
218 int byteLen = ((propBytes != null) ? propBytes.length : 0);
219 if(byteLen == 0) {
220 assertTrue(propMaps.isEmpty());
221 } else if(propMaps.isEmpty()) {
222 assertTrue(byteLen < 80);
223 } else {
224 assertTrue(byteLen > 0);
225 }
226 }
227
228 db.close();
229 }
230 }
231 }
232
233 public void testWriteProperties() throws Exception
234 {
235 for(TestDB testDb : SUPPORTED_DBS_TEST) {
236 Database db = open(testDb);
237
238 TableImpl t = (TableImpl)db.getTable("Table1");
239
240 PropertyMap tProps = t.getProperties();
241
242 PropertyMaps maps = ((PropertyMapImpl)tProps).getOwner();
243
244 byte[] mapsBytes = maps.write();
245
246 PropertyMaps maps2 = ((DatabaseImpl)db).readProperties(
247 mapsBytes, maps.getObjectId(), null);
248
249 Iterator<PropertyMapImpl> iter = maps.iterator();
250 Iterator<PropertyMapImpl> iter2 = maps2.iterator();
251
252 while(iter.hasNext() && iter2.hasNext()) {
253 PropertyMapImpl propMap = iter.next();
254 PropertyMapImpl propMap2 = iter2.next();
255
256 checkProperties(propMap, propMap2);
257 }
258
259 assertFalse(iter.hasNext());
260 assertFalse(iter2.hasNext());
261
262 db.close();
263 }
264 }
265
266 public void testModifyProperties() throws Exception
267 {
268 for(TestDB testDb : SUPPORTED_DBS_TEST) {
269 Database db = openCopy(testDb);
270 File dbFile = db.getFile();
271
272 Table t = db.getTable("Table1");
273
274
275 PropertyMap origCProps = t.getColumn("C").getProperties();
276 PropertyMap origFProps = t.getColumn("F").getProperties();
277 PropertyMap origDProps = t.getColumn("D").getProperties();
278
279 db.close();
280
281
282
283 db = open(dbFile);
284
285 t = db.getTable("Table1");
286
287 PropertyMap cProps = t.getColumn("C").getProperties();
288 PropertyMap fProps = t.getColumn("F").getProperties();
289 PropertyMap dProps = t.getColumn("D").getProperties();
290
291 assertFalse((Boolean)cProps.getValue(PropertyMap.REQUIRED_PROP));
292 assertEquals("0", fProps.getValue(PropertyMap.DEFAULT_VALUE_PROP));
293 assertEquals((short)109, dProps.getValue("DisplayControl"));
294
295 cProps.put(PropertyMap.REQUIRED_PROP, DataType.BOOLEAN, true);
296 fProps.get(PropertyMap.DEFAULT_VALUE_PROP).setValue("42");
297 dProps.remove("DisplayControl");
298
299 db.close();
300
301
302
303 db = open(dbFile);
304
305 t = db.getTable("Table1");
306
307 cProps = t.getColumn("C").getProperties();
308 fProps = t.getColumn("F").getProperties();
309 dProps = t.getColumn("D").getProperties();
310
311 assertFalse((Boolean)cProps.getValue(PropertyMap.REQUIRED_PROP));
312 assertEquals("0", fProps.getValue(PropertyMap.DEFAULT_VALUE_PROP));
313 assertEquals((short)109, dProps.getValue("DisplayControl"));
314
315 checkProperties(origCProps, cProps);
316 checkProperties(origFProps, fProps);
317 checkProperties(origDProps, dProps);
318
319 cProps.put(PropertyMap.REQUIRED_PROP, DataType.BOOLEAN, true);
320 cProps.save();
321 fProps.get(PropertyMap.DEFAULT_VALUE_PROP).setValue("42");
322 fProps.save();
323 dProps.remove("DisplayControl");
324 dProps.save();
325
326 db.close();
327
328
329
330 db = open(dbFile);
331
332 t = db.getTable("Table1");
333
334 cProps = t.getColumn("C").getProperties();
335 fProps = t.getColumn("F").getProperties();
336 dProps = t.getColumn("D").getProperties();
337
338 assertTrue((Boolean)cProps.getValue(PropertyMap.REQUIRED_PROP));
339 assertEquals("42", fProps.getValue(PropertyMap.DEFAULT_VALUE_PROP));
340 assertNull(dProps.getValue("DisplayControl"));
341
342 cProps.put(PropertyMap.REQUIRED_PROP, DataType.BOOLEAN, false);
343 fProps.get(PropertyMap.DEFAULT_VALUE_PROP).setValue("0");
344 dProps.put("DisplayControl", DataType.INT, (short)109);
345
346 checkProperties(origCProps, cProps);
347 checkProperties(origFProps, fProps);
348 checkProperties(origDProps, dProps);
349
350 db.close();
351 }
352 }
353
354 public void testCreateDbProperties() throws Exception
355 {
356 for(FileFormat ff : SUPPORTED_FILEFORMATS) {
357
358 if(ff == FileFormat.GENERIC_JET4) {
359
360 continue;
361 }
362
363 File file = TestUtil.createTempFile(false);
364 Database db = newDatabase(file)
365 .setFileFormat(ff)
366 .putUserDefinedProperty("testing", "123")
367 .create();
368
369 UUID u1 = UUID.randomUUID();
370 UUID u2 = UUID.randomUUID();
371 Table t = newTable("Test")
372 .putProperty("awesome_table", true)
373 .addColumn(newColumn("id", DataType.LONG)
374 .setAutoNumber(true)
375 .putProperty(PropertyMap.REQUIRED_PROP, true)
376 .putProperty(PropertyMap.GUID_PROP, u1))
377 .addColumn(newColumn("data", DataType.TEXT)
378 .putProperty(PropertyMap.ALLOW_ZERO_LEN_PROP, false)
379 .putProperty(PropertyMap.GUID_PROP, u2))
380 .toTable(db);
381
382 t.addRow(Column.AUTO_NUMBER, "value");
383
384 db.close();
385
386 db = open(file);
387
388 assertEquals("123", db.getUserDefinedProperties().getValue("testing"));
389
390 t = db.getTable("Test");
391
392 assertEquals(Boolean.TRUE,
393 t.getProperties().getValue("awesome_table"));
394
395 Column c = t.getColumn("id");
396 assertEquals(Boolean.TRUE,
397 c.getProperties().getValue(PropertyMap.REQUIRED_PROP));
398 assertEquals("{" + u1.toString().toUpperCase() + "}",
399 c.getProperties().getValue(PropertyMap.GUID_PROP));
400
401 c = t.getColumn("data");
402 assertEquals(Boolean.FALSE,
403 c.getProperties().getValue(PropertyMap.ALLOW_ZERO_LEN_PROP));
404 assertEquals("{" + u2.toString().toUpperCase() + "}",
405 c.getProperties().getValue(PropertyMap.GUID_PROP));
406
407 }
408 }
409
410 public void testEnforceProperties() throws Exception
411 {
412 for(final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
413 Database db = create(fileFormat);
414
415 Table t = newTable("testReq")
416 .addColumn(newColumn("id", DataType.LONG)
417 .setAutoNumber(true)
418 .putProperty(PropertyMap.REQUIRED_PROP, true))
419 .addColumn(newColumn("value", DataType.TEXT)
420 .putProperty(PropertyMap.REQUIRED_PROP, true))
421 .toTable(db);
422
423 t.addRow(Column.AUTO_NUMBER, "v1");
424
425 try {
426 t.addRow(Column.AUTO_NUMBER, null);
427 fail("InvalidValueException should have been thrown");
428 } catch(InvalidValueException expected) {
429
430 }
431
432 t.addRow(Column.AUTO_NUMBER, "");
433
434 List<? extends Map<String, Object>> expectedRows =
435 createExpectedTable(
436 createExpectedRow(
437 "id", 1,
438 "value", "v1"),
439 createExpectedRow(
440 "id", 2,
441 "value", ""));
442 assertTable(expectedRows, t);
443
444
445 t = newTable("testNz")
446 .addColumn(newColumn("id", DataType.LONG)
447 .setAutoNumber(true)
448 .putProperty(PropertyMap.REQUIRED_PROP, true))
449 .addColumn(newColumn("value", DataType.TEXT)
450 .putProperty(PropertyMap.ALLOW_ZERO_LEN_PROP, false))
451 .toTable(db);
452
453 t.addRow(Column.AUTO_NUMBER, "v1");
454
455 try {
456 t.addRow(Column.AUTO_NUMBER, "");
457 fail("InvalidValueException should have been thrown");
458 } catch(InvalidValueException expected) {
459
460 }
461
462 t.addRow(Column.AUTO_NUMBER, null);
463
464 expectedRows =
465 createExpectedTable(
466 createExpectedRow(
467 "id", 1,
468 "value", "v1"),
469 createExpectedRow(
470 "id", 2,
471 "value", null));
472 assertTable(expectedRows, t);
473
474
475 t = newTable("testReqNz")
476 .addColumn(newColumn("id", DataType.LONG)
477 .setAutoNumber(true)
478 .putProperty(PropertyMap.REQUIRED_PROP, true))
479 .addColumn(newColumn("value", DataType.TEXT))
480 .toTable(db);
481
482 Column col = t.getColumn("value");
483 PropertyMap props = col.getProperties();
484 props.put(PropertyMap.REQUIRED_PROP, true);
485 props.put(PropertyMap.ALLOW_ZERO_LEN_PROP, false);
486 props.save();
487
488 t.addRow(Column.AUTO_NUMBER, "v1");
489
490 try {
491 t.addRow(Column.AUTO_NUMBER, "");
492 fail("InvalidValueException should have been thrown");
493 } catch(InvalidValueException expected) {
494
495 }
496
497 try {
498 t.addRow(Column.AUTO_NUMBER, null);
499 fail("InvalidValueException should have been thrown");
500 } catch(InvalidValueException expected) {
501
502 }
503
504 t.addRow(Column.AUTO_NUMBER, "v2");
505
506 expectedRows =
507 createExpectedTable(
508 createExpectedRow(
509 "id", 1,
510 "value", "v1"),
511 createExpectedRow(
512 "id", 2,
513 "value", "v2"));
514 assertTable(expectedRows, t);
515
516 db.close();
517 }
518 }
519
520 public void testEnumValues() throws Exception
521 {
522 PropertyMaps maps = new PropertyMaps(10, null, null, null);
523
524 PropertyMapImpl colMap = maps.get("testcol");
525
526 colMap.put(PropertyMap.DISPLAY_CONTROL_PROP,
527 PropertyMap.DisplayControl.TEXT_BOX);
528
529 assertEquals(PropertyMap.DisplayControl.TEXT_BOX.getValue(),
530 colMap.getValue(PropertyMap.DISPLAY_CONTROL_PROP));
531 }
532
533 private static void checkProperties(PropertyMap propMap1,
534 PropertyMap propMap2)
535 {
536 assertEquals(propMap1.getSize(), propMap2.getSize());
537 for(PropertyMap.Property prop : propMap1) {
538 PropertyMap.Property prop2 = propMap2.get(prop.getName());
539
540 assertEquals(prop.getName(), prop2.getName());
541 assertEquals(prop.getType(), prop2.getType());
542
543 Object v1 = prop.getValue();
544 Object v2 = prop2.getValue();
545
546 if(v1 instanceof byte[]) {
547 assertTrue(Arrays.equals((byte[])v1, (byte[])v2));
548 } else {
549 assertEquals(v1, v2);
550 }
551 }
552 }
553
554 }