From a307c8f58f02d68629a53c52dbefd50f8e4f97db Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Thu, 25 Jan 2018 21:33:03 +0000 Subject: Expose the ddl attribute on properties. Set the attribute appropriately for known builtin properties. fixes issue #145 git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1137 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 6 ++ .../healthmarketscience/jackcess/PropertyMap.java | 18 ++++ .../jackcess/impl/PropertyMapImpl.java | 98 ++++++++++++---------- .../jackcess/impl/PropertyMaps.java | 7 +- .../impl/complex/MultiValueColumnPropertyMap.java | 10 ++- .../jackcess/PropertiesTest.java | 8 +- 6 files changed, 96 insertions(+), 51 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c6188f9..6ea08e6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -4,6 +4,12 @@ Tim McCune + + + Expose the "ddl" attribute on properties. Set the attribute + appropriately for known builtin properties. + + diff --git a/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java b/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java index b216c6b..c93d896 100644 --- a/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java +++ b/src/main/java/com/healthmarketscience/jackcess/PropertyMap.java @@ -96,6 +96,16 @@ public interface PropertyMap extends Iterable */ public Property put(String name, DataType type, Object value); + /** + * Creates a new (or updates an existing) property in the map. + *

+ * Note, this change will not be persisted until the {@link #save} method + * has been called. + * + * @return the newly created (or updated) property + */ + public Property put(String name, DataType type, Object value, boolean isDdl); + /** * Puts all the given properties into this map. * @@ -125,6 +135,14 @@ public interface PropertyMap extends Iterable public DataType getType(); + /** + * Whether or not this property is a DDL object. If {@code true}, users + * can't change or delete the property in access without the dbSecWriteDef + * permission. Additionally, certain properties must be flagged correctly + * or the access engine may not recognize them correctly. + */ + public boolean isDdl(); + public Object getValue(); /** diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java index 9ec5fca..61c19a0 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMapImpl.java @@ -33,28 +33,28 @@ import com.healthmarketscience.jackcess.PropertyMap; */ public class PropertyMapImpl implements PropertyMap { - private static final Map DEFAULT_TYPES = - new HashMap(); + 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.BOOLEAN); - 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); + DEFAULT_TYPES.put(ACCESS_VERSION_PROP, new PropDef(DataType.TEXT, false)); + DEFAULT_TYPES.put(TITLE_PROP, new PropDef(DataType.TEXT, false)); + DEFAULT_TYPES.put(AUTHOR_PROP, new PropDef(DataType.TEXT, false)); + DEFAULT_TYPES.put(COMPANY_PROP, new PropDef(DataType.TEXT, false)); + + DEFAULT_TYPES.put(DEFAULT_VALUE_PROP, new PropDef(DataType.MEMO, true)); + DEFAULT_TYPES.put(REQUIRED_PROP, new PropDef(DataType.BOOLEAN, true)); + DEFAULT_TYPES.put(ALLOW_ZERO_LEN_PROP, new PropDef(DataType.BOOLEAN, true)); + DEFAULT_TYPES.put(DECIMAL_PLACES_PROP, new PropDef(DataType.BYTE, true)); + DEFAULT_TYPES.put(FORMAT_PROP, new PropDef(DataType.TEXT, true)); + DEFAULT_TYPES.put(INPUT_MASK_PROP, new PropDef(DataType.TEXT, true)); + DEFAULT_TYPES.put(CAPTION_PROP, new PropDef(DataType.MEMO, false)); + DEFAULT_TYPES.put(VALIDATION_RULE_PROP, new PropDef(DataType.TEXT, true)); + DEFAULT_TYPES.put(VALIDATION_TEXT_PROP, new PropDef(DataType.TEXT, true)); + DEFAULT_TYPES.put(GUID_PROP, new PropDef(DataType.BINARY, true)); + DEFAULT_TYPES.put(DESCRIPTION_PROP, new PropDef(DataType.MEMO, false)); + DEFAULT_TYPES.put(RESULT_TYPE_PROP, new PropDef(DataType.BYTE, true)); + DEFAULT_TYPES.put(EXPRESSION_PROP, new PropDef(DataType.MEMO, true)); } private final String _mapName; @@ -107,11 +107,11 @@ public class PropertyMapImpl implements PropertyMap } public PropertyImpl put(String name, Object value) { - return put(name, null, (byte)0, value); + return put(name, null, value, false); } public PropertyImpl put(String name, DataType type, Object value) { - return put(name, type, (byte)0, value); + return put(name, type, value, false); } public void putAll(Iterable props) { @@ -125,18 +125,15 @@ public class PropertyMapImpl implements PropertyMap } public PropertyImpl put(Property prop) { - byte flag = 0; - if(prop instanceof PropertyImpl) { - flag = ((PropertyImpl)prop).getFlag(); - } - return put(prop.getName(), prop.getType(), flag, prop.getValue()); + return put(prop.getName(), prop.getType(), prop.getValue(), prop.isDdl()); } /** * Puts a property into this map with the given information. */ - public PropertyImpl put(String name, DataType type, byte flag, Object value) { - PropertyImpl prop = (PropertyImpl)createProperty(name, type, flag, value); + public PropertyImpl put(String name, DataType type, Object value, + boolean isDdl) { + PropertyImpl prop = (PropertyImpl)createProperty(name, type, value, isDdl); _props.put(DatabaseImpl.toLookupName(name), prop); return prop; } @@ -174,17 +171,20 @@ public class PropertyMapImpl implements PropertyMap } public static Property createProperty(String name, DataType type, Object value) { - return createProperty(name, type, (byte)0, value); + return createProperty(name, type, value, false); } - public static Property createProperty(String name, DataType type, byte flag, - Object value) { + public static Property createProperty(String name, DataType type, + Object value, boolean isDdl) { if(type == null) { // attempt to get the default type for this property - type = DEFAULT_TYPES.get(name); + PropDef pd = DEFAULT_TYPES.get(name); - if(type == null) { + if(pd != null) { + type = pd._type; + isDdl |= pd._isDdl; + } else { // choose the type based on the value if(value instanceof String) { type = DataType.TEXT; @@ -214,9 +214,9 @@ public class PropertyMapImpl implements PropertyMap } } - return new PropertyImpl(name, type, flag, value); + return new PropertyImpl(name, type, value, isDdl); } - + /** * Info about a property defined in a PropertyMap. */ @@ -224,13 +224,14 @@ public class PropertyMapImpl implements PropertyMap { private final String _name; private final DataType _type; - private final byte _flag; + private final boolean _ddl; private Object _value; - private PropertyImpl(String name, DataType type, byte flag, Object value) { + private PropertyImpl(String name, DataType type, Object value, + boolean ddl) { _name = name; _type = type; - _flag = flag; + _ddl = ddl; _value = value; } @@ -250,8 +251,8 @@ public class PropertyMapImpl implements PropertyMap _value = newValue; } - public byte getFlag() { - return _flag; + public boolean isDdl() { + return _ddl; } @Override @@ -260,8 +261,21 @@ public class PropertyMapImpl implements PropertyMap if(val instanceof byte[]) { val = ByteUtil.toHexString((byte[])val); } - return getName() + "[" + getType() + ":" + _flag + "]=" + val; + return getName() + "[" + getType() + (_ddl ? ":ddl" : "") + "]=" + val; } } + /** + * Helper for holding info about default properties + */ + private static final class PropDef + { + private final DataType _type; + private final boolean _isDdl; + + private PropDef(DataType type, boolean isDdl) { + _type = type; + _isDdl = isDdl; + } + } } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMaps.java b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMaps.java index 3a63aba..4ac9e9a 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMaps.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/PropertyMaps.java @@ -313,7 +313,7 @@ public class PropertyMaps implements Iterable int valLen = bbBlock.getShort(); int endPos = bbBlock.position() + valLen - 2; - byte flag = bbBlock.get(); + boolean isDdl = (bbBlock.get() != 0); DataType dataType = DataType.fromByte(bbBlock.get()); int nameIdx = bbBlock.getShort(); int dataSize = bbBlock.getShort(); @@ -324,7 +324,7 @@ public class PropertyMaps implements Iterable byte[] data = ByteUtil.getBytes(bbBlock, dataSize); Object value = col.read(data); - map.put(propName, dataType, flag, value); + map.put(propName, dataType, value, isDdl); bbBlock.position(endPos); } @@ -359,7 +359,8 @@ public class PropertyMaps implements Iterable int valStartPos = bab.position(); bab.reserveShort(); - bab.put(prop.getFlag()); + byte ddlFlag = (byte)(prop.isDdl() ? 1 : 0); + bab.put(ddlFlag); bab.put(prop.getType().getValue()); bab.putShort((short)nameIdx); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/complex/MultiValueColumnPropertyMap.java b/src/main/java/com/healthmarketscience/jackcess/impl/complex/MultiValueColumnPropertyMap.java index 25c8e95..7adc2e3 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/complex/MultiValueColumnPropertyMap.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/complex/MultiValueColumnPropertyMap.java @@ -79,16 +79,20 @@ public class MultiValueColumnPropertyMap implements PropertyMap } public Property put(String name, Object value) { - return put(name, null, value); + return put(name, null, value, false); } public Property put(String name, DataType type, Object value) { + return put(name, type, value, false); + } + + public Property put(String name, DataType type, Object value, boolean isDdl) { // the only property which seems to go in the "primary" is the "multi // value" property if(isPrimaryKey(name)) { - return _primary.put(name, DataType.BOOLEAN, value); + return _primary.put(name, DataType.BOOLEAN, value, true); } - return _complex.put(name, value); + return _complex.put(name, type, value, isDdl); } public void putAll(Iterable props) { diff --git a/src/test/java/com/healthmarketscience/jackcess/PropertiesTest.java b/src/test/java/com/healthmarketscience/jackcess/PropertiesTest.java index 89ab4c4..69eb7c6 100644 --- a/src/test/java/com/healthmarketscience/jackcess/PropertiesTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/PropertiesTest.java @@ -68,13 +68,15 @@ public class PropertiesTest extends TestCase assertSame(colMap, maps.get("TESTCOL")); assertEquals("testcol", colMap.getName()); - defMap.put("foo", DataType.TEXT, (byte)0, "bar"); - defMap.put("baz", DataType.LONG, (byte)1, 13); + defMap.put("foo", DataType.TEXT, "bar", false); + defMap.put("baz", DataType.LONG, 13, true); assertFalse(defMap.isEmpty()); assertEquals(2, defMap.getSize()); + assertFalse(defMap.get("foo").isDdl()); + assertTrue(defMap.get("baz").isDdl()); - colMap.put("buzz", DataType.BOOLEAN, (byte)0, Boolean.TRUE); + colMap.put("buzz", DataType.BOOLEAN, Boolean.TRUE, true); assertFalse(colMap.isEmpty()); assertEquals(1, colMap.getSize()); -- cgit v1.2.3