aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2014-03-20 04:17:37 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2014-03-20 04:17:37 +0000
commitf73e6c33c75c8a0ba444ff200fdc234b59e59027 (patch)
tree9fb6c4cc452ec52b4945cf584800f7b068f26daf /src/main
parenta8a31e67bc8ec31c6377c5f38299314721a5c0fb (diff)
downloadjackcess-f73e6c33c75c8a0ba444ff200fdc234b59e59027.tar.gz
jackcess-f73e6c33c75c8a0ba444ff200fdc234b59e59027.zip
add initial ColumnValidator support
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@849 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Database.java16
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Table.java6
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java24
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java15
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java113
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/ColumnValidator.java41
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/ColumnValidatorFactory.java38
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidator.java40
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidatorFactory.java39
9 files changed, 286 insertions, 46 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/Database.java b/src/main/java/com/healthmarketscience/jackcess/Database.java
index ab4b7ca..4e9d136 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Database.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Database.java
@@ -33,6 +33,7 @@ import java.util.TimeZone;
import com.healthmarketscience.jackcess.query.Query;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
+import com.healthmarketscience.jackcess.util.ColumnValidatorFactory;
import com.healthmarketscience.jackcess.util.ErrorHandler;
import com.healthmarketscience.jackcess.util.LinkResolver;
@@ -366,7 +367,7 @@ public interface Database extends Iterable<Table>, Closeable, Flushable
public void setColumnOrder(Table.ColumnOrder newColumnOrder);
/**
- * Gets currently foreign-key enforcement policy.
+ * Gets current foreign-key enforcement policy.
* @usage _intermediate_method_
*/
public boolean isEnforceForeignKeys();
@@ -379,6 +380,19 @@ public interface Database extends Iterable<Table>, Closeable, Flushable
public void setEnforceForeignKeys(Boolean newEnforceForeignKeys);
/**
+ * Gets currently configured ColumnValidatorFactory (always non-{@code null}).
+ * @usage _intermediate_method_
+ */
+ public ColumnValidatorFactory getColumnValidatorFactory();
+
+ /**
+ * Sets a new ColumnValidatorFactory. If {@code null}, resets to the
+ * default value.
+ * @usage _intermediate_method_
+ */
+ public void setColumnValidatorFactory(ColumnValidatorFactory newFactory);
+
+ /**
* Returns the FileFormat of this database (which may involve inspecting the
* database itself).
* @throws IllegalStateException if the file format cannot be determined
diff --git a/src/main/java/com/healthmarketscience/jackcess/Table.java b/src/main/java/com/healthmarketscience/jackcess/Table.java
index 0765e1f..16b559f 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Table.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Table.java
@@ -71,6 +71,12 @@ public interface Table extends Iterable<Row>
public boolean isHidden();
/**
+ * Whether or not this table is a system (internal) table.
+ * @usage _general_method_
+ */
+ public boolean isSystem();
+
+ /**
* @usage _general_method_
*/
public int getColumnCount();
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
index ae68a17..b2a1ffc 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
@@ -65,6 +65,8 @@ import com.healthmarketscience.jackcess.impl.scsu.Compress;
import com.healthmarketscience.jackcess.impl.scsu.EndOfInputException;
import com.healthmarketscience.jackcess.impl.scsu.Expand;
import com.healthmarketscience.jackcess.impl.scsu.IllegalInputException;
+import com.healthmarketscience.jackcess.util.ColumnValidator;
+import com.healthmarketscience.jackcess.util.SimpleColumnValidator;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -221,6 +223,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
private PropertyMap _props;
/** Holds additional info for writing long values */
private LongValueBufferHolder _lvalBufferH;
+ /** Validator for writing new values */
+ private ColumnValidator _validator = SimpleColumnValidator.INSTANCE;
/**
* @usage _advanced_method_
@@ -509,6 +513,18 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
public ComplexColumnInfo<? extends ComplexValue> getComplexInfo() {
return _complexInfo;
}
+
+ public ColumnValidator getColumnValidator() {
+ return _validator;
+ }
+
+ public void setColumnValidator(ColumnValidator newValidator) {
+ if(newValidator == null) {
+ newValidator = getDatabase().getColumnValidatorFactory()
+ .createValidator(this);
+ }
+ _validator = newValidator;
+ }
private void setUnknownDataType(byte type) {
// slight hack, stash the original type in the _scale
@@ -1198,6 +1214,14 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
}
/**
+ * Passes the given obj through the currently configured validator for this
+ * column and returns the result.
+ */
+ public Object validate(Object obj) throws IOException {
+ return _validator.validate(this, obj);
+ }
+
+ /**
* Serialize an Object into a raw byte value for this column in little
* endian order
* @param obj Object to serialize
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index 810868c..8ddc4a0 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -72,8 +72,10 @@ import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.impl.query.QueryImpl;
import com.healthmarketscience.jackcess.query.Query;
import com.healthmarketscience.jackcess.util.CaseInsensitiveColumnMatcher;
+import com.healthmarketscience.jackcess.util.ColumnValidatorFactory;
import com.healthmarketscience.jackcess.util.ErrorHandler;
import com.healthmarketscience.jackcess.util.LinkResolver;
+import com.healthmarketscience.jackcess.util.SimpleColumnValidatorFactory;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -303,6 +305,8 @@ public class DatabaseImpl implements Database
private Table.ColumnOrder _columnOrder;
/** whether or not enforcement of foreign-keys is enabled */
private boolean _enforceForeignKeys;
+ /** factory for ColumnValidators */
+ private ColumnValidatorFactory _validatorFactory = SimpleColumnValidatorFactory.INSTANCE;
/** cache of in-use tables */
private final TableCache _tableCache = new TableCache();
/** handler for reading/writing properteies */
@@ -638,6 +642,17 @@ public class DatabaseImpl implements Database
_enforceForeignKeys = newEnforceForeignKeys;
}
+ public ColumnValidatorFactory getColumnValidatorFactory() {
+ return _validatorFactory;
+ }
+
+ public void setColumnValidatorFactory(ColumnValidatorFactory newFactory) {
+ if(newFactory == null) {
+ newFactory = SimpleColumnValidatorFactory.INSTANCE;
+ }
+ _validatorFactory = newFactory;
+ }
+
/**
* @usage _advanced_method_
*/
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java
index 15dfaec..f52bb1d 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java
@@ -303,6 +303,11 @@ public class TableImpl implements Table
}
_fkEnforcer = new FKEnforcer(this);
+
+ // after fully constructed, allow column validator to be configured
+ for(ColumnImpl col : _columns) {
+ col.setColumnValidator(null);
+ }
}
public String getName() {
@@ -313,6 +318,10 @@ public class TableImpl implements Table
return((_flags & DatabaseImpl.HIDDEN_OBJECT_FLAG) != 0);
}
+ public boolean isSystem() {
+ return(_tableType != TYPE_USER);
+ }
+
/**
* @usage _advanced_method_
*/
@@ -1528,8 +1537,35 @@ public class TableImpl implements Table
dupeRows.set(i, row);
}
- // fill in autonumbers
- handleAutoNumbersForAdd(row);
+ // handle various value massaging activities
+ Object complexAutoNumber = null;
+ for(ColumnImpl column : _columns) {
+
+ Object rowValue = null;
+ if(column.isAutoNumber()) {
+
+ // fill in autonumbers, ignore given row value, use next
+ // autonumber
+ ColumnImpl.AutoNumberGenerator autoNumGen =
+ column.getAutoNumberGenerator();
+ if(autoNumGen.getType() != DataType.COMPLEX_TYPE) {
+ rowValue = autoNumGen.getNext(null);
+ } else {
+ // complex type auto numbers are shared across all complex
+ // columns in the row
+ complexAutoNumber = autoNumGen.getNext(complexAutoNumber);
+ rowValue = complexAutoNumber;
+ }
+
+ } else {
+
+ // pass input value through column validator
+ rowValue = column.validate(column.getRowValue(row));
+ }
+
+ column.setRowValue(row, rowValue);
+ }
+
++autoNumAssignCount;
// write the row of data to a temporary buffer
@@ -1732,20 +1768,38 @@ public class TableImpl implements Table
Map<ColumnImpl,byte[]> keepRawVarValues =
(!_varColumns.isEmpty() ? new HashMap<ColumnImpl,byte[]>() : null);
+ // handle various value massaging activities
for(ColumnImpl column : _columns) {
- if(_autoNumColumns.contains(column)) {
+
+ Object rowValue = null;
+ if(column.isAutoNumber()) {
+
// fill in any auto-numbers (we don't allow autonumber values to be
// modified)
- column.setRowValue(row, getRowColumn(getFormat(), rowBuffer, column,
- rowState, null));
- } else if(column.getRowValue(row) == Column.KEEP_VALUE) {
- // fill in any "keep value" fields
- column.setRowValue(row, getRowColumn(getFormat(), rowBuffer, column,
- rowState, keepRawVarValues));
- } else if(_indexColumns.contains(column)) {
- // read row value to help update indexes
- getRowColumn(getFormat(), rowBuffer, column, rowState, null);
+ rowValue = getRowColumn(getFormat(), rowBuffer, column, rowState, null);
+
+ } else {
+
+ rowValue = column.getRowValue(row);
+ if(rowValue == Column.KEEP_VALUE) {
+
+ // fill in any "keep value" fields (restore old value)
+ rowValue = getRowColumn(getFormat(), rowBuffer, column, rowState,
+ keepRawVarValues);
+
+ } else {
+
+ if(_indexColumns.contains(column)) {
+ // read (old) row value to help update indexes
+ getRowColumn(getFormat(), rowBuffer, column, rowState, null);
+ }
+
+ // pass input value through column validator
+ rowValue = column.validate(rowValue);
+ }
}
+
+ column.setRowValue(row, rowValue);
}
// generate new row bytes
@@ -1969,10 +2023,7 @@ public class TableImpl implements Table
return dataPage;
}
- /**
- * @usage _advanced_method_
- */
- public ByteBuffer createRow(Object[] rowArray, ByteBuffer buffer)
+ protected ByteBuffer createRow(Object[] rowArray, ByteBuffer buffer)
throws IOException
{
return createRow(rowArray, buffer, 0,
@@ -2133,33 +2184,6 @@ public class TableImpl implements Table
}
/**
- * Fill in all autonumber column values.
- */
- private void handleAutoNumbersForAdd(Object[] row)
- throws IOException
- {
- if(_autoNumColumns.isEmpty()) {
- return;
- }
-
- Object complexAutoNumber = null;
- for(ColumnImpl col : _autoNumColumns) {
- // ignore given row value, use next autonumber
- ColumnImpl.AutoNumberGenerator autoNumGen = col.getAutoNumberGenerator();
- Object rowValue = null;
- if(autoNumGen.getType() != DataType.COMPLEX_TYPE) {
- rowValue = autoNumGen.getNext(null);
- } else {
- // complex type auto numbers are shared across all complex columns
- // in the row
- complexAutoNumber = autoNumGen.getNext(complexAutoNumber);
- rowValue = complexAutoNumber;
- }
- col.setRowValue(row, rowValue);
- }
- }
-
- /**
* Restores all autonumber column values from a failed add row.
*/
private void restoreAutoNumbersFromAdd(Object[] row)
@@ -2224,8 +2248,7 @@ public class TableImpl implements Table
@Override
public String toString() {
return CustomToStringStyle.builder(this)
- .append("type", (_tableType +
- ((_tableType == TYPE_USER) ? " (USER)" : " (SYSTEM)")))
+ .append("type", (_tableType + (!isSystem() ? " (USER)" : " (SYSTEM)")))
.append("name", _name)
.append("rowCount", _rowCount)
.append("columnCount", _columns.size())
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/ColumnValidator.java b/src/main/java/com/healthmarketscience/jackcess/util/ColumnValidator.java
new file mode 100644
index 0000000..50c8916
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/util/ColumnValidator.java
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2014 James Ahlborn
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+*/
+
+package com.healthmarketscience.jackcess.util;
+
+import java.io.IOException;
+
+import com.healthmarketscience.jackcess.Column;
+
+/**
+ * Interface which allows for data manipulation/validation as values are being
+ * inserted into a database.
+ *
+ * @author James Ahlborn
+ */
+public interface ColumnValidator
+{
+ /**
+ * Validates and/or manipulates the given potential new value for the given
+ * column. This method may return an entirely different value or throw an
+ * exception if the input value is not valid.
+ */
+ public Object validate(Column col, Object val) throws IOException;
+}
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/ColumnValidatorFactory.java b/src/main/java/com/healthmarketscience/jackcess/util/ColumnValidatorFactory.java
new file mode 100644
index 0000000..3a8a323
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/util/ColumnValidatorFactory.java
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 2014 James Ahlborn
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+*/
+
+package com.healthmarketscience.jackcess.util;
+
+import com.healthmarketscience.jackcess.Column;
+
+/**
+ * Factory which generates appropriate ColumnValidators when Column instances
+ * are created.
+ *
+ * @author James Ahlborn
+ */
+public interface ColumnValidatorFactory
+{
+ /**
+ * Returns a ColumnValidator instance for the given column, must be
+ * non-{@code null}.
+ */
+ public ColumnValidator createValidator(Column col);
+}
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidator.java b/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidator.java
new file mode 100644
index 0000000..7dd8817
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidator.java
@@ -0,0 +1,40 @@
+/*
+Copyright (c) 2014 James Ahlborn
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+*/
+
+package com.healthmarketscience.jackcess.util;
+
+import java.io.IOException;
+
+import com.healthmarketscience.jackcess.Column;
+
+/**
+ * Simple concrete implementation of ColumnValidator which simply returns the
+ * given value.
+ *
+ * @author James Ahlborn
+ */
+public class SimpleColumnValidator implements ColumnValidator
+{
+ public static final SimpleColumnValidator INSTANCE = new SimpleColumnValidator();
+
+ public Object validate(Column col, Object val) throws IOException {
+ return val;
+ }
+}
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidatorFactory.java b/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidatorFactory.java
new file mode 100644
index 0000000..367f8c7
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/util/SimpleColumnValidatorFactory.java
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2014 James Ahlborn
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+*/
+
+package com.healthmarketscience.jackcess.util;
+
+import com.healthmarketscience.jackcess.Column;
+
+/**
+ * Simple concrete implementation of ColumnValidatorFactory which returns
+ * {@link SimpleColumnValidator.INSTANCE} for all columns.
+ *
+ * @author James Ahlborn
+ */
+public class SimpleColumnValidatorFactory implements ColumnValidatorFactory
+{
+ public static final SimpleColumnValidatorFactory INSTANCE =
+ new SimpleColumnValidatorFactory();
+
+ public ColumnValidator createValidator(Column col) {
+ return SimpleColumnValidator.INSTANCE;
+ }
+}