View Javadoc
1   /*
2   Copyright (c) 2013 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.Closeable;
20  import java.io.File;
21  import java.io.Flushable;
22  import java.io.IOException;
23  import java.nio.charset.Charset;
24  import java.util.ConcurrentModificationException;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.TimeZone;
30  
31  import com.healthmarketscience.jackcess.query.Query;
32  import com.healthmarketscience.jackcess.impl.DatabaseImpl;
33  import com.healthmarketscience.jackcess.util.ColumnValidatorFactory;
34  import com.healthmarketscience.jackcess.util.ErrorHandler;
35  import com.healthmarketscience.jackcess.util.LinkResolver;
36  import com.healthmarketscience.jackcess.util.TableIterableBuilder;
37  
38  /**
39   * An Access database instance.  A new instance can be instantiated by opening
40   * an existing database file ({@link DatabaseBuilder#open(File)}) or creating
41   * a new database file ({@link DatabaseBuilder#create(Database.FileFormat,File)}) (for
42   * more advanced opening/creating use {@link DatabaseBuilder}).  Once a
43   * Database has been opened, you can interact with the data via the relevant
44   * {@link Table}.  When a Database instance is no longer useful, it should
45   * <b>always</b> be closed ({@link #close}) to avoid corruption.
46   * <p/>
47   * Database instances (and all the related objects) are <i>not</i>
48   * thread-safe.  However, separate Database instances (and their respective
49   * objects) can be used by separate threads without a problem.
50   * <p/>
51   * Database instances do not implement any "transactional" support, and
52   * therefore concurrent editing of the same database file by multiple Database
53   * instances (or with outside programs such as MS Access) <i>will generally
54   * result in database file corruption</i>.
55   *
56   * @author James Ahlborn
57   * @usage _general_class_
58   */
59  public interface Database extends Iterable<Table>, Closeable, Flushable
60  {
61    /** default value for the auto-sync value ({@code true}).  this is slower,
62     *  but leaves more chance of a useable database in the face of failures.
63     * @usage _general_field_
64     */
65    public static final boolean DEFAULT_AUTO_SYNC = true;
66  
67    /**
68     * the default sort order for table columns.
69     * @usage _intermediate_field_
70     */
71    public static final Table.ColumnOrder DEFAULT_COLUMN_ORDER = 
72      Table.ColumnOrder.DATA;
73  
74    /** system property which can be used to set the default TimeZone used for
75     *  date calculations.
76     * @usage _general_field_
77     */
78    public static final String TIMEZONE_PROPERTY =
79      "com.healthmarketscience.jackcess.timeZone";
80  
81    /** system property prefix which can be used to set the default Charset
82     *  used for text data (full property includes the JetFormat version).
83     * @usage _general_field_
84     */
85    public static final String CHARSET_PROPERTY_PREFIX =
86      "com.healthmarketscience.jackcess.charset.";
87  
88    /** system property which can be used to set the path from which classpath
89     *  resources are loaded (must end with a "/" if non-empty).  Default value
90     *  is {@value com.healthmarketscience.jackcess.impl.DatabaseImpl#DEFAULT_RESOURCE_PATH}
91     *  if unspecified.
92     * @usage _general_field_
93     */
94    public static final String RESOURCE_PATH_PROPERTY = 
95      "com.healthmarketscience.jackcess.resourcePath";
96  
97    /** (boolean) system property which can be used to indicate that the current
98     *  vm has a poor nio implementation (specifically for
99     *  {@code FileChannel.transferFrom})
100    * @usage _intermediate_field_
101    */
102   public static final String BROKEN_NIO_PROPERTY = 
103     "com.healthmarketscience.jackcess.brokenNio";
104 
105   /** system property which can be used to set the default sort order for
106    *  table columns.  Value should be one {@link Table.ColumnOrder} enum
107    *  values.
108    * @usage _intermediate_field_
109    */
110   public static final String COLUMN_ORDER_PROPERTY = 
111     "com.healthmarketscience.jackcess.columnOrder";
112 
113   /** system property which can be used to set the default enforcement of
114    * foreign-key relationships.  Defaults to {@code true}.
115    * @usage _general_field_
116    */
117   public static final String FK_ENFORCE_PROPERTY = 
118     "com.healthmarketscience.jackcess.enforceForeignKeys";
119 
120   /** system property which can be used to set the default allow auto number
121    * insert policy.  Defaults to {@code false}.
122    * @usage _general_field_
123    */
124   public static final String ALLOW_AUTONUM_INSERT_PROPERTY = 
125     "com.healthmarketscience.jackcess.allowAutoNumberInsert";
126 
127   /**
128    * Enum which indicates which version of Access created the database.
129    * @usage _general_class_
130    */
131   public enum FileFormat {
132 
133     /** A database which was created by MS Access 97 */
134     V1997(".mdb"),
135     /** A database which was most likely created programmatically (e.g. using
136         windows ADOX) */
137     GENERIC_JET4(".mdb"),
138     /** A database which was created by MS Access 2000 */
139     V2000(".mdb"),
140     /** A database which was created by MS Access 2002/2003 */
141     V2003(".mdb"),
142     /** A database which was created by MS Access 2007 */
143     V2007(".accdb"),
144     /** A database which was created by MS Access 2010+ */
145     V2010(".accdb"),
146     /** A database which was created by MS Money */
147     MSISAM(".mny");
148 
149     private final String _ext;
150 
151     private FileFormat(String ext) {
152       _ext = ext;
153     }
154 
155     /**
156      * @return the file extension used for database files with this format.
157      */
158     public String getFileExtension() { return _ext; }
159 
160     @Override
161     public String toString() { 
162       return name() + " [" + DatabaseImpl.getFileFormatDetails(this).getFormat() + "]";
163     }
164   }
165 
166   /**
167    * Returns the File underlying this Database
168    */
169   public File getFile();
170 
171   /**
172    * @return The names of all of the user tables
173    * @usage _general_method_
174    */
175   public Set<String> getTableNames() throws IOException;
176 
177   /**
178    * @return The names of all of the system tables (String).  Note, in order
179    *         to read these tables, you must use {@link #getSystemTable}.
180    *         <i>Extreme care should be taken if modifying these tables
181    *         directly!</i>.
182    * @usage _intermediate_method_
183    */
184   public Set<String> getSystemTableNames() throws IOException;
185 
186   /**
187    * @return an unmodifiable Iterator of the user Tables in this Database.
188    * @throws RuntimeIOException if an IOException is thrown by one of the
189    *         operations, the actual exception will be contained within
190    * @throws ConcurrentModificationException if a table is added to the
191    *         database while an Iterator is in use.
192    * @usage _general_method_
193    */
194   public Iterator<Table> iterator();
195 
196   /**
197    * Convenience method for constructing a new TableIterableBuilder for this
198    * cursor.  A TableIterableBuilder provides a variety of options for more
199    * flexible iteration of Tables.
200    */
201   public TableIterableBuilder newIterable();
202   
203   /**
204    * @param name User table name (case-insensitive)
205    * @return The Table, or null if it doesn't exist (or is a system table)
206    * @usage _general_method_
207    */
208   public Table getTable(String name) throws IOException;
209 
210   /**
211    * @param name Table name (case-insensitive), may be any table type
212    *             (i.e. includes system or linked tables).
213    * @return The meta data for the table, or null if it doesn't exist
214    * @usage _intermediate_method_
215    */
216   public TableMetaData getTableMetaData(String name) throws IOException;
217 
218   /**
219    * Finds all the relationships in the database between the given tables.
220    * @usage _intermediate_method_
221    */
222   public List<Relationship> getRelationships(Table table1, Table table2)
223     throws IOException;
224 
225   /**
226    * Finds all the relationships in the database for the given table.
227    * @usage _intermediate_method_
228    */
229   public List<Relationship> getRelationships(Table table) throws IOException;
230 
231   /**
232    * Finds all the relationships in the database in <i>non-system</i> tables.
233    * </p>
234    * Warning, this may load <i>all</i> the Tables (metadata, not data) in the
235    * database which could cause memory issues.
236    * @usage _intermediate_method_
237    */
238   public List<Relationship> getRelationships() throws IOException;
239 
240   /**
241    * Finds <i>all</i> the relationships in the database, <i>including system
242    * tables</i>.
243    * </p>
244    * Warning, this may load <i>all</i> the Tables (metadata, not data) in the
245    * database which could cause memory issues.
246    * @usage _intermediate_method_
247    */
248   public List<Relationship> getSystemRelationships()
249     throws IOException;
250 
251   /**
252    * Finds all the queries in the database.
253    * @usage _intermediate_method_
254    */
255   public List<Query> getQueries() throws IOException;
256 
257   /**
258    * Returns a reference to <i>any</i> available table in this access
259    * database, including system tables.
260    * <p>
261    * Warning, this method is not designed for common use, only for the
262    * occassional time when access to a system table is necessary.  Messing
263    * with system tables can strip the paint off your house and give your whole
264    * family a permanent, orange afro.  You have been warned.
265    * 
266    * @param tableName Table name, may be a system table
267    * @return The table, or {@code null} if it doesn't exist
268    * @usage _intermediate_method_
269    */
270   public Table getSystemTable(String tableName) throws IOException;
271 
272   /**
273    * @return the core properties for the database
274    * @usage _general_method_
275    */
276   public PropertyMap getDatabaseProperties() throws IOException;
277 
278   /**
279    * @return the summary properties for the database
280    * @usage _general_method_
281    */
282   public PropertyMap getSummaryProperties() throws IOException;
283 
284   /**
285    * @return the user-defined properties for the database
286    * @usage _general_method_
287    */
288   public PropertyMap getUserDefinedProperties() throws IOException;
289 
290   /**
291    * @return the current database password, or {@code null} if none set.
292    * @usage _general_method_
293    */
294   public String getDatabasePassword() throws IOException;
295 
296   /**
297    * Create a new table in this database
298    * @param name Name of the table to create in this database
299    * @param linkedDbName path to the linked database
300    * @param linkedTableName name of the table in the linked database
301    * @usage _general_method_
302    */
303   public void createLinkedTable(String name, String linkedDbName,
304                                 String linkedTableName)
305     throws IOException;
306 
307   /**
308    * Flushes any current changes to the database file (and any linked
309    * databases) to disk.
310    * @usage _general_method_
311    */
312   public void flush() throws IOException;
313 
314   /**
315    * Close the database file (and any linked databases).  A Database
316    * <b>must</b> be closed after use or changes could be lost and the Database
317    * file corrupted.  A Database instance should be treated like any other
318    * external resource which would be closed in a finally block (e.g. an
319    * OutputStream or jdbc Connection).
320    * @usage _general_method_
321    */
322   public void close() throws IOException;
323 
324   /**
325    * Gets the currently configured ErrorHandler (always non-{@code null}).
326    * This will be used to handle all errors unless overridden at the Table or
327    * Cursor level.
328    * @usage _intermediate_method_
329    */
330   public ErrorHandler getErrorHandler();
331 
332   /**
333    * Sets a new ErrorHandler.  If {@code null}, resets to the
334    * {@link ErrorHandler#DEFAULT}.
335    * @usage _intermediate_method_
336    */
337   public void setErrorHandler(ErrorHandler newErrorHandler);
338 
339   /**
340    * Gets the currently configured LinkResolver (always non-{@code null}).
341    * This will be used to handle all linked database loading.
342    * @usage _intermediate_method_
343    */
344   public LinkResolver getLinkResolver();
345 
346   /**
347    * Sets a new LinkResolver.  If {@code null}, resets to the
348    * {@link LinkResolver#DEFAULT}.
349    * @usage _intermediate_method_
350    */
351   public void setLinkResolver(LinkResolver newLinkResolver);
352 
353   /**
354    * Returns an unmodifiable view of the currently loaded linked databases,
355    * mapped from the linked database file name to the linked database.  This
356    * information may be useful for implementing a LinkResolver.
357    * @usage _intermediate_method_
358    */
359   public Map<String,Database> getLinkedDatabases();
360 
361   
362   /**
363    * Returns {@code true} if this Database links to the given Table, {@code
364    * false} otherwise.
365    * @usage _general_method_
366    */
367   public boolean isLinkedTable(Table table) throws IOException;
368   
369   /**
370    * Gets currently configured TimeZone (always non-{@code null}).
371    * @usage _intermediate_method_
372    */
373   public TimeZone getTimeZone();
374 
375   /**
376    * Sets a new TimeZone.  If {@code null}, resets to the default value.
377    * @usage _intermediate_method_
378    */
379   public void setTimeZone(TimeZone newTimeZone);
380 
381   /**
382    * Gets currently configured Charset (always non-{@code null}).
383    * @usage _intermediate_method_
384    */
385   public Charset getCharset();
386 
387   /**
388    * Sets a new Charset.  If {@code null}, resets to the default value.
389    * @usage _intermediate_method_
390    */
391   public void setCharset(Charset newCharset);
392 
393   /**
394    * Gets currently configured {@link Table.ColumnOrder} (always non-{@code
395    * null}).
396    * @usage _intermediate_method_
397    */
398   public Table.ColumnOrder getColumnOrder();
399 
400   /**
401    * Sets a new Table.ColumnOrder.  If {@code null}, resets to the default value.
402    * @usage _intermediate_method_
403    */
404   public void setColumnOrder(Table.ColumnOrder newColumnOrder);
405 
406   /**
407    * Gets current foreign-key enforcement policy.
408    * @usage _intermediate_method_
409    */
410   public boolean isEnforceForeignKeys();
411 
412   /**
413    * Sets a new foreign-key enforcement policy.  If {@code null}, resets to
414    * the default value.
415    * @usage _intermediate_method_
416    */
417   public void setEnforceForeignKeys(Boolean newEnforceForeignKeys);
418 
419   /**
420    * Gets current allow auto number insert policy.  By default, jackcess does
421    * not allow auto numbers to be inserted or updated directly (they are
422    * always handled internally by the Table).  Setting this policy to {@code
423    * true} allows the caller to optionally set the value explicitly when
424    * adding or updating rows (if a value is not provided, it will still be
425    * handled internally by the Table).  This value can be set database-wide
426    * using {@link #setAllowAutoNumberInsert} and/or on a per-table basis using
427    * {@link Table#setAllowAutoNumberInsert} (and/or on a jvm-wide using the
428    * {@link #ALLOW_AUTONUM_INSERT_PROPERTY} system property).  Note that
429    * <i>enabling this feature should be done with care</i> to reduce the
430    * chances of screwing up the database.
431    * 
432    * @usage _intermediate_method_
433    */
434   public boolean isAllowAutoNumberInsert();
435 
436   /**
437    * Sets the new auto number insert policy for the database (unless
438    * overridden at the Table level).  If {@code null}, resets to the default
439    * value.
440    * @usage _intermediate_method_
441    */
442   public void setAllowAutoNumberInsert(Boolean allowAutoNumInsert);
443 
444   /**
445    * Gets currently configured ColumnValidatorFactory (always non-{@code null}).
446    * @usage _intermediate_method_
447    */
448   public ColumnValidatorFactory getColumnValidatorFactory();
449 
450   /**
451    * Sets a new ColumnValidatorFactory.  If {@code null}, resets to the
452    * default value.  The configured ColumnValidatorFactory will be used to
453    * create ColumnValidator instances on any <i>user</i> tables loaded from
454    * this point onward (this will not be used for system tables).
455    * @usage _intermediate_method_
456    */
457   public void setColumnValidatorFactory(ColumnValidatorFactory newFactory);
458   
459   /**
460    * Returns the FileFormat of this database (which may involve inspecting the
461    * database itself).
462    * @throws IllegalStateException if the file format cannot be determined
463    * @usage _general_method_
464    */
465   public FileFormat getFileFormat() throws IOException;
466 
467 }