Jackcess will not evaluate the actual expressions, but the column
values can be written directly.
</action>
+ <action dev="jahlborn" type="add">
+ Add the ability to set properties in DatabaseBuilder, TableBuilder,
+ and ColumnBuilder.
+ </action>
</release>
<release version="2.0.4" date="2014-04-05">
<action dev="jahlborn" type="add">
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
private short _columnNumber;
/** the collating sort order for a text field */
private ColumnImpl.SortOrder _sortOrder;
+ /** table properties (if any) */
+ private Map<String,PropertyMap.Property> _props;
public ColumnBuilder(String name) {
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<String,PropertyMap.Property>();
+ }
+ _props.put(name, PropertyMapImpl.createProperty(name, type, value));
+ return this;
+ }
+
+ public Map<String,PropertyMap.Property> getProperties() {
+ return _props;
+ }
+
/**
* Sets all attributes except name from the given Column template.
*/
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;
/**
/** optional pre-opened FileChannel, will _not_ be closed by Database
close */
private FileChannel _channel;
+ /** database properties (if any) */
+ private Map<String,PropertyMap.Property> _dbProps;
+ /** database summary properties (if any) */
+ private Map<String,PropertyMap.Property> _summaryProps;
+ /** database user-defined (if any) */
+ private Map<String,PropertyMap.Property> _userProps;
+
public DatabaseBuilder() {
this(null);
}
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<String,PropertyMap.Property> putProperty(
+ Map<String,PropertyMap.Property> props, String name, DataType type,
+ Object value)
+ {
+ if(props == null) {
+ props = new HashMap<String,PropertyMap.Property>();
+ }
+ props.put(name, PropertyMapImpl.createProperty(name, type, value));
+ return props;
+ }
+
/**
* Opens an existingnew Database using the configured information.
*/
* 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;
}
/**
{
return new DatabaseBuilder(mdbFile).setFileFormat(fileFormat).create();
}
-
-
}
*/
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).
+ * <p/>
+ * 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.
* <p/>
*/
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<? extends Property> props);
+
/**
* Removes the property with the given name
*
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}.
private List<IndexBuilder> _indexes = new ArrayList<IndexBuilder>();
/** whether or not table/column/index names are automatically escaped */
private boolean _escapeIdentifiers;
-
+ /** table properties (if any) */
+ private Map<String,PropertyMap.Property> _props;
+
public TableBuilder(String name) {
this(name, false);
}
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<String,PropertyMap.Property>();
+ }
+ _props.put(name, PropertyMapImpl.createProperty(name, type, value));
+ return this;
+ }
+
/**
* Creates a new Table in the given Database with the currently configured
* attributes.
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<String,PropertyMap.Property> 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;
}
/**
return ReservedWords.VALUES.contains(s.toLowerCase());
}
-
}
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;
*/
public class PropertyMapImpl implements PropertyMap
{
+ private static final Map<String,DataType> DEFAULT_TYPES =
+ new HashMap<String,DataType>();
+
+ 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<String,Property> _props =
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<? extends Property> 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;
}
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.
*/