@@ -244,11 +244,6 @@ | |||
</plugins> | |||
</build> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.apache.commons</groupId> | |||
<artifactId>commons-lang3</artifactId> | |||
<version>3.10</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>commons-logging</groupId> | |||
<artifactId>commons-logging</artifactId> |
@@ -65,7 +65,7 @@ import com.healthmarketscience.jackcess.impl.complex.ComplexValueForeignKeyImpl; | |||
import com.healthmarketscience.jackcess.impl.expr.NumberFormatter; | |||
import com.healthmarketscience.jackcess.util.ColumnValidator; | |||
import com.healthmarketscience.jackcess.util.SimpleColumnValidator; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -1749,18 +1749,16 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = CustomToStringStyle.builder(this) | |||
.append("name", "(" + _table.getName() + ") " + _name); | |||
byte typeValue = getOriginalDataType(); | |||
sb.append("type", "0x" + Integer.toHexString(typeValue) + | |||
ToStringBuilder sb = ToStringBuilder.builder(this) | |||
.append("name", "(" + _table.getName() + ") " + _name) | |||
.append("type", "0x" + Integer.toHexString(getOriginalDataType()) + | |||
" (" + _type + ")") | |||
.append("number", _columnNumber) | |||
.append("length", _columnLength) | |||
.append("variableLength", _variableLength); | |||
if(_calculated) { | |||
sb.append("calculated", _calculated) | |||
.append("expression", | |||
CustomToStringStyle.ignoreNull(getCalculationContext())); | |||
.appendIgnoreNull("expression", getCalculationContext()); | |||
} | |||
if(_type.isTextual()) { | |||
sb.append("compressedUnicode", isCompressedUnicode()) | |||
@@ -1782,11 +1780,11 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte | |||
if(_autoNumber) { | |||
sb.append("lastAutoNumber", _autoNumberGenerator.getLast()); | |||
} | |||
sb.append("complexInfo", CustomToStringStyle.ignoreNull(getComplexInfo())) | |||
.append("validator", CustomToStringStyle.ignoreNull( | |||
((_validator != SimpleColumnValidator.INSTANCE) ? | |||
_validator : null))) | |||
.append("defaultValue", CustomToStringStyle.ignoreNull(_defValue)); | |||
sb.appendIgnoreNull("complexInfo", getComplexInfo()) | |||
.appendIgnoreNull("validator", | |||
_validator != SimpleColumnValidator.INSTANCE ? | |||
_validator : null) | |||
.appendIgnoreNull("defaultValue", _defValue); | |||
return sb.toString(); | |||
} | |||
@@ -2398,7 +2396,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append(null, getBytes()) | |||
.toString(); | |||
} | |||
@@ -2684,7 +2682,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeConte | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append(null, _value + "(" + _version + ")") | |||
.toString(); | |||
} |
@@ -30,9 +30,11 @@ import java.util.List; | |||
import com.healthmarketscience.jackcess.RuntimeIOException; | |||
import static com.healthmarketscience.jackcess.impl.OleUtil.*; | |||
import com.healthmarketscience.jackcess.util.MemFileChannel; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
import static com.healthmarketscience.jackcess.util.OleBlob.*; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import org.apache.poi.poifs.filesystem.DirectoryEntry; | |||
import org.apache.poi.poifs.filesystem.DocumentEntry; | |||
import org.apache.poi.poifs.filesystem.DocumentInputStream; | |||
@@ -212,7 +214,7 @@ public class CompoundOleUtil implements CompoundPackageFactory | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = toString(CustomToStringStyle.builder(this)); | |||
ToStringBuilder sb = toString(ToStringBuilder.builder(this)); | |||
try { | |||
sb.append("hasContentsEntry", hasContentsEntry()); | |||
@@ -278,7 +280,7 @@ public class CompoundOleUtil implements CompoundPackageFactory | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append("name", _name) | |||
.append("length", length()) | |||
.toString(); |
@@ -1,210 +0,0 @@ | |||
/* | |||
Copyright (c) 2013 James Ahlborn | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
*/ | |||
package com.healthmarketscience.jackcess.impl; | |||
import java.nio.ByteBuffer; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import org.apache.commons.lang3.builder.StandardToStringStyle; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
/** | |||
* Custom ToStringStyle for use with ToStringBuilder. | |||
* | |||
* @author James Ahlborn | |||
*/ | |||
public class CustomToStringStyle extends StandardToStringStyle | |||
{ | |||
private static final long serialVersionUID = 0L; | |||
private static final String ML_FIELD_SEP = System.lineSeparator() + " "; | |||
private static final String IMPL_SUFFIX = "Impl"; | |||
private static final int MAX_BYTE_DETAIL_LEN = 20; | |||
private static final Object IGNORE_ME = new Object(); | |||
public static final CustomToStringStyle INSTANCE = new CustomToStringStyle() { | |||
private static final long serialVersionUID = 0L; | |||
{ | |||
setContentStart("["); | |||
setFieldSeparator(ML_FIELD_SEP); | |||
setFieldSeparatorAtStart(true); | |||
setFieldNameValueSeparator(": "); | |||
setArraySeparator("," + ML_FIELD_SEP); | |||
setContentEnd(System.lineSeparator() + "]"); | |||
setUseShortClassName(true); | |||
} | |||
}; | |||
public static final CustomToStringStyle VALUE_INSTANCE = new CustomToStringStyle() { | |||
private static final long serialVersionUID = 0L; | |||
{ | |||
setUseShortClassName(true); | |||
setUseIdentityHashCode(false); | |||
} | |||
}; | |||
private CustomToStringStyle() { | |||
} | |||
public static ToStringBuilder builder(Object obj) { | |||
return new ToStringBuilder(obj, INSTANCE); | |||
} | |||
public static ToStringBuilder valueBuilder(Object obj) { | |||
return new ToStringBuilder(obj, VALUE_INSTANCE); | |||
} | |||
@Override | |||
public void append(StringBuffer buffer, String fieldName, Object value, | |||
Boolean fullDetail) { | |||
if(value == IGNORE_ME) { | |||
return; | |||
} | |||
super.append(buffer, fieldName, value, fullDetail); | |||
} | |||
@Override | |||
protected void appendClassName(StringBuffer buffer, Object obj) { | |||
if(obj instanceof String) { | |||
// the caller gave an "explicit" class name | |||
buffer.append(obj); | |||
} else { | |||
super.appendClassName(buffer, obj); | |||
} | |||
} | |||
@Override | |||
protected String getShortClassName(Class<?> clss) { | |||
String shortName = super.getShortClassName(clss); | |||
if(shortName.endsWith(IMPL_SUFFIX)) { | |||
shortName = shortName.substring(0, | |||
shortName.length() - IMPL_SUFFIX.length()); | |||
} | |||
int idx = shortName.lastIndexOf('.'); | |||
if(idx >= 0) { | |||
shortName = shortName.substring(idx + 1); | |||
} | |||
return shortName; | |||
} | |||
@Override | |||
protected void appendDetail(StringBuffer buffer, String fieldName, | |||
Object value) { | |||
if(value instanceof ByteBuffer) { | |||
appendDetail(buffer, (ByteBuffer)value); | |||
} else { | |||
buffer.append(indent(value)); | |||
} | |||
} | |||
@Override | |||
protected void appendDetail(StringBuffer buffer, String fieldName, | |||
Collection<?> value) { | |||
buffer.append("["); | |||
// gather contents of list in a new StringBuffer | |||
StringBuffer sb = new StringBuffer(); | |||
Iterator<?> iter = value.iterator(); | |||
if(iter.hasNext()) { | |||
if(isFieldSeparatorAtStart()) { | |||
appendFieldSeparator(sb); | |||
} | |||
appendValueDetail(sb, fieldName, iter.next()); | |||
} | |||
while(iter.hasNext()) { | |||
sb.append(getArraySeparator()); | |||
appendValueDetail(sb, fieldName, iter.next()); | |||
} | |||
// indent entire list contents another level | |||
buffer.append(indent(sb)); | |||
if(isFieldSeparatorAtStart()) { | |||
appendFieldSeparator(buffer); | |||
} | |||
buffer.append("]"); | |||
} | |||
@Override | |||
protected void appendDetail(StringBuffer buffer, String fieldName, | |||
Map<?,?> value) { | |||
buffer.append("{"); | |||
// gather contents of map in a new StringBuffer | |||
StringBuffer sb = new StringBuffer(); | |||
Iterator<? extends Map.Entry<?,?>> iter = value.entrySet().iterator(); | |||
if(iter.hasNext()) { | |||
if(isFieldSeparatorAtStart()) { | |||
appendFieldSeparator(sb); | |||
} | |||
Map.Entry<?,?> e = iter.next(); | |||
sb.append(e.getKey()).append("="); | |||
appendValueDetail(sb, fieldName, e.getValue()); | |||
} | |||
while(iter.hasNext()) { | |||
sb.append(getArraySeparator()); | |||
Map.Entry<?,?> e = iter.next(); | |||
sb.append(e.getKey()).append("="); | |||
appendValueDetail(sb, fieldName, e.getValue()); | |||
} | |||
// indent entire map contents another level | |||
buffer.append(indent(sb)); | |||
if(isFieldSeparatorAtStart()) { | |||
appendFieldSeparator(buffer); | |||
} | |||
buffer.append("}"); | |||
} | |||
@Override | |||
protected void appendDetail(StringBuffer buffer, String fieldName, | |||
byte[] array) { | |||
appendDetail(buffer, PageChannel.wrap(array)); | |||
} | |||
private void appendValueDetail(StringBuffer buffer, String fieldName, | |||
Object value) { | |||
if (value == null) { | |||
appendNullText(buffer, fieldName); | |||
} else { | |||
appendInternal(buffer, fieldName, value, true); | |||
} | |||
} | |||
private static void appendDetail(StringBuffer buffer, ByteBuffer bb) { | |||
int len = bb.remaining(); | |||
buffer.append("(").append(len).append(") "); | |||
buffer.append(ByteUtil.toHexString(bb, bb.position(), | |||
Math.min(len, MAX_BYTE_DETAIL_LEN))); | |||
if(len > MAX_BYTE_DETAIL_LEN) { | |||
buffer.append(" ..."); | |||
} | |||
} | |||
private static String indent(Object obj) { | |||
return ((obj != null) ? obj.toString().replaceAll( | |||
System.lineSeparator(), ML_FIELD_SEP) : null); | |||
} | |||
public static Object ignoreNull(Object obj) { | |||
return ((obj != null) ? obj : IGNORE_ME); | |||
} | |||
} |
@@ -34,53 +34,14 @@ import java.nio.file.StandardOpenOption; | |||
import java.text.SimpleDateFormat; | |||
import java.time.LocalDateTime; | |||
import java.time.ZoneId; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.EnumMap; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.NoSuchElementException; | |||
import java.util.Set; | |||
import java.util.TimeZone; | |||
import java.util.TreeSet; | |||
import java.util.*; | |||
import java.util.regex.Pattern; | |||
import com.healthmarketscience.jackcess.ColumnBuilder; | |||
import com.healthmarketscience.jackcess.Cursor; | |||
import com.healthmarketscience.jackcess.CursorBuilder; | |||
import com.healthmarketscience.jackcess.DataType; | |||
import com.healthmarketscience.jackcess.Database; | |||
import com.healthmarketscience.jackcess.DatabaseBuilder; | |||
import com.healthmarketscience.jackcess.DateTimeType; | |||
import com.healthmarketscience.jackcess.Index; | |||
import com.healthmarketscience.jackcess.IndexBuilder; | |||
import com.healthmarketscience.jackcess.IndexCursor; | |||
import com.healthmarketscience.jackcess.PropertyMap; | |||
import com.healthmarketscience.jackcess.Relationship; | |||
import com.healthmarketscience.jackcess.Row; | |||
import com.healthmarketscience.jackcess.RuntimeIOException; | |||
import com.healthmarketscience.jackcess.Table; | |||
import com.healthmarketscience.jackcess.TableBuilder; | |||
import com.healthmarketscience.jackcess.TableDefinition; | |||
import com.healthmarketscience.jackcess.TableMetaData; | |||
import com.healthmarketscience.jackcess.*; | |||
import com.healthmarketscience.jackcess.expr.EvalConfig; | |||
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.ReadOnlyFileChannel; | |||
import com.healthmarketscience.jackcess.util.SimpleColumnValidatorFactory; | |||
import com.healthmarketscience.jackcess.util.TableIterableBuilder; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import com.healthmarketscience.jackcess.util.*; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -890,7 +851,7 @@ public class DatabaseImpl implements Database, DateTimeContext | |||
String accessVersion = (String)getDatabaseProperties().getValue( | |||
PropertyMap.ACCESS_VERSION_PROP); | |||
if(isBlank(accessVersion)) { | |||
if(StringUtil.isBlank(accessVersion)) { | |||
// no access version, fall back to "generic" | |||
accessVersion = null; | |||
} | |||
@@ -1980,7 +1941,7 @@ public class DatabaseImpl implements Database, DateTimeContext | |||
*/ | |||
private static void validateName(String name, int maxLength, String nameType) | |||
{ | |||
if(isBlank(name)) { | |||
if(StringUtil.isBlank(name)) { | |||
throw new IllegalArgumentException( | |||
nameType + " must have non-blank name"); | |||
} | |||
@@ -1991,25 +1952,9 @@ public class DatabaseImpl implements Database, DateTimeContext | |||
} | |||
} | |||
/** | |||
* Returns {@code true} if the given string is {@code null} or all blank | |||
* space, {@code false} otherwise. | |||
*/ | |||
public static boolean isBlank(String name) { | |||
return StringUtils.isBlank(name); | |||
} | |||
/** | |||
* Returns the given string trimmed, or {@code null} if the string is {@code | |||
* null} or empty. | |||
*/ | |||
public static String trimToNull(String str) { | |||
return StringUtils.trimToNull(str); | |||
} | |||
@Override | |||
public String toString() { | |||
return ToStringBuilder.reflectionToString(this); | |||
return StringUtil.reflectionToString(this); | |||
} | |||
/** | |||
@@ -2383,7 +2328,7 @@ public class DatabaseImpl implements Database, DateTimeContext | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = CustomToStringStyle.valueBuilder("TableMetaData") | |||
ToStringBuilder sb = ToStringBuilder.valueBuilder("TableMetaData") | |||
.append("name", getName()); | |||
if(isSystem()) { | |||
sb.append("isSystem", isSystem()); |
@@ -31,9 +31,10 @@ import com.healthmarketscience.jackcess.ConstraintViolationException; | |||
import com.healthmarketscience.jackcess.Index; | |||
import com.healthmarketscience.jackcess.IndexBuilder; | |||
import com.healthmarketscience.jackcess.RuntimeIOException; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
import static com.healthmarketscience.jackcess.impl.ByteUtil.ByteStream; | |||
import static com.healthmarketscience.jackcess.impl.IndexCodes.*; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -1108,7 +1109,7 @@ public class IndexData { | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = CustomToStringStyle.builder(this) | |||
ToStringBuilder sb = ToStringBuilder.builder(this) | |||
.append("dataNumber", _number) | |||
.append("pageNumber", _rootPageNumber) | |||
.append("isBackingPrimaryKey", isBackingPrimaryKey()) | |||
@@ -1679,7 +1680,7 @@ public class IndexData { | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.builder(this) | |||
return ToStringBuilder.builder(this) | |||
.append("column", getColumn()) | |||
.append("flags", getFlags() + " " + (isAscending() ? "(ASC)" : "(DSC)")) | |||
.toString(); | |||
@@ -2198,7 +2199,7 @@ public class IndexData { | |||
@Override | |||
public String toString() { | |||
return entryBytesToStringBuilder( | |||
CustomToStringStyle.valueBuilder(this) | |||
ToStringBuilder.valueBuilder(this) | |||
.append("rowId", _rowId)) | |||
.toString(); | |||
} | |||
@@ -2328,7 +2329,7 @@ public class IndexData { | |||
@Override | |||
public String toString() { | |||
return entryBytesToStringBuilder( | |||
CustomToStringStyle.valueBuilder(this) | |||
ToStringBuilder.valueBuilder(this) | |||
.append("rowId", getRowId()) | |||
.append("subPage", _subPageNumber)) | |||
.toString(); | |||
@@ -2566,7 +2567,7 @@ public class IndexData { | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append("curPosition", _curPos) | |||
.append("prevPosition", _prevPos) | |||
.toString(); | |||
@@ -2725,7 +2726,7 @@ public class IndexData { | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append("page", _dataPage.getPageNumber()) | |||
.append("idx", _idx) | |||
.append("entry", _entry) | |||
@@ -2800,7 +2801,7 @@ public class IndexData { | |||
(isLeaf() ? "Leaf" : "Node") + "DataPage[" + getPageNumber() + | |||
"] " + getPrevPageNumber() + ", " + getNextPageNumber() + ", (" + | |||
getChildTailPageNumber() + ")"; | |||
ToStringBuilder sb = CustomToStringStyle.valueBuilder(objName); | |||
ToStringBuilder sb = ToStringBuilder.valueBuilder(objName); | |||
if((isLeaf() && !entries.isEmpty())) { | |||
sb.append("entryRange", "[" + entries.get(0) + ", " + |
@@ -25,7 +25,7 @@ import java.util.Map; | |||
import com.healthmarketscience.jackcess.CursorBuilder; | |||
import com.healthmarketscience.jackcess.Index; | |||
import com.healthmarketscience.jackcess.IndexBuilder; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -366,7 +366,7 @@ public class IndexImpl implements Index, Comparable<IndexImpl> | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = CustomToStringStyle.builder(this) | |||
ToStringBuilder sb = ToStringBuilder.builder(this) | |||
.append("name", "(" + getTable().getName() + ") " + _name) | |||
.append("number", _indexNumber) | |||
.append("isPrimaryKey", isPrimaryKey()) | |||
@@ -515,7 +515,7 @@ public class IndexImpl implements Index, Comparable<IndexImpl> | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.builder(this) | |||
return ToStringBuilder.builder(this) | |||
.append("otherIndexNumber", _otherIndexNumber) | |||
.append("otherTablePageNum", _otherTablePageNumber) | |||
.append("isPrimaryTable", isPrimaryTable()) |
@@ -33,7 +33,7 @@ import java.util.RandomAccess; | |||
import static com.healthmarketscience.jackcess.impl.IndexData.*; | |||
import com.healthmarketscience.jackcess.impl.IndexData.DataPage; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* Manager of the index pages for a IndexData. | |||
@@ -1025,7 +1025,7 @@ public class IndexPageCache | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = CustomToStringStyle.builder(this); | |||
ToStringBuilder sb = ToStringBuilder.builder(this); | |||
if(_rootPage == null) { | |||
sb.append("pages", "(uninitialized)"); | |||
} else { | |||
@@ -1203,7 +1203,7 @@ public class IndexPageCache | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.builder("DPExtra") | |||
return ToStringBuilder.builder("DPExtra") | |||
.append(null, _entryView) | |||
.toString(); | |||
} |
@@ -35,8 +35,9 @@ import java.util.regex.Pattern; | |||
import com.healthmarketscience.jackcess.DataType; | |||
import com.healthmarketscience.jackcess.util.OleBlob; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
import static com.healthmarketscience.jackcess.util.OleBlob.*; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
/** | |||
* Utility code for working with OLE data. | |||
@@ -108,7 +109,7 @@ public class OleUtil | |||
/** | |||
* Creates a new OlBlob instance using the given information. | |||
*/ | |||
public static OleBlob createBlob(Builder oleBuilder) | |||
public static OleBlob createBlob(OleBlob.Builder oleBuilder) | |||
throws IOException | |||
{ | |||
try { | |||
@@ -184,7 +185,7 @@ public class OleUtil | |||
} | |||
} | |||
private static byte[] writePackageHeader(Builder oleBuilder, | |||
private static byte[] writePackageHeader(OleBlob.Builder oleBuilder, | |||
long contentLen) { | |||
byte[] prettyNameBytes = getZeroTermStrBytes(oleBuilder.getPrettyName()); | |||
@@ -230,7 +231,7 @@ public class OleUtil | |||
return headerBytes; | |||
} | |||
private static byte[] writePackageStreamHeader(Builder oleBuilder) { | |||
private static byte[] writePackageStreamHeader(OleBlob.Builder oleBuilder) { | |||
byte[] fileNameBytes = getZeroTermStrBytes(oleBuilder.getFileName()); | |||
byte[] filePathBytes = getZeroTermStrBytes(oleBuilder.getFilePath()); | |||
@@ -265,7 +266,7 @@ public class OleUtil | |||
return headerBytes; | |||
} | |||
private static byte[] writePackageStreamFooter(Builder oleBuilder) { | |||
private static byte[] writePackageStreamFooter(OleBlob.Builder oleBuilder) { | |||
// note, these are _not_ zero terminated | |||
byte[] fileNameBytes = oleBuilder.getFileName().getBytes(OLE_UTF_CHARSET); | |||
@@ -570,7 +571,7 @@ public class OleUtil | |||
@Override | |||
public String toString() { | |||
ToStringBuilder sb = CustomToStringStyle.builder(this); | |||
ToStringBuilder sb = ToStringBuilder.builder(this); | |||
if(_content != null) { | |||
sb.append("content", _content); | |||
} else { | |||
@@ -736,7 +737,7 @@ public class OleUtil | |||
@Override | |||
public String toString() { | |||
return toString(CustomToStringStyle.builder(this)) | |||
return toString(ToStringBuilder.builder(this)) | |||
.append("fileName", _fileName) | |||
.append("linkPath", _linkPath) | |||
.append("filePath", _filePath) | |||
@@ -786,7 +787,7 @@ public class OleUtil | |||
@Override | |||
public String toString() { | |||
return toString(CustomToStringStyle.builder(this)) | |||
return toString(ToStringBuilder.builder(this)) | |||
.append("fileName", _fileName) | |||
.append("filePath", _filePath) | |||
.append("localFilePath", _localFilePath) | |||
@@ -812,7 +813,7 @@ public class OleUtil | |||
@Override | |||
public String toString() { | |||
return toString(CustomToStringStyle.builder(this)) | |||
return toString(ToStringBuilder.builder(this)) | |||
.toString(); | |||
} | |||
} | |||
@@ -830,7 +831,7 @@ public class OleUtil | |||
@Override | |||
public String toString() { | |||
return toString(CustomToStringStyle.builder(this)) | |||
return toString(ToStringBuilder.builder(this)) | |||
.append("content", _blob._bytes) | |||
.toString(); | |||
} |
@@ -29,6 +29,8 @@ import java.util.Set; | |||
import com.healthmarketscience.jackcess.DataType; | |||
import com.healthmarketscience.jackcess.PropertyMap; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* Collection of PropertyMap instances read from a single property data block. | |||
@@ -121,7 +123,7 @@ public class PropertyMaps implements Iterable<PropertyMapImpl> | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.builder(this) | |||
return ToStringBuilder.builder(this) | |||
.append(null, _maps.values()) | |||
.toString(); | |||
} | |||
@@ -129,7 +131,7 @@ public class PropertyMaps implements Iterable<PropertyMapImpl> | |||
public static String getTrimmedStringProperty( | |||
PropertyMap props, String propName) | |||
{ | |||
return DatabaseImpl.trimToNull((String)props.getValue(propName)); | |||
return StringUtil.trimToNull((String)props.getValue(propName)); | |||
} | |||
/** |
@@ -28,6 +28,7 @@ import com.healthmarketscience.jackcess.IndexBuilder; | |||
import com.healthmarketscience.jackcess.IndexCursor; | |||
import com.healthmarketscience.jackcess.RelationshipBuilder; | |||
import com.healthmarketscience.jackcess.Row; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* Helper class used to maintain state during relationship creation. | |||
@@ -340,7 +341,7 @@ public class RelationshipCreator extends DBMutator | |||
colNames = getColumnNames(cols); | |||
} | |||
return CustomToStringStyle.valueBuilder(tableName) | |||
return ToStringBuilder.valueBuilder(tableName) | |||
.append(null, colNames) | |||
.toString(); | |||
} |
@@ -23,6 +23,7 @@ import java.util.ArrayList; | |||
import com.healthmarketscience.jackcess.Column; | |||
import com.healthmarketscience.jackcess.Relationship; | |||
import com.healthmarketscience.jackcess.Table; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* Information about a relationship between two tables in the database. | |||
@@ -163,7 +164,7 @@ public class RelationshipImpl implements Relationship | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.builder(this) | |||
return ToStringBuilder.builder(this) | |||
.append("name", _name) | |||
.append("fromTable", _fromTable.getName()) | |||
.append("fromColumns", _fromColumns) |
@@ -19,7 +19,6 @@ package com.healthmarketscience.jackcess.impl; | |||
import java.io.Serializable; | |||
import com.healthmarketscience.jackcess.RowId; | |||
import org.apache.commons.lang3.builder.CompareToBuilder; | |||
/** | |||
@@ -102,13 +101,16 @@ public class RowIdImpl implements RowId, Serializable | |||
public int compareTo(RowId other) { | |||
return compareTo((RowIdImpl)other); | |||
} | |||
public int compareTo(RowIdImpl other) { | |||
return new CompareToBuilder() | |||
.append(getType(), other.getType()) | |||
.append(getPageNumber(), other.getPageNumber()) | |||
.append(getRowNumber(), other.getRowNumber()) | |||
.toComparison(); | |||
int compare = getType().compareTo(other.getType()); | |||
if (compare == 0) { | |||
compare = Integer.compare(getPageNumber(), other.getPageNumber()); | |||
} | |||
if (compare == 0) { | |||
compare = Integer.compare(getRowNumber(), other.getRowNumber()); | |||
} | |||
return compare; | |||
} | |||
@Override |
@@ -25,7 +25,7 @@ import java.time.LocalDateTime; | |||
import com.healthmarketscience.jackcess.Row; | |||
import com.healthmarketscience.jackcess.complex.ComplexValueForeignKey; | |||
import com.healthmarketscience.jackcess.util.OleBlob; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* A row of data as column->value pairs. | |||
@@ -129,7 +129,7 @@ public class RowImpl extends LinkedHashMap<String,Object> implements Row | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder("Row[" + _id + "]") | |||
return ToStringBuilder.valueBuilder("Row[" + _id + "]") | |||
.append(null, this) | |||
.toString(); | |||
} |
@@ -53,6 +53,7 @@ import com.healthmarketscience.jackcess.Table; | |||
import com.healthmarketscience.jackcess.expr.Identifier; | |||
import com.healthmarketscience.jackcess.util.ErrorHandler; | |||
import com.healthmarketscience.jackcess.util.ExportUtil; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -3089,14 +3090,14 @@ public class TableImpl implements Table, PropertyMaps.Owner | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.builder(this) | |||
return ToStringBuilder.builder(this) | |||
.append("type", (_tableType + (!isSystem() ? " (USER)" : " (SYSTEM)"))) | |||
.append("name", _name) | |||
.append("rowCount", _rowCount) | |||
.append("columnCount", _columns.size()) | |||
.append("indexCount(data)", _indexCount) | |||
.append("logicalIndexCount", _logicalIndexCount) | |||
.append("validator", CustomToStringStyle.ignoreNull(_rowValidator)) | |||
.appendIgnoreNull("validator", _rowValidator) | |||
.append("columns", _columns) | |||
.append("indexes", _indexes) | |||
.append("ownedPages", _ownedPages) | |||
@@ -3614,7 +3615,7 @@ public class TableImpl implements Table, PropertyMaps.Owner | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append("headerRowId", _headerRowId) | |||
.append("finalRowId", _finalRowId) | |||
.toString(); |
@@ -22,6 +22,8 @@ import java.util.ArrayList; | |||
import java.util.BitSet; | |||
import java.util.List; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* Describes which database pages a particular table uses | |||
@@ -428,7 +430,7 @@ public class UsageMap | |||
rangeToString(ranges, curRangeStart, prevPage); | |||
} | |||
return CustomToStringStyle.valueBuilder( | |||
return ToStringBuilder.valueBuilder( | |||
_handler.getClass().getSimpleName()) | |||
.append("range", "(" + _startPage + "-" + _endPage + ")") | |||
.append("pageNumbers", ranges) |
@@ -37,8 +37,8 @@ import com.healthmarketscience.jackcess.complex.ComplexDataType; | |||
import com.healthmarketscience.jackcess.complex.ComplexValue; | |||
import com.healthmarketscience.jackcess.complex.ComplexValueForeignKey; | |||
import com.healthmarketscience.jackcess.impl.ColumnImpl; | |||
import com.healthmarketscience.jackcess.impl.CustomToStringStyle; | |||
import com.healthmarketscience.jackcess.impl.TableImpl; | |||
import com.healthmarketscience.jackcess.util.ToStringBuilder; | |||
/** | |||
* Base class for the additional information tracked for complex columns. | |||
@@ -315,7 +315,7 @@ public abstract class ComplexColumnInfoImpl<V extends ComplexValue> | |||
@Override | |||
public String toString() { | |||
return CustomToStringStyle.valueBuilder(this) | |||
return ToStringBuilder.valueBuilder(this) | |||
.append("complexType", getType()) | |||
.append("complexTypeId", _complexTypeId) | |||
.toString(); |
@@ -16,12 +16,15 @@ limitations under the License. | |||
package com.healthmarketscience.jackcess.impl.expr; | |||
import java.math.BigDecimal; | |||
import java.util.Arrays; | |||
import java.util.stream.Collectors; | |||
import com.healthmarketscience.jackcess.expr.EvalContext; | |||
import com.healthmarketscience.jackcess.expr.EvalException; | |||
import com.healthmarketscience.jackcess.expr.Function; | |||
import com.healthmarketscience.jackcess.expr.LocaleContext; | |||
import com.healthmarketscience.jackcess.expr.Value; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*; | |||
import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*; | |||
@@ -386,8 +389,8 @@ public class DefaultTextFunctions | |||
break; | |||
case 3: | |||
// vbProperCase | |||
str = org.apache.commons.lang3.text.WordUtils.capitalize( | |||
str.toLowerCase()); | |||
str = Arrays.stream(str.toLowerCase().split(" ")) | |||
.map(StringUtil::capitalize).collect(Collectors.joining(" ")); | |||
break; | |||
default: | |||
// do nothing |
@@ -38,7 +38,7 @@ import com.healthmarketscience.jackcess.expr.ParseException; | |||
import com.healthmarketscience.jackcess.expr.TemporalConfig; | |||
import com.healthmarketscience.jackcess.expr.Value; | |||
import com.healthmarketscience.jackcess.impl.ColumnImpl; | |||
import org.apache.commons.lang3.StringUtils; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
/** | |||
@@ -90,7 +90,7 @@ class ExpressionTokenizer | |||
exprStr = exprStr.trim(); | |||
} | |||
if(StringUtils.isEmpty(exprStr)) { | |||
if(StringUtil.isEmpty(exprStr)) { | |||
return null; | |||
} | |||
@@ -44,7 +44,7 @@ import com.healthmarketscience.jackcess.expr.ParseException; | |||
import com.healthmarketscience.jackcess.expr.Value; | |||
import com.healthmarketscience.jackcess.impl.expr.ExpressionTokenizer.Token; | |||
import com.healthmarketscience.jackcess.impl.expr.ExpressionTokenizer.TokenType; | |||
import org.apache.commons.lang3.StringUtils; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
/** | |||
@@ -1239,7 +1239,7 @@ public class Expressionator | |||
private static void literalStrToString(String str, StringBuilder sb) { | |||
sb.append("\"") | |||
.append(StringUtils.replace(str, "\"", "\"\"")) | |||
.append(StringUtil.replace(str, "\"", "\"\"")) | |||
.append("\""); | |||
} | |||
@@ -41,7 +41,7 @@ import com.healthmarketscience.jackcess.expr.EvalException; | |||
import com.healthmarketscience.jackcess.expr.NumericConfig; | |||
import com.healthmarketscience.jackcess.expr.TemporalConfig; | |||
import com.healthmarketscience.jackcess.expr.Value; | |||
import org.apache.commons.lang3.StringUtils; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
import static com.healthmarketscience.jackcess.impl.expr.ExpressionTokenizer.ExprBuf; | |||
/** | |||
@@ -448,7 +448,7 @@ public class FormatUtil | |||
return predefFmt; | |||
} | |||
if(StringUtils.isEmpty(fmtStr)) { | |||
if(StringUtil.isEmpty(fmtStr)) { | |||
return DUMMY_FMT; | |||
} | |||
@@ -22,7 +22,7 @@ import java.text.DecimalFormatSymbols; | |||
import com.healthmarketscience.jackcess.expr.EvalException; | |||
import com.healthmarketscience.jackcess.expr.LocaleContext; | |||
import com.healthmarketscience.jackcess.expr.Value; | |||
import org.apache.commons.lang3.StringUtils; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
/** | |||
* | |||
@@ -148,7 +148,7 @@ public class StringValue extends BaseValue | |||
// - convert decimal separator to '.' | |||
DecimalFormatSymbols syms = ctx.getNumericConfig().getDecimalFormatSymbols(); | |||
char groupSepChar = syms.getGroupingSeparator(); | |||
tmpVal = StringUtils.remove(tmpVal, groupSepChar); | |||
tmpVal = StringUtil.remove(tmpVal, String.valueOf(groupSepChar)); | |||
char decSepChar = syms.getDecimalSeparator(); | |||
if((decSepChar != ValueSupport.CANON_DEC_SEP) && (tmpVal.indexOf(decSepChar) >= 0)) { |
@@ -25,12 +25,13 @@ import com.healthmarketscience.jackcess.RowId; | |||
import com.healthmarketscience.jackcess.impl.DatabaseImpl; | |||
import com.healthmarketscience.jackcess.impl.RowIdImpl; | |||
import com.healthmarketscience.jackcess.impl.RowImpl; | |||
import static com.healthmarketscience.jackcess.impl.query.QueryFormat.*; | |||
import com.healthmarketscience.jackcess.query.Query; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import com.healthmarketscience.jackcess.util.StringUtil; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import static com.healthmarketscience.jackcess.impl.query.QueryFormat.*; | |||
/** | |||
* Base class for classes which encapsulate information about an Access query. | |||
@@ -347,7 +348,7 @@ public abstract class QueryImpl implements Query | |||
@Override | |||
public String toString() { | |||
return ToStringBuilder.reflectionToString(this); | |||
return StringUtil.reflectionToString(this); | |||
} | |||
/** | |||
@@ -633,7 +634,7 @@ public abstract class QueryImpl implements Query | |||
@Override | |||
public String toString() { | |||
return ToStringBuilder.reflectionToString(this); | |||
return StringUtil.reflectionToString(this); | |||
} | |||
} | |||
@@ -26,7 +26,6 @@ import com.healthmarketscience.jackcess.expr.EvalException; | |||
import com.healthmarketscience.jackcess.impl.ColEvalContext; | |||
import com.healthmarketscience.jackcess.impl.ColumnImpl; | |||
import com.healthmarketscience.jackcess.impl.expr.FormatUtil; | |||
import org.apache.commons.lang3.StringUtils; | |||
/** | |||
* Utility for applying Column formatting to column values for display. This | |||
@@ -72,7 +71,7 @@ public class ColumnFormatter | |||
*/ | |||
public void setFormatString(String fmtStr) throws IOException { | |||
PropertyMap props = _col.getProperties(); | |||
if(!StringUtils.isEmpty(fmtStr)) { | |||
if(!StringUtil.isEmpty(fmtStr)) { | |||
props.put(PropertyMap.FORMAT_PROP, fmtStr); | |||
} else { | |||
props.remove(PropertyMap.FORMAT_PROP); |
@@ -22,7 +22,6 @@ import com.healthmarketscience.jackcess.Database; | |||
import com.healthmarketscience.jackcess.Table; | |||
import com.healthmarketscience.jackcess.TableBuilder; | |||
import com.healthmarketscience.jackcess.impl.ByteUtil; | |||
import com.healthmarketscience.jackcess.impl.DatabaseImpl; | |||
import java.io.BufferedReader; | |||
import java.io.EOFException; | |||
import java.io.File; | |||
@@ -434,7 +433,7 @@ public class ImportUtil | |||
throws IOException | |||
{ | |||
String line = in.readLine(); | |||
if(DatabaseImpl.isBlank(line)) { | |||
if(StringUtil.isBlank(line)) { | |||
return null; | |||
} | |||
@@ -0,0 +1,162 @@ | |||
package com.healthmarketscience.jackcess.util; | |||
import java.lang.reflect.Field; | |||
import java.lang.reflect.Modifier; | |||
import java.nio.CharBuffer; | |||
import java.util.Arrays; | |||
import java.util.Comparator; | |||
import java.util.concurrent.atomic.AtomicBoolean; | |||
import java.util.stream.IntStream; | |||
/** | |||
* <p> | |||
* Static utility methods for null-safe {@link String} operations. | |||
* </p> | |||
* | |||
* The class prefers interface {@link CharSequence} for inputs over | |||
* {@code String} whenever possible, so that all implementations (e.g. | |||
* {@link StringBuffer}, {@link StringBuilder}, {@link CharBuffer}) can benefit. | |||
* | |||
* @author Markus Spann | |||
*/ | |||
public final class StringUtil | |||
{ | |||
private StringUtil() { | |||
} | |||
/** | |||
* Gets the given char sequence's length or {@code 0} if it is {@code null}. | |||
* | |||
* @param cs string | |||
* @return length of string | |||
*/ | |||
public static int length(CharSequence cs) | |||
{ | |||
return cs == null ? 0 : cs.length(); | |||
} | |||
/** | |||
* Checks if the given char sequence is either null or empty. | |||
* | |||
* @param cs char sequence to test | |||
* @return true if char sequence is empty or null, false otherwise | |||
*/ | |||
public static boolean isEmpty(CharSequence cs) | |||
{ | |||
return length(cs) == 0; | |||
} | |||
/** | |||
* Returns {@code true} if the given char sequence is {@code null} or all blank space, | |||
* {@code false} otherwise. | |||
*/ | |||
public static boolean isBlank(CharSequence cs) | |||
{ | |||
int len = length(cs); | |||
return len == 0 || IntStream.range(0, len).allMatch(i -> Character.isWhitespace(cs.charAt(i))); | |||
} | |||
/** | |||
* Returns the given char sequence trimmed or {@code null} if the string is {@code null} or empty. | |||
*/ | |||
public static String trimToNull(CharSequence cs) | |||
{ | |||
String str = cs == null ? null : cs.toString().trim(); | |||
return isEmpty(str) ? null : str; | |||
} | |||
/** | |||
* Capitalizes a string changing its first character to title case as per | |||
* {@link Character#toTitleCase(int)}. | |||
*/ | |||
public static String capitalize(String str) | |||
{ | |||
if (isEmpty(str)) { | |||
return str; | |||
} | |||
int cp = str.codePointAt(0); | |||
int newCp = Character.toTitleCase(cp); | |||
return cp == newCp ? str : new String(Character.toString((char) newCp)) + str.substring(1); | |||
} | |||
public static String replace(String text, CharSequence searchString, CharSequence replacement) | |||
{ | |||
return isEmpty(text) || isEmpty(searchString) ? text : text.replace(searchString, replacement); | |||
} | |||
/** | |||
* Removes all occurrences of character sequence {@code remove} from string {@code cs}. | |||
* | |||
* @param cs the character sequence to remove from | |||
* @param remove the character sequence to remove | |||
* @return modified input | |||
*/ | |||
public static String remove(CharSequence cs, CharSequence remove) | |||
{ | |||
if (cs == null) { | |||
return null; | |||
} | |||
int len = cs.length(); | |||
if (len == 0) { | |||
return ""; | |||
} else if (isEmpty(remove) || remove.length() > len) { | |||
return cs.toString(); | |||
} | |||
return cs.toString().replace(remove, ""); | |||
} | |||
/** | |||
* Generates a string representation of {@code obj} using reflection on its | |||
* non-static declared fields. | |||
* | |||
* @param obj object to generate string from | |||
* @param longClassName use full class name if {@code true} or simple name if | |||
* {@code false} | |||
* @param hashCode include the object's hash code if {@code true} | |||
* @return string representation | |||
*/ | |||
public static String reflectionToString(Object obj, boolean longClassName, boolean hashCode) | |||
{ | |||
if (obj == null) { | |||
return "null"; | |||
} | |||
StringBuilder sb = new StringBuilder(longClassName ? obj.getClass().getName() : obj.getClass().getSimpleName()); | |||
if (hashCode) { | |||
sb.append('@').append(Integer.toHexString(System.identityHashCode(obj))); | |||
} | |||
sb.append('['); | |||
AtomicBoolean firstField = new AtomicBoolean(true); | |||
Arrays.stream(obj.getClass().getDeclaredFields()) | |||
.filter(f -> !Modifier.isStatic(f.getModifiers())) | |||
.sorted(Comparator.comparing(Field::getName)) | |||
.forEach(f -> { | |||
f.setAccessible(true); | |||
if (!firstField.compareAndSet(true, false)) { | |||
sb.append(','); | |||
} | |||
sb.append(f.getName()).append('='); | |||
try { | |||
Object val = f.get(obj); | |||
sb.append(val == null ? "<null>" : val); | |||
} catch (Exception _ex) { | |||
sb.append('<').append(_ex).append('>'); | |||
} | |||
}); | |||
return sb.append(']').toString(); | |||
} | |||
/** | |||
* Generates a string representation of {@code obj} using reflection on its | |||
* non-static declared fields using the object's full class name and including | |||
* the object's hash code.<br> | |||
* | |||
* @param obj object to generate string from | |||
* @return string representation | |||
*/ | |||
public static String reflectionToString(Object obj) { | |||
return reflectionToString(obj, true, true); | |||
} | |||
} |
@@ -0,0 +1,181 @@ | |||
package com.healthmarketscience.jackcess.util; | |||
import java.lang.reflect.Array; | |||
import java.nio.ByteBuffer; | |||
import java.util.Collection; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.WeakHashMap; | |||
import java.util.stream.Collectors; | |||
import com.healthmarketscience.jackcess.impl.ByteUtil; | |||
import com.healthmarketscience.jackcess.impl.PageChannel; | |||
/** | |||
* <p>Builder for {@link Object#toString()} methods.</p> | |||
* | |||
* @author Markus Spann | |||
*/ | |||
public class ToStringBuilder | |||
{ | |||
/** Object registry for avoidance of cycles. */ | |||
private static final Map<Object, Object> OBJ_REGISTRY = new WeakHashMap<>(); | |||
private final StringBuilder buffer; | |||
private final Object object; | |||
private final String fieldSeparator; | |||
private final boolean fieldSeparatorAtStart; | |||
private final String fieldNameValueSeparator; | |||
private final String contentStart; | |||
private final String contentEnd; | |||
private final String nullText; | |||
private final String implSuffix; | |||
private boolean useIdentityHashCode = true; | |||
private final int maxByteDetailLen = 20; | |||
ToStringBuilder(Object _object, String _fieldSeparator, boolean _fieldSeparatorAtStart, String _fieldNameValueSeparator, String _contentEnd, | |||
boolean _useIdentityHashCode) { | |||
buffer = new StringBuilder(512); | |||
object = _object; | |||
fieldSeparator = Optional.ofNullable(_fieldSeparator).orElse(","); | |||
fieldSeparatorAtStart = _fieldSeparatorAtStart; | |||
fieldNameValueSeparator = Optional.ofNullable(_fieldNameValueSeparator).orElse("="); | |||
contentStart = "["; | |||
contentEnd = Optional.ofNullable(_contentEnd).orElse("]"); | |||
nullText = "<null>"; | |||
implSuffix = "Impl"; | |||
useIdentityHashCode = _useIdentityHashCode; | |||
if (object != null) { | |||
buffer.append(_object instanceof String ? _object : getShortClassName(_object.getClass(), implSuffix)); | |||
if (useIdentityHashCode) { | |||
buffer.append('@').append(Integer.toHexString(System.identityHashCode(object))); | |||
} | |||
buffer.append(contentStart); | |||
if (fieldSeparatorAtStart) { | |||
buffer.append(fieldSeparator); | |||
} | |||
} | |||
} | |||
public static ToStringBuilder valueBuilder(Object obj) | |||
{ | |||
return new ToStringBuilder(obj, null, false, null, null, false); | |||
} | |||
public static ToStringBuilder builder(Object obj) | |||
{ | |||
return new ToStringBuilder(obj, System.lineSeparator() + " ", true, ": ", System.lineSeparator() + "]", true); | |||
} | |||
public ToStringBuilder append(String fieldName, Object value) | |||
{ | |||
if (fieldName != null) { | |||
buffer.append(fieldName).append(fieldNameValueSeparator); | |||
} | |||
if (value == null) { | |||
buffer.append(nullText); | |||
} else { | |||
appendInternal(buffer, fieldName, value); | |||
} | |||
buffer.append(fieldSeparator); | |||
return this; | |||
} | |||
public ToStringBuilder appendIgnoreNull(String fieldName, Object value) | |||
{ | |||
return append(fieldName, value == null ? "" : value); | |||
} | |||
@Override | |||
public String toString() | |||
{ | |||
if (object == null) { | |||
buffer.append(nullText); | |||
} else { | |||
removeLastFieldSeparator(buffer, fieldSeparator); | |||
buffer.append(contentEnd); | |||
} | |||
return buffer.toString(); | |||
} | |||
void appendInternal(StringBuilder buffer, String fieldName, Object value) | |||
{ | |||
boolean primitiveWrapper = value instanceof Number || value instanceof Boolean || value instanceof Character; | |||
if (OBJ_REGISTRY.containsKey(value) && !primitiveWrapper) { | |||
buffer.append(value.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(value))); | |||
return; | |||
} | |||
OBJ_REGISTRY.put(value, null); // register object | |||
try { | |||
if (value instanceof byte[]) { | |||
ByteBuffer bb = PageChannel.wrap((byte[]) value); | |||
int len = bb.remaining(); | |||
buffer.append("(").append(len).append(") ").append(ByteUtil.toHexString(bb, bb.position(), Math.min(len, maxByteDetailLen))); | |||
if (len > maxByteDetailLen) { | |||
buffer.append("..."); | |||
} | |||
} else if (value.getClass().isArray()) { | |||
Object arr = value; | |||
buffer.append('{'); | |||
for (int i = 0; i < Array.getLength(arr); i++) { | |||
Object item = Array.get(arr, i); | |||
if (i > 0) { | |||
buffer.append(fieldSeparator); | |||
} | |||
if (item == null) { | |||
buffer.append(nullText); | |||
} else { | |||
appendInternal(buffer, fieldName, item); // recursive call | |||
} | |||
} | |||
buffer.append('}'); | |||
} else if (value instanceof Collection<?>) { | |||
String str = ((Collection<?>) value).stream().map(v -> v == null ? nullText : v.toString()).collect(Collectors.joining(",")); | |||
buffer.append('[').append(str).append(']'); | |||
} else if (value instanceof Map<?, ?>) { | |||
String str = ((Map<?, ?>) value).entrySet().stream().map(e -> e.getKey() + "=" + (e.getValue() == null ? nullText : e.getValue())) | |||
.collect(Collectors.joining(",")); | |||
buffer.append('{').append(str).append('}'); | |||
} else { | |||
buffer.append(value); | |||
} | |||
} finally { | |||
OBJ_REGISTRY.remove(value); // unregister object | |||
} | |||
} | |||
static String getShortClassName(Class<?> clazz, String _implSuffix) | |||
{ | |||
String nm = clazz.getSimpleName(); | |||
if (nm.endsWith(_implSuffix)) { | |||
nm = nm.substring(0, nm.length() - _implSuffix.length()); | |||
} | |||
int idx = nm.lastIndexOf('.'); | |||
return idx >= 0 ? nm.substring(idx + 1) : nm; | |||
} | |||
static void removeLastFieldSeparator(StringBuilder _buffer, String _fieldSeparator) | |||
{ | |||
int len = _buffer.length(); | |||
int sepLen = _fieldSeparator.length(); | |||
if (len > 0 && sepLen > 0 && len >= sepLen) { | |||
boolean match = true; | |||
for (int i = 0; i < sepLen; i++) { | |||
if (_buffer.charAt(len - 1 - i) != _fieldSeparator.charAt(sepLen - 1 - i)) { | |||
return; | |||
} | |||
} | |||
if (match) { | |||
_buffer.setLength(len - sepLen); | |||
} | |||
} | |||
} | |||
} |
@@ -933,7 +933,8 @@ public class DatabaseTest extends TestCase | |||
RowImpl row = new RowImpl(new RowIdImpl(1, 1)); | |||
row.put("id", 37); | |||
row.put("data", null); | |||
assertEquals("Row[1:1][{id=37,data=<null>}]", row.toString()); | |||
String str = row.toString(); | |||
assertEquals("Row[1:1][{id=37,data=<null>}]", str); | |||
} | |||
public void testIterateTableNames() throws Exception { |
@@ -29,7 +29,6 @@ import com.healthmarketscience.jackcess.TestUtil; | |||
import com.healthmarketscience.jackcess.impl.query.QueryImpl; | |||
import com.healthmarketscience.jackcess.impl.query.QueryImpl.Row; | |||
import junit.framework.TestCase; | |||
import org.apache.commons.lang3.StringUtils; | |||
import static com.healthmarketscience.jackcess.impl.query.QueryFormat.*; | |||
@@ -645,7 +644,7 @@ public class QueryTest extends TestCase | |||
private static String multiline(String... strs) | |||
{ | |||
return StringUtils.join(strs, System.lineSeparator()); | |||
return String.join(System.lineSeparator(), strs); | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
package com.healthmarketscience.jackcess.util; | |||
import org.junit.Test; | |||
import static org.junit.Assert.*; | |||
public class StringUtilTest | |||
{ | |||
@Test | |||
public void testLength() { | |||
assertEquals(0, StringUtil.length(null)); | |||
assertEquals(0, StringUtil.length("")); | |||
assertEquals(1, StringUtil.length("A")); | |||
assertEquals(1, StringUtil.length(" ")); | |||
assertEquals(4, StringUtil.length("sman")); | |||
} | |||
@Test | |||
public void testIsEmpty() { | |||
assertTrue(StringUtil.isEmpty(null)); | |||
assertTrue(StringUtil.isEmpty("")); | |||
assertFalse(StringUtil.isEmpty(" ")); | |||
assertFalse(StringUtil.isEmpty("not Empty")); | |||
} | |||
@Test | |||
public void testIsBlank() { | |||
assertTrue(StringUtil.isBlank(null)); | |||
assertTrue(StringUtil.isBlank("")); | |||
assertTrue(StringUtil.isBlank(" ")); | |||
assertTrue(StringUtil.isBlank(System.lineSeparator())); | |||
} | |||
@Test | |||
public void testTrimToNull() { | |||
assertNull(StringUtil.trimToNull(null)); | |||
assertNull(StringUtil.trimToNull("")); | |||
assertNull(StringUtil.trimToNull(" ")); | |||
assertEquals("sman", StringUtil.trimToNull("sman")); | |||
assertEquals("81", StringUtil.trimToNull(" 81 ")); | |||
} | |||
@Test | |||
public void testCapitalize() { | |||
assertNull(StringUtil.capitalize(null)); | |||
assertEquals("", StringUtil.capitalize("")); | |||
assertEquals("Hello", StringUtil.capitalize("hello")); | |||
assertEquals("Foo bar", StringUtil.capitalize("foo bar")); | |||
assertEquals("Boo far", StringUtil.capitalize("Boo far")); | |||
} | |||
@Test | |||
public void testReplace() { | |||
assertNull(null, StringUtil.replace(null, null, null)); | |||
assertEquals(" ", StringUtil.replace(" ", " ", " ")); | |||
assertEquals("text", StringUtil.replace("text", "", "newText")); | |||
assertEquals(" txt txt ", StringUtil.replace(" text text ", "text", "txt")); | |||
} | |||
@Test | |||
public void testRemove() { | |||
assertNull(StringUtil.remove(null, null)); | |||
assertNull(StringUtil.remove(null, "")); | |||
assertNull(StringUtil.remove(null, "remove")); | |||
assertEquals("", StringUtil.remove("", "remove")); | |||
assertEquals("input", StringUtil.remove("input", "remove")); | |||
assertEquals("Removed", StringUtil.remove("Removed", "remove")); | |||
assertEquals("", StringUtil.remove("remove", "remove")); | |||
assertEquals("long", StringUtil.remove("long", "longer")); | |||
} | |||
@Test | |||
public void testReflectionToString() { | |||
assertEquals("null", StringUtil.reflectionToString(null)); | |||
assertTrue(StringUtil.reflectionToString("").matches("^java\\.lang\\.String@[0-9a-f]+\\[hash=0,value=\\[C.+$")); | |||
assertEquals("Integer[value=47]", StringUtil.reflectionToString(Integer.valueOf(47), false, false)); | |||
} | |||
} |