diff options
12 files changed, 163 insertions, 52 deletions
@@ -10,6 +10,8 @@ Missing pieces: * MEDIUM - implement (optional) foreign key enforcement * MEDIUM +- implement write support for properties + * EASY - implement table, column, index renaming * EASY - implement table, column, index deletion diff --git a/src/java/com/healthmarketscience/jackcess/complex/Attachment.java b/src/java/com/healthmarketscience/jackcess/complex/Attachment.java index af33544..2f4b046 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/Attachment.java +++ b/src/java/com/healthmarketscience/jackcess/complex/Attachment.java @@ -22,6 +22,7 @@ package com.healthmarketscience.jackcess.complex; import java.util.Date; /** + * Complex value corresponding to an attachment. * * @author James Ahlborn */ diff --git a/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java index f258ca0..b86b9d1 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java @@ -20,7 +20,6 @@ USA package com.healthmarketscience.jackcess.complex; import java.io.IOException; -import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; @@ -31,6 +30,7 @@ import com.healthmarketscience.jackcess.Table; /** + * Complex column info for a column holding 0 or more attachments per row. * * @author James Ahlborn */ @@ -131,19 +131,8 @@ public class AttachmentColumnInfo extends ComplexColumnInfo<Attachment> } @Override - protected List<Attachment> toValues(ComplexValueForeignKey complexValueFk, - List<Map<String,Object>> rawValues) - throws IOException - { - List<Attachment> attachments = new ArrayList<Attachment>(); - for(Map<String,Object> rawValue : rawValues) { - attachments.add(toAttachment(complexValueFk, rawValue)); - } - return attachments; - } - - protected AttachmentImpl toAttachment(ComplexValueForeignKey complexValueFk, - Map<String,Object> rawValue) { + protected AttachmentImpl toValue(ComplexValueForeignKey complexValueFk, + Map<String,Object> rawValue) { int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); String url = (String)getFileUrlColumn().getRowValue(rawValue); String name = (String)getFileNameColumn().getRowValue(rawValue); diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java index 5232637..bcdaf9f 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java @@ -76,9 +76,11 @@ public abstract class ComplexColumnInfo<V extends ComplexValue> // the flat table has all the "value" columns and 2 extra columns, a // primary key for each row, and a LONG value which is essentially a // foreign key to the main table. - _typeCols = new ArrayList<Column>(); + List<Column> typeCols = new ArrayList<Column>(); List<Column> otherCols = new ArrayList<Column>(); - diffFlatColumns(typeObjTable, flatTable, _typeCols, otherCols); + diffFlatColumns(typeObjTable, flatTable, typeCols, otherCols); + + _typeCols = Collections.unmodifiableList(typeCols); Column pkCol = null; Column complexValFkCol = null; @@ -234,6 +236,18 @@ public abstract class ComplexColumnInfo<V extends ComplexValue> return toValues(complexValueFk, rawValues); } + protected List<V> toValues(ComplexValueForeignKey complexValueFk, + List<Map<String,Object>> rawValues) + throws IOException + { + List<V> values = new ArrayList<V>(); + for(Map<String,Object> rawValue : rawValues) { + values.add(toValue(complexValueFk, rawValue)); + } + + return values; + } + public int addRawValue(Map<String,Object> rawValue) throws IOException { Object[] row = _flatTable.asRow(rawValue); _flatTable.addRow(row); @@ -336,9 +350,9 @@ public abstract class ComplexColumnInfo<V extends ComplexValue> public abstract ComplexDataType getType(); - protected abstract List<V> toValues( + protected abstract V toValue( ComplexValueForeignKey complexValueFk, - List<Map<String,Object>> rawValues) + Map<String,Object> rawValues) throws IOException; protected static class ComplexValueImpl implements ComplexValue diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexDataType.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexDataType.java index 1c5e699..c0ae495 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexDataType.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexDataType.java @@ -20,6 +20,7 @@ USA package com.healthmarketscience.jackcess.complex; /** + * Secondary type classification for the data in a complex column. * * @author James Ahlborn */ diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java index e65a09c..b2f7d8c 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java @@ -24,20 +24,43 @@ import java.io.IOException; import com.healthmarketscience.jackcess.Column; /** + * Base class for a value in a complex column (where there may be multiple + * values for a single row in the main table). * * @author James Ahlborn */ public interface ComplexValue { + /** + * Returns the unique identifier of this complex value (this value is unique + * among all values in all rows of the main table). + * + * @return the current id or {@link ComplexColumnInfo#INVALID_ID} for a new, + * unsaved value. + */ public int getId(); public void setId(int newId); + /** + * Returns the foreign key identifier for this complex value (this value is + * the same for all values in the same row of the main table). + * + * @return the current id or {@link ComplexColumnInfo#INVALID_COMPLEX_VALUE_ID} + * for a new, unsaved value. + */ public ComplexValueForeignKey getComplexValueForeignKey(); public void setComplexValueForeignKey(ComplexValueForeignKey complexValueFk); + /** + * @return the column in the main table with which this complex value is + * associated + */ public Column getColumn(); + /** + * Writes any updated data for this complex value to the database. + */ public void update() throws IOException; } diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexValueForeignKey.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexValueForeignKey.java index 294958f..843cc5e 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexValueForeignKey.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexValueForeignKey.java @@ -28,6 +28,16 @@ import java.util.Map; import com.healthmarketscience.jackcess.Column; /** + * Value which is returned for a complex column. This value corresponds to a + * foreign key in a secondary table which contains the actual complex data for + * this row (which could be 0 or more complex values for a given row). This + * class contains various convenience methods for interacting with the actual + * complex values. + * <p> + * This class will cache the associated complex values returned from one of + * the lookup methods. The various modification methods will clear this cache + * automatically. The {@link #reset} method may be called manually to clear + * this internal cache. * * @author James Ahlborn */ @@ -37,10 +47,9 @@ public class ComplexValueForeignKey extends Number private final Column _column; private final int _value; - private List<? extends ComplexValue> _values; + private transient List<? extends ComplexValue> _values; - public ComplexValueForeignKey(Column column, int value) - { + public ComplexValueForeignKey(Column column, int value) { _column = column; _value = value; } @@ -103,6 +112,10 @@ public class ComplexValueForeignKey extends Number return (MultiValueColumnInfo)getComplexInfo(); } + protected UnsupportedColumnInfo getUnsupportedInfo() { + return (UnsupportedColumnInfo)getComplexInfo(); + } + public int countValues() throws IOException { @@ -217,6 +230,23 @@ public class ComplexValueForeignKey extends Number return value; } + public UnsupportedValue addUnsupportedValue(Map<String,Object> values) + throws IOException + { + reset(); + UnsupportedValue v = UnsupportedColumnInfo.newValue(this, values); + getUnsupportedInfo().addValue(v); + return v; + } + + public UnsupportedValue updateUnsupportedValue(UnsupportedValue value) + throws IOException + { + reset(); + getUnsupportedInfo().updateValue(value); + return value; + } + private Object writeReplace() throws ObjectStreamException { // if we are going to serialize this ComplexValueForeignKey, convert it // back to a normal Integer (in case it is restored outside of the context diff --git a/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java index 1b117c6..61488c1 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java @@ -20,7 +20,6 @@ USA package com.healthmarketscience.jackcess.complex; import java.io.IOException; -import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -31,6 +30,7 @@ import com.healthmarketscience.jackcess.DataType; import com.healthmarketscience.jackcess.Table; /** + * Complex column info for a column holding multiple values per row. * * @author James Ahlborn */ @@ -60,21 +60,9 @@ public class MultiValueColumnInfo extends ComplexColumnInfo<SingleValue> public Column getValueColumn() { return _valueCol; } - - @Override - protected List<SingleValue> toValues(ComplexValueForeignKey complexValueFk, - List<Map<String,Object>> rawValues) - throws IOException - { - List<SingleValue> values = new ArrayList<SingleValue>(); - for(Map<String,Object> rawValue : rawValues) { - values.add(toSingleValue(complexValueFk, rawValue)); - } - - return values; - } - protected SingleValueImpl toSingleValue( + @Override + protected SingleValueImpl toValue( ComplexValueForeignKey complexValueFk, Map<String,Object> rawValue) { diff --git a/src/java/com/healthmarketscience/jackcess/complex/SingleValue.java b/src/java/com/healthmarketscience/jackcess/complex/SingleValue.java index d8f6527..2e4c509 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/SingleValue.java +++ b/src/java/com/healthmarketscience/jackcess/complex/SingleValue.java @@ -20,6 +20,7 @@ USA package com.healthmarketscience.jackcess.complex; /** + * Complex value corresponding to an single value in a multi-value column. * * @author James Ahlborn */ diff --git a/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java index fd2a0fc..d362aa7 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java @@ -20,6 +20,7 @@ USA package com.healthmarketscience.jackcess.complex; import java.io.IOException; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -27,10 +28,11 @@ import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.Table; /** + * Complex column info for an unsupported complex type. * * @author James Ahlborn */ -public class UnsupportedColumnInfo extends ComplexColumnInfo<ComplexValue> +public class UnsupportedColumnInfo extends ComplexColumnInfo<UnsupportedValue> { public UnsupportedColumnInfo(Column column, int complexId, Table typeObjTable, @@ -40,6 +42,10 @@ public class UnsupportedColumnInfo extends ComplexColumnInfo<ComplexValue> super(column, complexId, typeObjTable, flatTable); } + public List<Column> getValueColumns() { + return getTypeColumns(); + } + @Override public ComplexDataType getType() { @@ -47,17 +53,73 @@ public class UnsupportedColumnInfo extends ComplexColumnInfo<ComplexValue> } @Override - protected List<ComplexValue> toValues(ComplexValueForeignKey complexValueFk, - List<Map<String,Object>> rawValues) - throws IOException + protected UnsupportedValueImpl toValue( + ComplexValueForeignKey complexValueFk, + Map<String,Object> rawValue) { - // FIXME - return null; + int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); + + Map<String,Object> values = new LinkedHashMap<String,Object>(rawValue); + values.remove(getPrimaryKeyColumn().getName()); + + return new UnsupportedValueImpl(id, complexValueFk, values); + } + + @Override + protected Object[] asRow(Object[] row, UnsupportedValue value) { + super.asRow(row, value); + + Map<String,Object> values = value.getValues(); + for(Column col : getValueColumns()) { + col.setRowValue(row, col.getRowValue(values)); + } + + return row; + } + + public static UnsupportedValue newValue(Map<String,Object> values) { + return newValue(INVALID_COMPLEX_VALUE_ID, values); } - public ComplexValue newValue() { - // FIXME - return null; + public static UnsupportedValue newValue( + ComplexValueForeignKey complexValueFk, Map<String,Object> values) { + return new UnsupportedValueImpl(INVALID_ID, complexValueFk, values); } + private static class UnsupportedValueImpl extends ComplexValueImpl + implements UnsupportedValue + { + private Map<String,Object> _values; + + private UnsupportedValueImpl(int id, ComplexValueForeignKey complexValueFk, + Map<String,Object> values) + { + super(id, complexValueFk); + _values = values; + } + + public Map<String,Object> getValues() { + return _values; + } + + public Object get(String columnName) { + return getValues().get(columnName); + } + + public void set(String columnName, Object value) { + getValues().put(columnName, value); + } + + @Override + public void update() throws IOException { + getComplexValueForeignKey().updateUnsupportedValue(this); + } + + @Override + public String toString() + { + return "UnsupportedValue(" + getComplexValueForeignKey() + "," + getId() + + ") " + getValues(); + } + } } diff --git a/src/java/com/healthmarketscience/jackcess/complex/Version.java b/src/java/com/healthmarketscience/jackcess/complex/Version.java index 70477f8..376eb32 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/Version.java +++ b/src/java/com/healthmarketscience/jackcess/complex/Version.java @@ -22,6 +22,7 @@ package com.healthmarketscience.jackcess.complex; import java.util.Date; /** + * Complex value corresponding to a version of a memo column. * * @author James Ahlborn */ diff --git a/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java index 0cf2fe7..ba98708 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java @@ -20,7 +20,6 @@ USA package com.healthmarketscience.jackcess.complex; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; @@ -30,6 +29,8 @@ import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.Table; /** + * Complex column info for a column which tracking the version history of an + * "append only" memo column. * * @author James Ahlborn */ @@ -92,10 +93,7 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo<Version> List<Map<String,Object>> rawValues) throws IOException { - List<Version> versions = new ArrayList<Version>(); - for(Map<String,Object> rawValue : rawValues) { - versions.add(toVersion(complexValueFk, rawValue)); - } + List<Version> versions = super.toValues(complexValueFk, rawValues); // order versions newest to oldest Collections.sort(versions); @@ -103,8 +101,9 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo<Version> return versions; } - protected VersionImpl toVersion(ComplexValueForeignKey complexValueFk, - Map<String,Object> rawValue) { + @Override + protected VersionImpl toValue(ComplexValueForeignKey complexValueFk, + Map<String,Object> rawValue) { int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); String value = (String)getValueColumn().getRowValue(rawValue); Date modifiedDate = (Date)getModifiedDateColumn().getRowValue(rawValue); |