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