View Javadoc
1   /*
2   Copyright (c) 2011 James Ahlborn
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
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.UUID;
25  
26  import static com.healthmarketscience.jackcess.Database.*;
27  import com.healthmarketscience.jackcess.impl.DatabaseImpl;
28  import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
29  import com.healthmarketscience.jackcess.impl.PropertyMapImpl;
30  import com.healthmarketscience.jackcess.impl.PropertyMaps;
31  import com.healthmarketscience.jackcess.impl.TableImpl;
32  import junit.framework.TestCase;
33  import static com.healthmarketscience.jackcess.TestUtil.*;
34  
35  /**
36   * @author James Ahlborn
37   */
38  public class PropertiesTest extends TestCase
39  {
40  
41    public PropertiesTest(String name) throws Exception {
42      super(name);
43    }
44  
45    public void testPropertyMaps() throws Exception
46    {
47      PropertyMaps maps = new PropertyMaps(10, null, null);
48      assertTrue(maps.isEmpty());
49      assertEquals(0, maps.getSize());
50      assertFalse(maps.iterator().hasNext());
51      assertEquals(10, maps.getObjectId());
52  
53      PropertyMapImpl defMap = maps.getDefault();
54      assertTrue(defMap.isEmpty());
55      assertEquals(0, defMap.getSize());
56      assertFalse(defMap.iterator().hasNext());
57  
58      PropertyMapImpl colMap = maps.get("testcol");
59      assertTrue(colMap.isEmpty());
60      assertEquals(0, colMap.getSize());
61      assertFalse(colMap.iterator().hasNext());
62      
63      assertFalse(maps.isEmpty());
64      assertEquals(2, maps.getSize());
65      
66      assertSame(defMap, maps.get(PropertyMaps.DEFAULT_NAME));
67      assertEquals(PropertyMaps.DEFAULT_NAME, defMap.getName());
68      assertSame(colMap, maps.get("TESTCOL"));
69      assertEquals("testcol", colMap.getName());
70  
71      defMap.put("foo", DataType.TEXT, (byte)0, "bar");
72      defMap.put("baz", DataType.LONG, (byte)1, 13);
73  
74      assertFalse(defMap.isEmpty());
75      assertEquals(2, defMap.getSize());
76  
77      colMap.put("buzz", DataType.BOOLEAN, (byte)0, Boolean.TRUE);
78  
79      assertFalse(colMap.isEmpty());
80      assertEquals(1, colMap.getSize());
81  
82      assertEquals("bar", defMap.getValue("foo"));
83      assertEquals("bar", defMap.getValue("FOO"));
84      assertNull(colMap.getValue("foo"));
85      assertEquals(13, defMap.get("baz").getValue());
86      assertEquals(Boolean.TRUE, colMap.getValue("Buzz"));
87  
88      assertEquals("bar", defMap.getValue("foo", "blah"));
89      assertEquals("blah", defMap.getValue("bogus", "blah"));
90  
91      List<PropertyMap.Property> props = new ArrayList<PropertyMap.Property>();
92      for(PropertyMap map : maps) {
93        for(PropertyMap.Property prop : map) {
94          props.add(prop);
95        }
96      }
97  
98      assertEquals(Arrays.asList(defMap.get("foo"), defMap.get("baz"), 
99                                 colMap.get("buzz")), props);
100   }
101 
102   public void testInferTypes() throws Exception
103   {
104     PropertyMaps maps = new PropertyMaps(10, null, null);
105     PropertyMap defMap = maps.getDefault();
106 
107     assertEquals(DataType.TEXT, 
108                  defMap.put(PropertyMap.FORMAT_PROP, null).getType());
109     assertEquals(DataType.BOOLEAN, 
110                  defMap.put(PropertyMap.REQUIRED_PROP, null).getType());
111 
112     assertEquals(DataType.TEXT, 
113                  defMap.put("strprop", "this is a string").getType());
114     assertEquals(DataType.BOOLEAN, 
115                  defMap.put("boolprop", true).getType());
116     assertEquals(DataType.LONG, 
117                  defMap.put("intprop", 37).getType());
118   }
119 
120   public void testReadProperties() throws Exception
121   {
122     byte[] nameMapBytes = null;
123 
124     for(TestDB testDb : SUPPORTED_DBS_TEST_FOR_READ) {
125       Database db = open(testDb);
126 
127       TableImpl t = (TableImpl)db.getTable("Table1");
128       assertEquals(t.getTableDefPageNumber(), 
129                    t.getPropertyMaps().getObjectId());
130       PropertyMap tProps = t.getProperties();
131       assertEquals(PropertyMaps.DEFAULT_NAME, tProps.getName());
132       int expectedNumProps = 3;
133       if(db.getFileFormat() != Database.FileFormat.V1997) {
134         assertEquals("{5A29A676-1145-4D1A-AE47-9F5415CDF2F1}", 
135                      tProps.getValue(PropertyMap.GUID_PROP));
136         if(nameMapBytes == null) {
137           nameMapBytes = (byte[])tProps.getValue("NameMap");
138         } else {
139           assertTrue(Arrays.equals(nameMapBytes, 
140                                    (byte[])tProps.getValue("NameMap")));
141         }
142         expectedNumProps += 2;
143       }  
144       assertEquals(expectedNumProps, tProps.getSize());
145       assertEquals((byte)0, tProps.getValue("Orientation"));
146       assertEquals(Boolean.FALSE, tProps.getValue("OrderByOn"));
147       assertEquals((byte)2, tProps.getValue("DefaultView"));
148 
149       PropertyMap colProps = t.getColumn("A").getProperties();
150       assertEquals("A", colProps.getName());
151       expectedNumProps = 9;
152       if(db.getFileFormat() != Database.FileFormat.V1997) {
153         assertEquals("{E9EDD90C-CE55-4151-ABE1-A1ACE1007515}", 
154                      colProps.getValue(PropertyMap.GUID_PROP));
155         ++expectedNumProps;
156       }
157       assertEquals(expectedNumProps, colProps.getSize());
158       assertEquals((short)-1, colProps.getValue("ColumnWidth"));
159       assertEquals((short)0, colProps.getValue("ColumnOrder"));
160       assertEquals(Boolean.FALSE, colProps.getValue("ColumnHidden"));
161       assertEquals(Boolean.FALSE, 
162                    colProps.getValue(PropertyMap.REQUIRED_PROP));
163       assertEquals(Boolean.FALSE, 
164                    colProps.getValue(PropertyMap.ALLOW_ZERO_LEN_PROP));
165       assertEquals((short)109, colProps.getValue("DisplayControl"));
166       assertEquals(Boolean.TRUE, colProps.getValue("UnicodeCompression"));
167       assertEquals((byte)0, colProps.getValue("IMEMode"));
168       assertEquals((byte)3, colProps.getValue("IMESentenceMode"));
169 
170       PropertyMap dbProps = db.getDatabaseProperties();
171       assertTrue(((String)dbProps.getValue(PropertyMap.ACCESS_VERSION_PROP))
172                  .matches("[0-9]{2}[.][0-9]{2}"));
173 
174       PropertyMap sumProps = db.getSummaryProperties();
175       assertEquals(3, sumProps.getSize());
176       assertEquals("test", sumProps.getValue(PropertyMap.TITLE_PROP));
177       assertEquals("tmccune", sumProps.getValue(PropertyMap.AUTHOR_PROP));
178       assertEquals("Health Market Science", sumProps.getValue(PropertyMap.COMPANY_PROP));
179 
180       PropertyMap userProps = db.getUserDefinedProperties();
181       assertEquals(1, userProps.getSize());
182       assertEquals(Boolean.TRUE, userProps.getValue("ReplicateProject"));
183 
184       db.close();
185     }
186   }
187 
188   public void testParseProperties() throws Exception
189   {
190     for(FileFormat ff : SUPPORTED_FILEFORMATS_FOR_READ) {
191       File[] dbFiles = new File(DIR_TEST_DATA, ff.name()).listFiles();
192       if(dbFiles == null) {
193         continue;
194       }
195       for(File f : dbFiles) {
196 
197         if(!f.isFile()) {
198           continue;
199         }
200 
201         Database db = open(ff, f);
202 
203         PropertyMap dbProps = db.getDatabaseProperties();
204         assertFalse(dbProps.isEmpty());
205         assertTrue(((String)dbProps.getValue(PropertyMap.ACCESS_VERSION_PROP))
206                    .matches("[0-9]{2}[.][0-9]{2}"));
207 
208         for(Row row : ((DatabaseImpl)db).getSystemCatalog()) {
209           int id = row.getInt("Id");
210           byte[] propBytes = row.getBytes("LvProp");
211           PropertyMaps propMaps = ((DatabaseImpl)db).getPropertiesForObject(id);
212           int byteLen = ((propBytes != null) ? propBytes.length : 0);
213           if(byteLen == 0) {
214             assertTrue(propMaps.isEmpty());
215           } else if(propMaps.isEmpty()) {
216             assertTrue(byteLen < 80);
217           } else {
218             assertTrue(byteLen > 0);
219           }
220         }
221 
222         db.close();
223       }
224     }
225   }
226 
227   public void testWriteProperties() throws Exception
228   {
229     for(TestDB testDb : SUPPORTED_DBS_TEST) {
230       Database db = open(testDb);
231 
232       TableImpl t = (TableImpl)db.getTable("Table1");
233 
234       PropertyMap tProps = t.getProperties();
235 
236       PropertyMaps maps = ((PropertyMapImpl)tProps).getOwner();
237 
238       byte[] mapsBytes = maps.write();
239 
240       PropertyMaps maps2 = ((DatabaseImpl)db).readProperties(
241           mapsBytes, maps.getObjectId(), null);
242 
243       Iterator<PropertyMapImpl> iter = maps.iterator();
244       Iterator<PropertyMapImpl> iter2 = maps2.iterator();
245 
246       while(iter.hasNext() && iter2.hasNext()) {
247         PropertyMapImpl propMap = iter.next();
248         PropertyMapImpl propMap2 = iter2.next();
249 
250         checkProperties(propMap, propMap2);
251       }
252       
253       assertFalse(iter.hasNext());
254       assertFalse(iter2.hasNext());
255 
256       db.close();
257     }    
258   }
259 
260   public void testModifyProperties() throws Exception
261   {
262     for(TestDB testDb : SUPPORTED_DBS_TEST) {
263       Database db = openCopy(testDb);
264       File dbFile = db.getFile();
265 
266       Table t = db.getTable("Table1");
267 
268       // grab originals
269       PropertyMap origCProps = t.getColumn("C").getProperties();
270       PropertyMap origFProps = t.getColumn("F").getProperties();
271       PropertyMap origDProps = t.getColumn("D").getProperties();
272 
273       db.close();
274 
275 
276       // modify but do not save
277       db = new DatabaseBuilder(dbFile).open();
278 
279       t = db.getTable("Table1");
280 
281       PropertyMap cProps = t.getColumn("C").getProperties();
282       PropertyMap fProps = t.getColumn("F").getProperties();
283       PropertyMap dProps = t.getColumn("D").getProperties();
284 
285       assertFalse((Boolean)cProps.getValue(PropertyMap.REQUIRED_PROP));
286       assertEquals("0", fProps.getValue(PropertyMap.DEFAULT_VALUE_PROP));
287       assertEquals((short)109, dProps.getValue("DisplayControl"));
288 
289       cProps.put(PropertyMap.REQUIRED_PROP, DataType.BOOLEAN, true);
290       fProps.get(PropertyMap.DEFAULT_VALUE_PROP).setValue("42");
291       dProps.remove("DisplayControl");
292 
293       db.close();
294 
295 
296       // modify and save
297       db = new DatabaseBuilder(dbFile).open();
298 
299       t = db.getTable("Table1");
300 
301       cProps = t.getColumn("C").getProperties();
302       fProps = t.getColumn("F").getProperties();
303       dProps = t.getColumn("D").getProperties();
304 
305       assertFalse((Boolean)cProps.getValue(PropertyMap.REQUIRED_PROP));
306       assertEquals("0", fProps.getValue(PropertyMap.DEFAULT_VALUE_PROP));
307       assertEquals((short)109, dProps.getValue("DisplayControl"));
308 
309       checkProperties(origCProps, cProps);
310       checkProperties(origFProps, fProps);
311       checkProperties(origDProps, dProps);
312 
313       cProps.put(PropertyMap.REQUIRED_PROP, DataType.BOOLEAN, true);
314       cProps.save();
315       fProps.get(PropertyMap.DEFAULT_VALUE_PROP).setValue("42");
316       fProps.save();
317       dProps.remove("DisplayControl");
318       dProps.save();
319 
320       db.close();
321 
322 
323       // reload saved props
324       db = new DatabaseBuilder(dbFile).open();
325 
326       t = db.getTable("Table1");
327 
328       cProps = t.getColumn("C").getProperties();
329       fProps = t.getColumn("F").getProperties();
330       dProps = t.getColumn("D").getProperties();
331 
332       assertTrue((Boolean)cProps.getValue(PropertyMap.REQUIRED_PROP));
333       assertEquals("42", fProps.getValue(PropertyMap.DEFAULT_VALUE_PROP));
334       assertNull(dProps.getValue("DisplayControl"));      
335 
336       cProps.put(PropertyMap.REQUIRED_PROP, DataType.BOOLEAN, false);
337       fProps.get(PropertyMap.DEFAULT_VALUE_PROP).setValue("0");
338       dProps.put("DisplayControl", DataType.INT, (short)109);
339 
340       checkProperties(origCProps, cProps);
341       checkProperties(origFProps, fProps);
342       checkProperties(origDProps, dProps);
343 
344       db.close();
345     }
346   }
347 
348   public void testCreateDbProperties() throws Exception
349   {
350     for(FileFormat ff : SUPPORTED_FILEFORMATS) {
351 
352       if(ff == FileFormat.GENERIC_JET4) {
353         // weirdo format, no properties
354         continue;
355       }
356       
357       File file = TestUtil.createTempFile(false);
358       Database db = new DatabaseBuilder(file)
359         .setFileFormat(ff)
360         .putUserDefinedProperty("testing", "123")
361         .create();
362 
363       UUID u1 = UUID.randomUUID();
364       UUID u2 = UUID.randomUUID();
365       Table t = new TableBuilder("Test")
366         .putProperty("awesome_table", true)
367         .addColumn(new ColumnBuilder("id", DataType.LONG)
368                    .setAutoNumber(true)
369                    .putProperty(PropertyMap.REQUIRED_PROP, true)
370                    .putProperty(PropertyMap.GUID_PROP, u1))
371         .addColumn(new ColumnBuilder("data", DataType.TEXT)
372                    .putProperty(PropertyMap.ALLOW_ZERO_LEN_PROP, false)
373                    .putProperty(PropertyMap.GUID_PROP, u2))
374         .toTable(db);
375 
376       t.addRow(Column.AUTO_NUMBER, "value");
377 
378       db.close();
379 
380       db = new DatabaseBuilder(file).open();
381       
382       assertEquals("123", db.getUserDefinedProperties().getValue("testing"));
383 
384       t = db.getTable("Test");
385 
386       assertEquals(Boolean.TRUE, 
387                    t.getProperties().getValue("awesome_table"));
388 
389       Column c = t.getColumn("id");
390       assertEquals(Boolean.TRUE, 
391                    c.getProperties().getValue(PropertyMap.REQUIRED_PROP));
392       assertEquals("{" + u1.toString().toUpperCase() + "}",
393                    c.getProperties().getValue(PropertyMap.GUID_PROP));
394 
395       c = t.getColumn("data");
396       assertEquals(Boolean.FALSE,
397                    c.getProperties().getValue(PropertyMap.ALLOW_ZERO_LEN_PROP));
398       assertEquals("{" + u2.toString().toUpperCase() + "}", 
399                    c.getProperties().getValue(PropertyMap.GUID_PROP));
400 
401     }
402   }
403 
404   private static void checkProperties(PropertyMap propMap1, 
405                                       PropertyMap propMap2)
406   {
407     assertEquals(propMap1.getSize(), propMap2.getSize());
408     for(PropertyMap.Property prop : propMap1) {
409       PropertyMap.Property prop2 = propMap2.get(prop.getName());
410 
411       assertEquals(prop.getName(), prop2.getName());
412       assertEquals(prop.getType(), prop2.getType());
413 
414       Object v1 = prop.getValue();
415       Object v2 = prop2.getValue();
416 
417       if(v1 instanceof byte[]) {
418         assertTrue(Arrays.equals((byte[])v1, (byte[])v2));
419       } else {
420         assertEquals(v1, v2);
421       }
422     }
423   }
424 
425 }