From d608f41a7ac08274eed9adc95ae18674050c8720 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Tue, 9 Sep 2014 01:03:04 +0000 Subject: [PATCH] add ability to set properties in the various Bulders git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@870 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 4 + .../jackcess/ColumnBuilder.java | 36 +++++- .../jackcess/DatabaseBuilder.java | 105 +++++++++++++++++- .../jackcess/PropertyMap.java | 23 ++++ .../jackcess/TableBuilder.java | 51 ++++++++- .../jackcess/impl/PropertyMapImpl.java | 87 ++++++++++++++- 6 files changed, 294 insertions(+), 12 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ccc033a..8ef8f7e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -14,6 +14,10 @@ Jackcess will not evaluate the actual expressions, but the column values can be written directly. + + Add the ability to set properties in DatabaseBuilder, TableBuilder, + and ColumnBuilder. + diff --git a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java index dc0b566..57c5bb5 100644 --- a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java +++ b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java @@ -28,12 +28,15 @@ King of Prussia, PA 19406 package com.healthmarketscience.jackcess; import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import com.healthmarketscience.jackcess.impl.ColumnImpl; -import com.healthmarketscience.jackcess.impl.JetFormat; import com.healthmarketscience.jackcess.impl.DatabaseImpl; +import com.healthmarketscience.jackcess.impl.JetFormat; +import com.healthmarketscience.jackcess.impl.PropertyMapImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * Builder style class for constructing a {@link Column}. See {@link @@ -66,6 +69,8 @@ public class ColumnBuilder { private short _columnNumber; /** the collating sort order for a text field */ private ColumnImpl.SortOrder _sortOrder; + /** table properties (if any) */ + private Map _props; public ColumnBuilder(String name) { @@ -198,6 +203,31 @@ public class ColumnBuilder { return _hyperlink; } + /** + * Sets the column property with the given name to the given value. Attempts + * to determine the type of the property (see + * {@link PropertyMap#put(String,Object)} for details on determining the + * property type). + */ + public ColumnBuilder putProperty(String name, Object value) { + return putProperty(name, null, value); + } + + /** + * Sets the column property with the given name and type to the given value. + */ + public ColumnBuilder putProperty(String name, DataType type, Object value) { + if(_props == null) { + _props = new HashMap(); + } + _props.put(name, PropertyMapImpl.createProperty(name, type, value)); + return this; + } + + public Map getProperties() { + return _props; + } + /** * Sets all attributes except name from the given Column template. */ diff --git a/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java b/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java index 7e40c10..c1dc889 100644 --- a/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java +++ b/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java @@ -23,10 +23,13 @@ import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; import java.util.TimeZone; -import com.healthmarketscience.jackcess.impl.DatabaseImpl; import com.healthmarketscience.jackcess.impl.CodecProvider; +import com.healthmarketscience.jackcess.impl.DatabaseImpl; +import com.healthmarketscience.jackcess.impl.PropertyMapImpl; import com.healthmarketscience.jackcess.util.MemFileChannel; /** @@ -66,7 +69,14 @@ public class DatabaseBuilder /** optional pre-opened FileChannel, will _not_ be closed by Database close */ private FileChannel _channel; + /** database properties (if any) */ + private Map _dbProps; + /** database summary properties (if any) */ + private Map _summaryProps; + /** database user-defined (if any) */ + private Map _userProps; + public DatabaseBuilder() { this(null); } @@ -163,6 +173,77 @@ public class DatabaseBuilder return this; } + /** + * Sets the database property with the given name to the given value. + * Attempts to determine the type of the property (see + * {@link PropertyMap#put(String,Object)} for details on determining the + * property type). + */ + public DatabaseBuilder putDatabaseProperty(String name, Object value) { + return putDatabaseProperty(name, null, value); + } + + /** + * Sets the database property with the given name and type to the given + * value. + */ + public DatabaseBuilder putDatabaseProperty(String name, DataType type, + Object value) { + _dbProps = putProperty(_dbProps, name, type, value); + return this; + } + + /** + * Sets the summary database property with the given name to the given + * value. Attempts to determine the type of the property (see + * {@link PropertyMap#put(String,Object)} for details on determining the + * property type). + */ + public DatabaseBuilder putSummaryProperty(String name, Object value) { + return putSummaryProperty(name, null, value); + } + + /** + * Sets the summary database property with the given name and type to + * the given value. + */ + public DatabaseBuilder putSummaryProperty(String name, DataType type, + Object value) { + _summaryProps = putProperty(_summaryProps, name, type, value); + return this; + } + + /** + * Sets the user-defined database property with the given name to the given + * value. Attempts to determine the type of the property (see + * {@link PropertyMap#put(String,Object)} for details on determining the + * property type). + */ + public DatabaseBuilder putUserDefinedProperty(String name, Object value) { + return putUserDefinedProperty(name, null, value); + } + + /** + * Sets the user-defined database property with the given name and type to + * the given value. + */ + public DatabaseBuilder putUserDefinedProperty(String name, DataType type, + Object value) { + _userProps = putProperty(_userProps, name, type, value); + return this; + } + + private static Map putProperty( + Map props, String name, DataType type, + Object value) + { + if(props == null) { + props = new HashMap(); + } + props.put(name, PropertyMapImpl.createProperty(name, type, value)); + return props; + } + /** * Opens an existingnew Database using the configured information. */ @@ -175,8 +256,24 @@ public class DatabaseBuilder * Creates a new Database using the configured information. */ public Database create() throws IOException { - return DatabaseImpl.create(_fileFormat, _mdbFile, _channel, _autoSync, - _charset, _timeZone); + Database db = DatabaseImpl.create(_fileFormat, _mdbFile, _channel, _autoSync, + _charset, _timeZone); + if(_dbProps != null) { + PropertyMap props = db.getDatabaseProperties(); + props.putAll(_dbProps.values()); + props.save(); + } + if(_summaryProps != null) { + PropertyMap props = db.getSummaryProperties(); + props.putAll(_summaryProps.values()); + props.save(); + } + if(_userProps != null) { + PropertyMap props = db.getUserDefinedProperties(); + props.putAll(_userProps.values()); + props.save(); + } + return db; } /** @@ -208,6 +305,4 @@ public class DatabaseBuilder { return new DatabaseBuilder(mdbFile).setFileFormat(fileFormat).create(); } - - } diff --git a/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java b/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java index 779d92b..f411bfd 100644 --- a/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java +++ b/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java @@ -71,6 +71,21 @@ public interface PropertyMap extends Iterable */ public Object getValue(String name, Object defaultValue); + /** + * Creates a new (or updates an existing) property in the map. Attempts to + * determine the type of the property based on the name and value (the + * property names listed above have their types builtin, otherwise the type + * of the value is used). + *

+ * Note, this change will not be persisted until the {@link #save} method + * has been called. + * + * @return the newly created (or updated) property + * @throws IllegalArgumentException if the type of the property could not be + * determined automatically + */ + public Property put(String name, Object value); + /** * Creates a new (or updates an existing) property in the map. *

@@ -81,6 +96,14 @@ public interface PropertyMap extends Iterable */ public Property put(String name, DataType type, Object value); + /** + * Puts all the given properties into this map. + * + * @props the properties to put into this map ({@code null} is tolerated and + * ignored). + */ + public void putAll(Iterable props); + /** * Removes the property with the given name * diff --git a/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java b/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java index 9f63796..b28d35b 100644 --- a/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java +++ b/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java @@ -31,11 +31,14 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import com.healthmarketscience.jackcess.impl.DatabaseImpl; +import com.healthmarketscience.jackcess.impl.PropertyMapImpl; /** * Builder style class for constructing a {@link Table}. @@ -108,8 +111,10 @@ public class TableBuilder { private List _indexes = new ArrayList(); /** whether or not table/column/index names are automatically escaped */ private boolean _escapeIdentifiers; - + /** table properties (if any) */ + private Map _props; + public TableBuilder(String name) { this(name, false); } @@ -187,6 +192,27 @@ public class TableBuilder { return this; } + /** + * Sets the table property with the given name to the given value. Attempts + * to determine the type of the property (see + * {@link PropertyMap#put(String,Object)} for details on determining the + * property type). + */ + public TableBuilder putProperty(String name, Object value) { + return putProperty(name, null, value); + } + + /** + * Sets the table property with the given name and type to the given value. + */ + public TableBuilder putProperty(String name, DataType type, Object value) { + if(_props == null) { + _props = new HashMap(); + } + _props.put(name, PropertyMapImpl.createProperty(name, type, value)); + return this; + } + /** * Creates a new Table in the given Database with the currently configured * attributes. @@ -195,7 +221,27 @@ public class TableBuilder { throws IOException { ((DatabaseImpl)db).createTable(_name, _columns, _indexes); - return db.getTable(_name); + Table table = db.getTable(_name); + + boolean addedProps = false; + if(_props != null) { + table.getProperties().putAll(_props.values()); + addedProps = true; + } + for(ColumnBuilder cb : _columns) { + Map colProps = cb.getProperties(); + if(colProps != null) { + table.getColumn(cb.getName()).getProperties().putAll(colProps.values()); + addedProps = true; + } + } + + // all table and column props are saved together + if(addedProps) { + table.getProperties().save(); + } + + return table; } /** @@ -218,5 +264,4 @@ public class TableBuilder { return ReservedWords.VALUES.contains(s.toLowerCase()); } - } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java index 11bdf21..3c14be2 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java @@ -20,6 +20,8 @@ USA package com.healthmarketscience.jackcess.impl; import java.io.IOException; +import java.util.Date; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; @@ -34,6 +36,30 @@ import com.healthmarketscience.jackcess.PropertyMap; */ public class PropertyMapImpl implements PropertyMap { + private static final Map DEFAULT_TYPES = + new HashMap(); + + static { + DEFAULT_TYPES.put(ACCESS_VERSION_PROP, DataType.TEXT); + DEFAULT_TYPES.put(TITLE_PROP, DataType.TEXT); + DEFAULT_TYPES.put(AUTHOR_PROP, DataType.TEXT); + DEFAULT_TYPES.put(COMPANY_PROP, DataType.TEXT); + + DEFAULT_TYPES.put(DEFAULT_VALUE_PROP, DataType.MEMO); + DEFAULT_TYPES.put(REQUIRED_PROP, DataType.BOOLEAN); + DEFAULT_TYPES.put(ALLOW_ZERO_LEN_PROP, DataType.MEMO); + DEFAULT_TYPES.put(DECIMAL_PLACES_PROP, DataType.BYTE); + DEFAULT_TYPES.put(FORMAT_PROP, DataType.TEXT); + DEFAULT_TYPES.put(INPUT_MASK_PROP, DataType.TEXT); + DEFAULT_TYPES.put(CAPTION_PROP, DataType.MEMO); + DEFAULT_TYPES.put(VALIDATION_RULE_PROP, DataType.TEXT); + DEFAULT_TYPES.put(VALIDATION_TEXT_PROP, DataType.TEXT); + DEFAULT_TYPES.put(GUID_PROP, DataType.BINARY); + DEFAULT_TYPES.put(DESCRIPTION_PROP, DataType.MEMO); + DEFAULT_TYPES.put(RESULT_TYPE_PROP, DataType.BYTE); + DEFAULT_TYPES.put(EXPRESSION_PROP, DataType.MEMO); + } + private final String _mapName; private final short _mapType; private final Map _props = @@ -83,15 +109,33 @@ public class PropertyMapImpl implements PropertyMap return value; } + public PropertyImpl put(String name, Object value) { + return put(name, null, (byte)0, value); + } + public PropertyImpl put(String name, DataType type, Object value) { return put(name, type, (byte)0, value); } + public void putAll(Iterable props) { + if(props == null) { + return; + } + + for(Property prop : props) { + byte flag = 0; + if(prop instanceof PropertyImpl) { + flag = ((PropertyImpl)prop).getFlag(); + } + put(prop.getName(), prop.getType(), flag, prop.getValue()); + } + } + /** * Puts a property into this map with the given information. */ public PropertyImpl put(String name, DataType type, byte flag, Object value) { - PropertyImpl prop = new PropertyImpl(name, type, flag, value); + PropertyImpl prop = (PropertyImpl)createProperty(name, type, flag, value); _props.put(DatabaseImpl.toLookupName(name), prop); return prop; } @@ -124,6 +168,47 @@ public class PropertyMapImpl implements PropertyMap return sb.toString(); } + public static Property createProperty(String name, DataType type, Object value) { + return createProperty(name, type, (byte)0, value); + } + + public static Property createProperty(String name, DataType type, byte flag, + Object value) { + if(type == null) { + + // attempt to figure out the type + type = DEFAULT_TYPES.get(type); + + if(type == null) { + if(value instanceof String) { + type = DataType.TEXT; + } else if(value instanceof Boolean) { + type = DataType.BOOLEAN; + } else if(value instanceof Byte) { + type = DataType.BYTE; + } else if(value instanceof Short) { + type = DataType.INT; + } else if(value instanceof Integer) { + type = DataType.LONG; + } else if(value instanceof Float) { + type = DataType.FLOAT; + } else if(value instanceof Double) { + type = DataType.DOUBLE; + } else if(value instanceof Date) { + type = DataType.SHORT_DATE_TIME; + } else if(value instanceof byte[]) { + type = DataType.OLE; + } else { + throw new IllegalArgumentException( + "Could not determine type for property " + name + + " with value " + value); + } + } + } + + return new PropertyImpl(name, type, flag, value); + } + /** * Info about a property defined in a PropertyMap. */ -- 2.39.5