This is an automated email from the git hooks/post-receive script. tmancill pushed a commit to branch master in repository joda-convert.
commit 0ee426bd04843093d73c04ecba23955f2666d5db Author: tony mancill <[email protected]> Date: Sat Sep 5 14:37:37 2015 -0700 Imported Upstream version 1.5 --- pom.xml | 10 +- src/changes/changes.xml | 26 ++ src/main/checkstyle/checkstyle.xml | 2 +- .../convert/AnnotationStringConverterFactory.java | 222 +++++++++++++ src/main/java/org/joda/convert/FromString.java | 2 +- .../java/org/joda/convert/FromStringConverter.java | 2 +- .../java/org/joda/convert/FromStringFactory.java | 2 +- .../java/org/joda/convert/JDKStringConverter.java | 28 +- .../convert/MethodConstructorStringConverter.java | 2 +- .../org/joda/convert/MethodsStringConverter.java | 6 +- .../joda/convert/ReflectionStringConverter.java | 2 +- src/main/java/org/joda/convert/StringConvert.java | 344 +++++++++++---------- .../java/org/joda/convert/StringConverter.java | 2 +- ...gConverter.java => StringConverterFactory.java} | 20 +- src/main/java/org/joda/convert/ToString.java | 2 +- .../java/org/joda/convert/ToStringConverter.java | 2 +- .../BooleanArrayStringConverterFactory.java | 103 ++++++ .../BooleanObjectArrayStringConverterFactory.java | 105 +++++++ .../ByteObjectArrayStringConverterFactory.java | 110 +++++++ .../CharObjectArrayStringConverterFactory.java | 128 ++++++++ .../NumericArrayStringConverterFactory.java | 240 ++++++++++++++ .../NumericObjectArrayStringConverterFactory.java | 250 +++++++++++++++ src/site/xdoc/index.xml | 4 +- src/site/xdoc/userguide.xml | 23 +- ...tanceFromStringConstructorInvalidParameter.java | 2 +- ...FromStringConstructorInvalidParameterCount.java | 2 +- .../joda/convert/DistanceFromStringException.java | 2 +- .../DistanceFromStringInvalidParameter.java | 2 +- .../DistanceFromStringInvalidParameterCount.java | 2 +- .../DistanceFromStringInvalidReturnType.java | 2 +- .../joda/convert/DistanceFromStringNoToString.java | 2 +- .../DistanceMethodAndConstructorAnnotations.java | 2 +- .../joda/convert/DistanceMethodConstructor.java | 2 +- .../DistanceMethodConstructorCharSequence.java | 2 +- .../org/joda/convert/DistanceMethodMethod.java | 2 +- .../convert/DistanceMethodMethodCharSequence.java | 2 +- .../org/joda/convert/DistanceNoAnnotations.java | 2 +- .../convert/DistanceNoAnnotationsCharSequence.java | 2 +- .../joda/convert/DistanceToStringException.java | 2 +- .../convert/DistanceToStringInvalidParameters.java | 2 +- .../convert/DistanceToStringInvalidReturnType.java | 2 +- .../joda/convert/DistanceToStringNoFromString.java | 2 +- .../DistanceTwoFromStringMethodAnnotations.java | 2 +- .../convert/DistanceTwoToStringAnnotations.java | 2 +- .../java/org/joda/convert/DistanceWithFactory.java | 2 +- .../joda/convert/DistanceWithFactoryFactory.java | 2 +- .../joda/convert/MockDistanceStringConverter.java | 2 +- .../joda/convert/MockIntegerStringConverter.java | 2 +- .../org/joda/convert/SubMethodConstructor.java | 2 +- .../java/org/joda/convert/SubMethodMethod.java | 2 +- .../java/org/joda/convert/SubNoAnnotations.java | 2 +- .../java/org/joda/convert/SuperFactorySub.java | 2 +- .../java/org/joda/convert/SuperFactorySuper.java | 2 +- .../TestBooleanArrayStringConverterFactory.java | 46 +++ ...stBooleanObjectArrayStringConverterFactory.java | 47 +++ .../TestByteObjectArrayStringConverterFactory.java | 46 +++ .../TestCharObjectArrayStringConverterFactory.java | 49 +++ .../org/joda/convert/TestJDKStringConverters.java | 34 +- .../TestNumericArrayStringConverterFactory.java | 112 +++++++ ...stNumericObjectArrayStringConverterFactory.java | 117 +++++++ .../java/org/joda/convert/TestStringConvert.java | 46 ++- .../joda/convert/TestStringConverterFactory.java | 61 ++++ .../java/org/joda/convert/test1/Test1Class.java | 2 +- .../org/joda/convert/test1/Test1Interface.java | 2 +- .../java/org/joda/convert/test2/Test2Class.java | 2 +- .../java/org/joda/convert/test2/Test2Factory.java | 2 +- .../org/joda/convert/test2/Test2Interface.java | 2 +- .../java/org/joda/convert/test3/Test3Class.java | 2 +- .../java/org/joda/convert/test3/Test3Factory.java | 2 +- .../org/joda/convert/test3/Test3Interface.java | 2 +- .../org/joda/convert/test3/Test3SuperClass.java | 2 +- .../java/org/joda/convert/test4/Test4Class.java | 2 +- .../java/org/joda/convert/test4/Test4Factory.java | 2 +- .../org/joda/convert/test4/Test4Interface.java | 2 +- 74 files changed, 2035 insertions(+), 242 deletions(-) diff --git a/pom.xml b/pom.xml index 96ebadf..800f379 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ <artifactId>joda-convert</artifactId> <packaging>jar</packaging> <name>Joda-Convert</name> - <version>1.4</version> + <version>1.5</version> <description>Library to convert Objects to and from String</description> <url>http://www.joda.org/joda-convert/</url> @@ -177,7 +177,7 @@ <skipDeploy>true</skipDeploy> </configuration> </plugin> - <plugin> + <plugin><!-- invoke with mvn site-deploy --> <groupId>com.github.github</groupId> <artifactId>site-maven-plugin</artifactId> <version>0.8</version> @@ -509,7 +509,7 @@ <maven-deploy-plugin.version>2.7</maven-deploy-plugin.version> <maven-dependency-plugin.version>2.8</maven-dependency-plugin.version> <maven-gpg-plugin.version>1.4</maven-gpg-plugin.version> - <maven-install-plugin.version>2.4</maven-install-plugin.version> + <maven-install-plugin.version>2.5</maven-install-plugin.version> <maven-jar-plugin.version>2.4</maven-jar-plugin.version> <maven-javadoc-plugin.version>2.9.1</maven-javadoc-plugin.version> <maven-jxr-plugin.version>2.3</maven-jxr-plugin.version> @@ -520,8 +520,8 @@ <maven-resources-plugin.version>2.6</maven-resources-plugin.version> <maven-site-plugin.version>3.3</maven-site-plugin.version> <maven-source-plugin.version>2.2.1</maven-source-plugin.version> - <maven-surefire-plugin.version>2.15</maven-surefire-plugin.version> - <maven-surefire-report-plugin.version>2.15</maven-surefire-report-plugin.version> + <maven-surefire-plugin.version>2.16</maven-surefire-plugin.version> + <maven-surefire-report-plugin.version>2.16</maven-surefire-report-plugin.version> <maven-toolchains-plugin.version>1.0</maven-toolchains-plugin.version> <!-- Properties for maven-compiler-plugin --> <maven.compiler.compilerVersion>1.6</maven.compiler.compilerVersion> diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5fc48d1..08a9b09 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -7,6 +7,32 @@ <body> <!-- types are add, fix, remove, update --> + <release version="1.5" date="2013-09-17" description="Version 1.5"> + <action dev="scolebourne" type="add" > + Add support for all primitive object arrays. + </action> + <action dev="scolebourne" type="add" > + Add support for boolean[]. + </action> + <action dev="scolebourne" type="add" > + Add support for numeric primitive arrays. + </action> + <action dev="scolebourne" type="add" > + Add support for char[] and byte[]. + </action> + <action dev="scolebourne" type="add" > + Add StringConverterFactory for more flexible initialization. + </action> + <action dev="scolebourne" type="add" > + Weaken generics to better support framework-level access. + </action> + <action dev="scolebourne" type="add" > + Add isConvertible() method. + </action> + <action dev="scolebourne" type="update" > + Validate the @FromString is a static method. + </action> + </release> <release version="1.4" date="2013-08-15" description="Version 1.4"> <action dev="scolebourne" type="update" > Change to use Maven plugin for OSGi, changing some published info. diff --git a/src/main/checkstyle/checkstyle.xml b/src/main/checkstyle/checkstyle.xml index 63ea58c..bb0c77a 100644 --- a/src/main/checkstyle/checkstyle.xml +++ b/src/main/checkstyle/checkstyle.xml @@ -122,7 +122,7 @@ </module> <!-- Header inlined due to m2e --> <module name="RegexpHeader"> - <property name="header" value="^/\*[*]?\n^ \* Copyright 2010([-](20[01][0-9]))? Stephen Colebourne"/> + <property name="header" value="^/\*[*]?\n^ \* Copyright 2010[-]present Stephen Colebourne"/> <property name="fileExtensions" value="java"/> </module> <module name="SuppressionCommentFilter"> diff --git a/src/main/java/org/joda/convert/AnnotationStringConverterFactory.java b/src/main/java/org/joda/convert/AnnotationStringConverterFactory.java new file mode 100644 index 0000000..c22cfb3 --- /dev/null +++ b/src/main/java/org/joda/convert/AnnotationStringConverterFactory.java @@ -0,0 +1,222 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * Factory for {@code StringConverter} looking up annotations. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +final class AnnotationStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + static final StringConverterFactory INSTANCE = new AnnotationStringConverterFactory(); + + /** + * Restricted constructor. + */ + private AnnotationStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + return findAnnotatedConverter(cls); // capture generics + } + + /** + * Finds a converter searching annotated. + * + * @param <T> the type of the converter + * @param cls the class to find a method for, not null + * @return the converter, not null + * @throws RuntimeException if none found + */ + private <T> StringConverter<T> findAnnotatedConverter(final Class<T> cls) { + Method toString = findToStringMethod(cls); // checks superclasses + if (toString == null) { + return null; + } + Constructor<T> con = findFromStringConstructor(cls); + Method fromString = findFromStringMethod(cls, con == null); // optionally checks superclasses + if (con == null && fromString == null) { + throw new IllegalStateException("Class annotated with @ToString but not with @FromString: " + cls.getName()); + } + if (con != null && fromString != null) { + throw new IllegalStateException("Both method and constructor are annotated with @FromString: " + cls.getName()); + } + if (con != null) { + return new MethodConstructorStringConverter<T>(cls, toString, con); + } else { + return new MethodsStringConverter<T>(cls, toString, fromString); + } + } + + /** + * Finds the conversion method. + * + * @param cls the class to find a method for, not null + * @return the method to call, null means use {@code toString} + * @throws RuntimeException if invalid + */ + private Method findToStringMethod(Class<?> cls) { + Method matched = null; + // find in superclass hierarchy + Class<?> loopCls = cls; + while (loopCls != null && matched == null) { + Method[] methods = loopCls.getDeclaredMethods(); + for (Method method : methods) { + ToString toString = method.getAnnotation(ToString.class); + if (toString != null) { + if (matched != null) { + throw new IllegalStateException("Two methods are annotated with @ToString: " + cls.getName()); + } + matched = method; + } + } + loopCls = loopCls.getSuperclass(); + } + // find in immediate parent interfaces + if (matched == null) { + for (Class<?> loopIfc : cls.getInterfaces()) { + Method[] methods = loopIfc.getDeclaredMethods(); + for (Method method : methods) { + ToString toString = method.getAnnotation(ToString.class); + if (toString != null) { + if (matched != null) { + throw new IllegalStateException("Two methods are annotated with @ToString on interfaces: " + cls.getName()); + } + matched = method; + } + } + } + } + return matched; + } + + /** + * Finds the conversion method. + * + * @param <T> the type of the converter + * @param cls the class to find a method for, not null + * @return the method to call, null means use {@code toString} + * @throws RuntimeException if invalid + */ + private <T> Constructor<T> findFromStringConstructor(Class<T> cls) { + Constructor<T> con; + try { + con = cls.getDeclaredConstructor(String.class); + } catch (NoSuchMethodException ex) { + try { + con = cls.getDeclaredConstructor(CharSequence.class); + } catch (NoSuchMethodException ex2) { + return null; + } + } + FromString fromString = con.getAnnotation(FromString.class); + return fromString != null ? con : null; + } + + /** + * Finds the conversion method. + * + * @param cls the class to find a method for, not null + * @return the method to call, null means not found + * @throws RuntimeException if invalid + */ + private Method findFromStringMethod(Class<?> cls, boolean searchSuperclasses) { + Method matched = null; + // find in superclass hierarchy + Class<?> loopCls = cls; + while (loopCls != null && matched == null) { + matched = findFromString(loopCls, matched); + if (searchSuperclasses == false) { + break; + } + loopCls = loopCls.getSuperclass(); + } + // find in immediate parent interfaces + if (searchSuperclasses && matched == null) { + for (Class<?> loopIfc : cls.getInterfaces()) { + matched = findFromString(loopIfc, matched); + } + } + return matched; + } + + /** + * Finds the conversion method. + * + * @param cls the class to find a method for, not null + * @param matched the matched method, may be null + * @return the method to call, null means not found + * @throws RuntimeException if invalid + */ + private Method findFromString(Class<?> cls, Method matched) { + // find in declared methods + Method[] methods = cls.getDeclaredMethods(); + for (Method method : methods) { + FromString fromString = method.getAnnotation(FromString.class); + if (fromString != null) { + if (matched != null) { + throw new IllegalStateException("Two methods are annotated with @FromString: " + cls.getName()); + } + matched = method; + } + } + // check for factory + FromStringFactory factory = cls.getAnnotation(FromStringFactory.class); + if (factory != null) { + if (matched != null) { + throw new IllegalStateException("Class annotated with @FromString and @FromStringFactory: " + cls.getName()); + } + Method[] factoryMethods = factory.factory().getDeclaredMethods(); + for (Method method : factoryMethods) { + // handle factory containing multiple FromString for different types + if (cls.isAssignableFrom(method.getReturnType())) { + FromString fromString = method.getAnnotation(FromString.class); + if (fromString != null) { + if (matched != null) { + throw new IllegalStateException("Two methods are annotated with @FromString on the factory: " + factory.factory().getName()); + } + matched = method; + } + } + } + } + return matched; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + +} diff --git a/src/main/java/org/joda/convert/FromString.java b/src/main/java/org/joda/convert/FromString.java index f3432a6..bf4290d 100644 --- a/src/main/java/org/joda/convert/FromString.java +++ b/src/main/java/org/joda/convert/FromString.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/FromStringConverter.java b/src/main/java/org/joda/convert/FromStringConverter.java index e5bace9..fc4e4e4 100644 --- a/src/main/java/org/joda/convert/FromStringConverter.java +++ b/src/main/java/org/joda/convert/FromStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/FromStringFactory.java b/src/main/java/org/joda/convert/FromStringFactory.java index 6517e06..3e970df 100644 --- a/src/main/java/org/joda/convert/FromStringFactory.java +++ b/src/main/java/org/joda/convert/FromStringFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/JDKStringConverter.java b/src/main/java/org/joda/convert/JDKStringConverter.java index c90448d..b74f0a8 100644 --- a/src/main/java/org/joda/convert/JDKStringConverter.java +++ b/src/main/java/org/joda/convert/JDKStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import javax.xml.bind.DatatypeConverter; + /** * Conversion between JDK classes and a {@code String}. */ @@ -109,6 +111,18 @@ enum JDKStringConverter implements StringConverter<Object> { } }, /** + * String converter. + */ + BYTE_ARRAY(byte[].class) { + @Override + public String convertToString(Object object) { + return DatatypeConverter.printBase64Binary((byte[]) object); + } + public Object convertFromString(Class<?> cls, String str) { + return DatatypeConverter.parseBase64Binary(str); + } + }, + /** * Character converter. */ CHARACTER(Character.class) { @@ -120,6 +134,18 @@ enum JDKStringConverter implements StringConverter<Object> { } }, /** + * String converter. + */ + CHAR_ARRAY(char[].class) { + @Override + public String convertToString(Object object) { + return new String((char[]) object); + } + public Object convertFromString(Class<?> cls, String str) { + return str.toCharArray(); + } + }, + /** * Boolean converter. */ BOOLEAN(Boolean.class) { diff --git a/src/main/java/org/joda/convert/MethodConstructorStringConverter.java b/src/main/java/org/joda/convert/MethodConstructorStringConverter.java index f6ed6a3..9cf0c53 100644 --- a/src/main/java/org/joda/convert/MethodConstructorStringConverter.java +++ b/src/main/java/org/joda/convert/MethodConstructorStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/MethodsStringConverter.java b/src/main/java/org/joda/convert/MethodsStringConverter.java index 7f5dd39..65aa5d4 100644 --- a/src/main/java/org/joda/convert/MethodsStringConverter.java +++ b/src/main/java/org/joda/convert/MethodsStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.joda.convert; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; /** * Conversion to and from a string using two methods. @@ -45,6 +46,9 @@ final class MethodsStringConverter<T> extends ReflectionStringConverter<T> { */ MethodsStringConverter(Class<T> cls, Method toString, Method fromString) { super(cls, toString); + if (Modifier.isStatic(fromString.getModifiers()) == false) { + throw new IllegalStateException("FromString method must be static: " + fromString); + } if (fromString.getParameterTypes().length != 1) { throw new IllegalStateException("FromString method must have one parameter: " + fromString); } diff --git a/src/main/java/org/joda/convert/ReflectionStringConverter.java b/src/main/java/org/joda/convert/ReflectionStringConverter.java index c3593d4..1cc8e30 100644 --- a/src/main/java/org/joda/convert/ReflectionStringConverter.java +++ b/src/main/java/org/joda/convert/ReflectionStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/StringConvert.java b/src/main/java/org/joda/convert/StringConvert.java index 778bfdc..56e99d7 100644 --- a/src/main/java/org/joda/convert/StringConvert.java +++ b/src/main/java/org/joda/convert/StringConvert.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,17 @@ package org.joda.convert; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.joda.convert.factory.BooleanArrayStringConverterFactory; +import org.joda.convert.factory.BooleanObjectArrayStringConverterFactory; +import org.joda.convert.factory.ByteObjectArrayStringConverterFactory; +import org.joda.convert.factory.CharObjectArrayStringConverterFactory; +import org.joda.convert.factory.NumericArrayStringConverterFactory; +import org.joda.convert.factory.NumericObjectArrayStringConverterFactory; /** * Manager for conversion to and from a {@code String}, acting as the main client interface. @@ -53,10 +62,48 @@ public final class StringConvert { }; /** + * The list of factories. + */ + private final CopyOnWriteArrayList<StringConverterFactory> factories = new CopyOnWriteArrayList<StringConverterFactory>(); + /** * The cache of converters. */ private final ConcurrentMap<Class<?>, StringConverter<?>> registered = new ConcurrentHashMap<Class<?>, StringConverter<?>>(); + //----------------------------------------------------------------------- + /** + * Creates a new conversion manager including the extended standard set of converters. + * <p> + * The returned converter is a new instance that includes additional converters: + * <ul> + * <li>JDK converters + * <li>{@link NumericArrayStringConverterFactory} + * <li>{@link NumericObjectArrayStringConverterFactory} + * <li>{@link CharObjectArrayStringConverterFactory} + * <li>{@link ByteObjectArrayStringConverterFactory} + * <li>{@link BooleanArrayStringConverterFactory} + * <li>{@link BooleanObjectArrayStringConverterFactory} + * </ul> + * <p> + * The convert instance is mutable in a thread-safe manner. + * Converters may be altered at any time, including the JDK converters. + * It is strongly recommended to only alter the converters before performing + * actual conversions. + * + * @return the new converter, not null + * @since 1.5 + */ + public static StringConvert create() { + return new StringConvert(true, + NumericArrayStringConverterFactory.INSTANCE, + NumericObjectArrayStringConverterFactory.INSTANCE, + CharObjectArrayStringConverterFactory.INSTANCE, + ByteObjectArrayStringConverterFactory.INSTANCE, + BooleanArrayStringConverterFactory.INSTANCE, + BooleanObjectArrayStringConverterFactory.INSTANCE); + } + + //----------------------------------------------------------------------- /** * Creates a new conversion manager including the JDK converters. * <p> @@ -76,10 +123,21 @@ public final class StringConvert { * Converters may be altered at any time, including the JDK converters. * It is strongly recommended to only alter the converters before performing * actual conversions. + * <p> + * If specified, the factories will be queried in the order specified. * * @param includeJdkConverters true to include the JDK converters + * @param factories optional array of factories to use, not null */ - public StringConvert(boolean includeJdkConverters) { + public StringConvert(boolean includeJdkConverters, StringConverterFactory... factories) { + if (factories == null) { + throw new IllegalArgumentException("StringConverterFactory array must not be null"); + } + for (int i = 0; i < factories.length; i++) { + if (factories[i] == null) { + throw new IllegalArgumentException("StringConverterFactory array must not contain a null element"); + } + } if (includeJdkConverters) { for (JDKStringConverter conv : JDKStringConverter.values()) { registered.put(conv.getType(), conv); @@ -140,6 +198,10 @@ public final class StringConvert { tryRegister("javax.time.calendar.ZoneId", "of"); tryRegister("javax.time.calendar.TimeZone", "of"); } + if (factories.length > 0) { + this.factories.addAll(Arrays.asList(factories)); + } + this.factories.add(AnnotationStringConverterFactory.INSTANCE); } /** @@ -162,18 +224,16 @@ public final class StringConvert { * <p> * This uses {@link #findConverter} to provide the converter. * - * @param <T> the type to convert from * @param object the object to convert, null returns null * @return the converted string, may be null * @throws RuntimeException (or subclass) if unable to convert */ - @SuppressWarnings("unchecked") - public <T> String convertToString(T object) { + public String convertToString(Object object) { if (object == null) { return null; } - Class<T> cls = (Class<T>) object.getClass(); - StringConverter<T> conv = findConverter(cls); + Class<?> cls = object.getClass(); + StringConverter<Object> conv = findConverterNoGenerics(cls); return conv.convertToString(object); } @@ -183,17 +243,16 @@ public final class StringConvert { * This uses {@link #findConverter} to provide the converter. * The class can be provided to select a more specific converter. * - * @param <T> the type to convert from * @param cls the class to convert from, not null * @param object the object to convert, null returns null * @return the converted string, may be null * @throws RuntimeException (or subclass) if unable to convert */ - public <T> String convertToString(Class<T> cls, T object) { + public String convertToString(Class<?> cls, Object object) { if (object == null) { return null; } - StringConverter<T> conv = findConverter(cls); + StringConverter<Object> conv = findConverterNoGenerics(cls); return conv.convertToString(object); } @@ -216,11 +275,32 @@ public final class StringConvert { return conv.convertFromString(cls, str); } + //----------------------------------------------------------------------- + /** + * Checks if a suitable converter exists for the type. + * <p> + * This performs the same checks as the {@code findConverter} methods. + * Calling this before {@code findConverter} will cache the converter. + * <p> + * Note that all exceptions, including developer errors are caught and hidden. + * + * @param cls the class to find a converter for, null returns false + * @return true if convertible + * @since 1.5 + */ + public boolean isConvertible(final Class<?> cls) { + try { + return cls != null && findConverterQuiet(cls) != null; + } catch (RuntimeException ex) { + return false; + } + } + /** * Finds a suitable converter for the type. * <p> * This returns an instance of {@code StringConverter} for the specified class. - * This could be useful in other frameworks. + * This is designed for user code where the {@code Class} object generics is known. * <p> * The search algorithm first searches the registered converters in the * class hierarchy and immediate parent interfaces. @@ -232,28 +312,84 @@ public final class StringConvert { * @return the converter, not null * @throws RuntimeException (or subclass) if no converter found */ - @SuppressWarnings("unchecked") public <T> StringConverter<T> findConverter(final Class<T> cls) { + StringConverter<T> conv = findConverterQuiet(cls); + if (conv == null) { + throw new IllegalStateException("No registered converter found: " + cls); + } + return conv; + } + + /** + * Finds a suitable converter for the type with open generics. + * <p> + * This returns an instance of {@code StringConverter} for the specified class. + * This is designed for framework usage where the {@code Class} object generics are unknown'?'. + * The returned type is declared with {@code Object} instead of '?' to + * allow the {@link ToStringConverter} to be invoked. + * <p> + * The search algorithm first searches the registered converters in the + * class hierarchy and immediate parent interfaces. + * It then searches for {@code ToString} and {@code FromString} annotations on the + * specified class, class hierarchy or immediate parent interfaces. + * + * @param cls the class to find a converter for, not null + * @return the converter, using {@code Object} to avoid generics, not null + * @throws RuntimeException (or subclass) if no converter found + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public StringConverter<Object> findConverterNoGenerics(final Class<?> cls) { + StringConverter<Object> conv = (StringConverter<Object>) findConverterQuiet(cls); + if (conv == null) { + throw new IllegalStateException("No registered converter found: " + cls); + } + return conv; + } + + /** + * Finds a converter searching registered and annotated. + * + * @param <T> the type of the converter + * @param cls the class to find a method for, not null + * @return the converter, null if no converter + * @throws RuntimeException if invalid + */ + @SuppressWarnings("unchecked") + private <T> StringConverter<T> findConverterQuiet(final Class<T> cls) { if (cls == null) { throw new IllegalArgumentException("Class must not be null"); } StringConverter<T> conv = (StringConverter<T>) registered.get(cls); if (conv == CACHED_NULL) { - throw new IllegalStateException("No registered converter found: " + cls); + return null; } if (conv == null) { - conv = findAnnotationConverter(cls); + try { + conv = findAnyConverter(cls); + } catch (RuntimeException ex) { + registered.putIfAbsent(cls, CACHED_NULL); + throw ex; + } if (conv == null) { registered.putIfAbsent(cls, CACHED_NULL); - throw new IllegalStateException("No registered converter found: " + cls); + return null; } registered.putIfAbsent(cls, conv); } return conv; } + /** + * Finds a converter searching registered and annotated. + * + * @param <T> the type of the converter + * @param cls the class to find a method for, not null + * @return the converter, not null + * @throws RuntimeException if invalid + */ @SuppressWarnings("unchecked") - private <T> StringConverter<T> findAnnotationConverter(final Class<T> cls) { + private <T> StringConverter<T> findAnyConverter(final Class<T> cls) { StringConverter<T> conv = null; // check for registered on superclass Class<?> loopCls = cls.getSuperclass(); @@ -271,170 +407,36 @@ public final class StringConvert { return conv; } } - // check for annotations - conv = findAnnotatedConverter(cls); - if (conv != null) { - return conv; - } - return null; - } - - /** - * Finds the conversion method. - * - * @param <T> the type of the converter - * @param cls the class to find a method for, not null - * @return the method to call, null means use {@code toString} - */ - private <T> StringConverter<T> findAnnotatedConverter(final Class<T> cls) { - Method toString = findToStringMethod(cls); // checks superclasses - if (toString == null) { - return null; - } - Constructor<T> con = findFromStringConstructor(cls); - Method fromString = findFromStringMethod(cls, con == null); // optionally checks superclasses - if (con == null && fromString == null) { - throw new IllegalStateException("Class annotated with @ToString but not with @FromString: " + cls.getName()); - } - if (con != null && fromString != null) { - throw new IllegalStateException("Both method and constructor are annotated with @FromString: " + cls.getName()); - } - if (con != null) { - return new MethodConstructorStringConverter<T>(cls, toString, con); - } else { - return new MethodsStringConverter<T>(cls, toString, fromString); - } - } - - /** - * Finds the conversion method. - * - * @param cls the class to find a method for, not null - * @return the method to call, null means use {@code toString} - */ - private Method findToStringMethod(Class<?> cls) { - Method matched = null; - // find in superclass hierarchy - Class<?> loopCls = cls; - while (loopCls != null && matched == null) { - Method[] methods = loopCls.getDeclaredMethods(); - for (Method method : methods) { - ToString toString = method.getAnnotation(ToString.class); - if (toString != null) { - if (matched != null) { - throw new IllegalStateException("Two methods are annotated with @ToString: " + cls.getName()); - } - matched = method; - } - } - loopCls = loopCls.getSuperclass(); - } - // find in immediate parent interfaces - if (matched == null) { - for (Class<?> loopIfc : cls.getInterfaces()) { - Method[] methods = loopIfc.getDeclaredMethods(); - for (Method method : methods) { - ToString toString = method.getAnnotation(ToString.class); - if (toString != null) { - if (matched != null) { - throw new IllegalStateException("Two methods are annotated with @ToString on interfaces: " + cls.getName()); - } - matched = method; - } - } - } - } - return matched; - } - - /** - * Finds the conversion method. - * - * @param <T> the type of the converter - * @param cls the class to find a method for, not null - * @return the method to call, null means use {@code toString} - */ - private <T> Constructor<T> findFromStringConstructor(Class<T> cls) { - Constructor<T> con; - try { - con = cls.getDeclaredConstructor(String.class); - } catch (NoSuchMethodException ex) { - try { - con = cls.getDeclaredConstructor(CharSequence.class); - } catch (NoSuchMethodException ex2) { - return null; - } - } - FromString fromString = con.getAnnotation(FromString.class); - return fromString != null ? con : null; - } - - /** - * Finds the conversion method. - * - * @param cls the class to find a method for, not null - * @return the method to call, null means not found - */ - private Method findFromStringMethod(Class<?> cls, boolean searchSuperclasses) { - Method matched = null; - // find in superclass hierarchy - Class<?> loopCls = cls; - while (loopCls != null && matched == null) { - matched = findFromString(loopCls, matched); - if (searchSuperclasses == false) { - break; - } - loopCls = loopCls.getSuperclass(); - } - // find in immediate parent interfaces - if (searchSuperclasses && matched == null) { - for (Class<?> loopIfc : cls.getInterfaces()) { - matched = findFromString(loopIfc, matched); + // check factories + for (StringConverterFactory factory : factories) { + conv = (StringConverter<T>) factory.findConverter(cls); + if (conv != null) { + return conv; } } - return matched; + return null; } + //----------------------------------------------------------------------- /** - * Finds the conversion method. + * Registers a converter factory. + * <p> + * This will be registered ahead of all existing factories. + * <p> + * No new factories may be registered for the global singleton. * - * @param cls the class to find a method for, not null - * @param matched the matched method, may be null - * @return the method to call, null means not found + * @param factory the converter factory, not null + * @throws IllegalStateException if trying to alter the global singleton + * @since 1.5 */ - private Method findFromString(Class<?> cls, Method matched) { - // find in declared methods - Method[] methods = cls.getDeclaredMethods(); - for (Method method : methods) { - FromString fromString = method.getAnnotation(FromString.class); - if (fromString != null) { - if (matched != null) { - throw new IllegalStateException("Two methods are annotated with @FromString: " + cls.getName()); - } - matched = method; - } + public void registerFactory(final StringConverterFactory factory) { + if (factory == null) { + throw new IllegalArgumentException("Factory must not be null"); } - // check for factory - FromStringFactory factory = cls.getAnnotation(FromStringFactory.class); - if (factory != null) { - if (matched != null) { - throw new IllegalStateException("Class annotated with @FromString and @FromStringFactory: " + cls.getName()); - } - Method[] factoryMethods = factory.factory().getDeclaredMethods(); - for (Method method : factoryMethods) { - // handle factory containing multiple FromString for different types - if (cls.isAssignableFrom(method.getReturnType())) { - FromString fromString = method.getAnnotation(FromString.class); - if (fromString != null) { - if (matched != null) { - throw new IllegalStateException("Two methods are annotated with @FromString on the factory: " + factory.factory().getName()); - } - matched = method; - } - } - } + if (this == INSTANCE) { + throw new IllegalStateException("Global singleton cannot be extended"); } - return matched; + factories.add(0, factory); } //----------------------------------------------------------------------- diff --git a/src/main/java/org/joda/convert/StringConverter.java b/src/main/java/org/joda/convert/StringConverter.java index e90f51b..f09335b 100644 --- a/src/main/java/org/joda/convert/StringConverter.java +++ b/src/main/java/org/joda/convert/StringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/ToStringConverter.java b/src/main/java/org/joda/convert/StringConverterFactory.java similarity index 57% copy from src/main/java/org/joda/convert/ToStringConverter.java copy to src/main/java/org/joda/convert/StringConverterFactory.java index 39b32af..067c575 100644 --- a/src/main/java/org/joda/convert/ToStringConverter.java +++ b/src/main/java/org/joda/convert/StringConverterFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,20 +16,22 @@ package org.joda.convert; /** - * Interface defining conversion to a {@code String}. + * Factory for {@code StringConverter} that allows converters to be + * created dynamically or easily initialised. * <p> - * ToStringConverter is an interface and must be implemented with care. * Implementations must be immutable and thread-safe. * - * @param <T> the type of the converter + * @since 1.5 */ -public interface ToStringConverter<T> { +public interface StringConverterFactory { /** - * Converts the specified object to a {@code String}. - * @param object the object to convert, not null - * @return the converted string, may be null but generally not + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid */ - String convertToString(T object); + StringConverter<?> findConverter(Class<?> cls); } diff --git a/src/main/java/org/joda/convert/ToString.java b/src/main/java/org/joda/convert/ToString.java index da248e1..c44e30e 100644 --- a/src/main/java/org/joda/convert/ToString.java +++ b/src/main/java/org/joda/convert/ToString.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/ToStringConverter.java b/src/main/java/org/joda/convert/ToStringConverter.java index 39b32af..3b50658 100644 --- a/src/main/java/org/joda/convert/ToStringConverter.java +++ b/src/main/java/org/joda/convert/ToStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/joda/convert/factory/BooleanArrayStringConverterFactory.java b/src/main/java/org/joda/convert/factory/BooleanArrayStringConverterFactory.java new file mode 100644 index 0000000..ac1421c --- /dev/null +++ b/src/main/java/org/joda/convert/factory/BooleanArrayStringConverterFactory.java @@ -0,0 +1,103 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert.factory; + +import org.joda.convert.StringConverter; +import org.joda.convert.StringConverterFactory; + +/** + * Factory for {@code StringConverter} providing support for primitive boolean array + * as a sequence of 'T' and 'F'. + * <p> + * This is intended as a human readable format, not a compact format. + * <p> + * To use, simply register the instance with a {@code StringConvert} instance. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +public final class BooleanArrayStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + public static final StringConverterFactory INSTANCE = new BooleanArrayStringConverterFactory(); + + /** + * Restricted constructor. + */ + private BooleanArrayStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + if (cls == boolean[].class) { + return BooleanArrayStringConverter.INSTANCE; + } + return null; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + + //----------------------------------------------------------------------- + enum BooleanArrayStringConverter implements StringConverter<boolean[]> { + INSTANCE { + @Override + public String convertToString(boolean[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length); + for (int i = 0; i < array.length; i++) { + buf.append(array[i] ? 'T' : 'F'); + } + return buf.toString(); + } + @Override + public boolean[] convertFromString(Class<? extends boolean[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + boolean[] array = new boolean[str.length()]; + for (int i = 0; i < array.length; i++) { + char ch = str.charAt(i); + if (ch == 'T') { + array[i] = true; + } else if (ch == 'F') { + array[i] = false; + } else { + throw new IllegalArgumentException("Invalid boolean[] string, must consist only of 'T' and 'F'"); + } + } + return array; + } + }; + private static final boolean[] EMPTY = new boolean[0]; + } + +} diff --git a/src/main/java/org/joda/convert/factory/BooleanObjectArrayStringConverterFactory.java b/src/main/java/org/joda/convert/factory/BooleanObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..99a2caa --- /dev/null +++ b/src/main/java/org/joda/convert/factory/BooleanObjectArrayStringConverterFactory.java @@ -0,0 +1,105 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert.factory; + +import org.joda.convert.StringConverter; +import org.joda.convert.StringConverterFactory; + +/** + * Factory for {@code StringConverter} providing support for Boolean object array + * as a sequence of 'T', 'F' and '-' for null. + * <p> + * This is intended as a human readable format, not a compact format. + * <p> + * To use, simply register the instance with a {@code StringConvert} instance. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +public final class BooleanObjectArrayStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + public static final StringConverterFactory INSTANCE = new BooleanObjectArrayStringConverterFactory(); + + /** + * Restricted constructor. + */ + private BooleanObjectArrayStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + if (cls == Boolean[].class) { + return BooleanArrayStringConverter.INSTANCE; + } + return null; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + + //----------------------------------------------------------------------- + enum BooleanArrayStringConverter implements StringConverter<Boolean[]> { + INSTANCE { + @Override + public String convertToString(Boolean[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length); + for (int i = 0; i < array.length; i++) { + buf.append(array[i] == null ? '-' : (array[i].booleanValue() ? 'T' : 'F')); + } + return buf.toString(); + } + @Override + public Boolean[] convertFromString(Class<? extends Boolean[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + Boolean[] array = new Boolean[str.length()]; + for (int i = 0; i < array.length; i++) { + char ch = str.charAt(i); + if (ch == 'T') { + array[i] = Boolean.TRUE; + } else if (ch == 'F') { + array[i] = Boolean.FALSE; + } else if (ch == '-') { + array[i] = null; + } else { + throw new IllegalArgumentException("Invalid Boolean[] string, must consist only of 'T', 'F' and '-'"); + } + } + return array; + } + }; + private static final Boolean[] EMPTY = new Boolean[0]; + } + +} diff --git a/src/main/java/org/joda/convert/factory/ByteObjectArrayStringConverterFactory.java b/src/main/java/org/joda/convert/factory/ByteObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..b1cfbd8 --- /dev/null +++ b/src/main/java/org/joda/convert/factory/ByteObjectArrayStringConverterFactory.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert.factory; + +import org.joda.convert.StringConverter; +import org.joda.convert.StringConverterFactory; + +/** + * Factory for {@code StringConverter} providing support for Byte object array + * as a sequence of two letter hex codes for each byte plus '--' for null. + * <p> + * This is intended as a human readable format, not a compact format. + * <p> + * To use, simply register the instance with a {@code StringConvert} instance. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +public final class ByteObjectArrayStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + public static final StringConverterFactory INSTANCE = new ByteObjectArrayStringConverterFactory(); + + /** + * Restricted constructor. + */ + private ByteObjectArrayStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + if (cls == Byte[].class) { + return ByteArrayStringConverter.INSTANCE; + } + return null; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + + //----------------------------------------------------------------------- + enum ByteArrayStringConverter implements StringConverter<Byte[]> { + INSTANCE { + @Override + public String convertToString(Byte[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length); + for (int i = 0; i < array.length; i++) { + if (array[i] == null) { + buf.append('-').append('-'); + } else { + int b = array[i].byteValue(); + buf.append(HEX.charAt((b & 0xF0) >>> 4)).append(HEX.charAt(b & 0x0F)); + } + } + return buf.toString(); + } + @Override + public Byte[] convertFromString(Class<? extends Byte[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + if (str.length() % 2 == 1) { + throw new IllegalArgumentException("Invalid Byte[] string"); + } + Byte[] array = new Byte[str.length() / 2]; + for (int i = 0; i < array.length; i++) { + String in = str.substring(i * 2, i * 2 + 2); + if (in.equals("--")) { + array[i] = null; + } else { + array[i] = (byte) Integer.parseInt(in, 16); + } + } + return array; + } + }; + private static final Byte[] EMPTY = new Byte[0]; + private static final String HEX = "0123456789ABCDEF"; + } + +} diff --git a/src/main/java/org/joda/convert/factory/CharObjectArrayStringConverterFactory.java b/src/main/java/org/joda/convert/factory/CharObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..2f17fc1 --- /dev/null +++ b/src/main/java/org/joda/convert/factory/CharObjectArrayStringConverterFactory.java @@ -0,0 +1,128 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert.factory; + +import java.util.Arrays; +import java.util.regex.Pattern; + +import org.joda.convert.StringConverter; +import org.joda.convert.StringConverterFactory; + +/** + * Factory for {@code StringConverter} providing support for Character object arrays + * as a string, using backslash as an escape. + * <p> + * Double backslash is a backslash. + * One backslash followed by a dash is null. + * <p> + * To use, simply register the instance with a {@code StringConvert} instance. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +public final class CharObjectArrayStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + public static final StringConverterFactory INSTANCE = new CharObjectArrayStringConverterFactory(); + /** + * Delimiter to find. + */ + static final Pattern DELIMITER = Pattern.compile("[,]"); + + /** + * Restricted constructor. + */ + private CharObjectArrayStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + if (cls == Character[].class) { + return CharecterArrayStringConverter.INSTANCE; + } + return null; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + + //----------------------------------------------------------------------- + enum CharecterArrayStringConverter implements StringConverter<Character[]> { + INSTANCE { + @Override + public String convertToString(Character[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + for (int i = 0; i < array.length; i++) { + if (array[i] == null) { + buf.append("\\-"); + } else { + char ch = array[i].charValue(); + if (ch == '\\') { + buf.append("\\\\"); + } else { + buf.append(ch); + } + } + } + return buf.toString(); + } + @Override + public Character[] convertFromString(Class<? extends Character[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + Character[] array = new Character[str.length()]; + int arrayPos = 0; + int pos; + while ((pos = str.indexOf('\\')) >= 0) { + for (int i = 0; i < pos; i++) { + array[arrayPos++] = str.charAt(i); + } + if (str.charAt(pos + 1) == '\\') { + array[arrayPos++] = '\\'; + } else if (str.charAt(pos + 1) == '-') { + array[arrayPos++] = null; + } else { + throw new IllegalArgumentException("Invalid Character[] string, incorrect escape"); + } + str = str.substring(pos + 2); + } + for (int i = 0; i < str.length(); i++) { + array[arrayPos++] = str.charAt(i); + } + return Arrays.copyOf(array, arrayPos); + } + }; + private static final Character[] EMPTY = new Character[0]; + } + +} diff --git a/src/main/java/org/joda/convert/factory/NumericArrayStringConverterFactory.java b/src/main/java/org/joda/convert/factory/NumericArrayStringConverterFactory.java new file mode 100644 index 0000000..5144697 --- /dev/null +++ b/src/main/java/org/joda/convert/factory/NumericArrayStringConverterFactory.java @@ -0,0 +1,240 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert.factory; + +import java.util.regex.Pattern; + +import org.joda.convert.StringConverter; +import org.joda.convert.StringConverterFactory; + +/** + * Factory for {@code StringConverter} providing support for primitive arrays + * as a comma separated list. + * <p> + * To use, simply register the instance with a {@code StringConvert} instance. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +public final class NumericArrayStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + public static final StringConverterFactory INSTANCE = new NumericArrayStringConverterFactory(); + /** + * Delimiter to find. + */ + static final Pattern DELIMITER = Pattern.compile("[,]"); + + /** + * Restricted constructor. + */ + private NumericArrayStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + if (cls.isArray() && cls.getComponentType().isPrimitive()) { + if (cls == long[].class) { + return LongArrayStringConverter.INSTANCE; + } + if (cls == int[].class) { + return IntArrayStringConverter.INSTANCE; + } + if (cls == short[].class) { + return ShortArrayStringConverter.INSTANCE; + } + if (cls == double[].class) { + return DoubleArrayStringConverter.INSTANCE; + } + if (cls == float[].class) { + return FloatArrayStringConverter.INSTANCE; + } + } + return null; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + + //----------------------------------------------------------------------- + enum LongArrayStringConverter implements StringConverter<long[]> { + INSTANCE { + @Override + public String convertToString(long[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + buf.append(array[0]); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i]); + } + return buf.toString(); + } + @Override + public long[] convertFromString(Class<? extends long[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + long[] array = new long[split.length]; + for (int i = 0; i < split.length; i++) { + array[i] = Long.parseLong(split[i]); + } + return array; + } + }; + private static final long[] EMPTY = new long[0]; + } + + //----------------------------------------------------------------------- + enum IntArrayStringConverter implements StringConverter<int[]> { + INSTANCE { + @Override + public String convertToString(int[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 6); + buf.append(array[0]); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i]); + } + return buf.toString(); + } + @Override + public int[] convertFromString(Class<? extends int[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + int[] array = new int[split.length]; + for (int i = 0; i < split.length; i++) { + array[i] = Integer.parseInt(split[i]); + } + return array; + } + }; + private static final int[] EMPTY = new int[0]; + } + + //----------------------------------------------------------------------- + enum ShortArrayStringConverter implements StringConverter<short[]> { + INSTANCE { + @Override + public String convertToString(short[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 3); + buf.append(array[0]); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i]); + } + return buf.toString(); + } + @Override + public short[] convertFromString(Class<? extends short[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + short[] array = new short[split.length]; + for (int i = 0; i < split.length; i++) { + array[i] = Short.parseShort(split[i]); + } + return array; + } + }; + private static final short[] EMPTY = new short[0]; + } + + //----------------------------------------------------------------------- + enum DoubleArrayStringConverter implements StringConverter<double[]> { + INSTANCE { + @Override + public String convertToString(double[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + buf.append(array[0]); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i]); + } + return buf.toString(); + } + @Override + public double[] convertFromString(Class<? extends double[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + double[] array = new double[split.length]; + for (int i = 0; i < split.length; i++) { + array[i] = Double.parseDouble(split[i]); + } + return array; + } + }; + private static final double[] EMPTY = new double[0]; + } + + //----------------------------------------------------------------------- + enum FloatArrayStringConverter implements StringConverter<float[]> { + INSTANCE { + @Override + public String convertToString(float[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + buf.append(array[0]); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i]); + } + return buf.toString(); + } + @Override + public float[] convertFromString(Class<? extends float[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + float[] array = new float[split.length]; + for (int i = 0; i < split.length; i++) { + array[i] = Float.parseFloat(split[i]); + } + return array; + } + }; + private static final float[] EMPTY = new float[0]; + } + +} diff --git a/src/main/java/org/joda/convert/factory/NumericObjectArrayStringConverterFactory.java b/src/main/java/org/joda/convert/factory/NumericObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..5514d94 --- /dev/null +++ b/src/main/java/org/joda/convert/factory/NumericObjectArrayStringConverterFactory.java @@ -0,0 +1,250 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert.factory; + +import java.util.regex.Pattern; + +import org.joda.convert.StringConverter; +import org.joda.convert.StringConverterFactory; + +/** + * Factory for {@code StringConverter} providing support for numeric object arrays + * as a comma separated list, using '-' for null. + * <p> + * To use, simply register the instance with a {@code StringConvert} instance. + * <p> + * This class is immutable and thread-safe. + * + * @since 1.5 + */ +public final class NumericObjectArrayStringConverterFactory implements StringConverterFactory { + + /** + * Singleton instance. + */ + public static final StringConverterFactory INSTANCE = new NumericObjectArrayStringConverterFactory(); + /** + * Delimiter to find. + */ + static final Pattern DELIMITER = Pattern.compile("[,]"); + + /** + * Restricted constructor. + */ + private NumericObjectArrayStringConverterFactory() { + } + + //----------------------------------------------------------------------- + /** + * Finds a converter by type. + * + * @param cls the type to lookup, not null + * @return the converter, null if not found + * @throws RuntimeException (or subclass) if source code is invalid + */ + public StringConverter<?> findConverter(Class<?> cls) { + if (cls.isArray()) { + if (cls == Long[].class) { + return LongArrayStringConverter.INSTANCE; + } + if (cls == Integer[].class) { + return IntArrayStringConverter.INSTANCE; + } + if (cls == Short[].class) { + return ShortArrayStringConverter.INSTANCE; + } + if (cls == Double[].class) { + return DoubleArrayStringConverter.INSTANCE; + } + if (cls == Float[].class) { + return FloatArrayStringConverter.INSTANCE; + } + } + return null; + } + + //----------------------------------------------------------------------- + @Override + public String toString() { + return getClass().getSimpleName(); + } + + //----------------------------------------------------------------------- + enum LongArrayStringConverter implements StringConverter<Long[]> { + INSTANCE { + @Override + public String convertToString(Long[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + buf.append(array[0] != null ? array[0] : "-"); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i] != null ? array[i] : "-"); + } + return buf.toString(); + } + @Override + public Long[] convertFromString(Class<? extends Long[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + Long[] array = new Long[split.length]; + for (int i = 0; i < split.length; i++) { + if (split[i].equals("-") == false) { + array[i] = Long.parseLong(split[i]); + } + } + return array; + } + }; + private static final Long[] EMPTY = new Long[0]; + } + + //----------------------------------------------------------------------- + enum IntArrayStringConverter implements StringConverter<Integer[]> { + INSTANCE { + @Override + public String convertToString(Integer[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 6); + buf.append(array[0] != null ? array[0] : "-"); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i] != null ? array[i] : "-"); + } + return buf.toString(); + } + @Override + public Integer[] convertFromString(Class<? extends Integer[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + Integer[] array = new Integer[split.length]; + for (int i = 0; i < split.length; i++) { + if (split[i].equals("-") == false) { + array[i] = Integer.parseInt(split[i]); + } + } + return array; + } + }; + private static final Integer[] EMPTY = new Integer[0]; + } + + //----------------------------------------------------------------------- + enum ShortArrayStringConverter implements StringConverter<Short[]> { + INSTANCE { + @Override + public String convertToString(Short[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 3); + buf.append(array[0] != null ? array[0] : "-"); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i] != null ? array[i] : "-"); + } + return buf.toString(); + } + @Override + public Short[] convertFromString(Class<? extends Short[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + Short[] array = new Short[split.length]; + for (int i = 0; i < split.length; i++) { + if (split[i].equals("-") == false) { + array[i] = Short.parseShort(split[i]); + } + } + return array; + } + }; + private static final Short[] EMPTY = new Short[0]; + } + + //----------------------------------------------------------------------- + enum DoubleArrayStringConverter implements StringConverter<Double[]> { + INSTANCE { + @Override + public String convertToString(Double[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + buf.append(array[0] != null ? array[0] : "-"); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i] != null ? array[i] : "-"); + } + return buf.toString(); + } + @Override + public Double[] convertFromString(Class<? extends Double[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + Double[] array = new Double[split.length]; + for (int i = 0; i < split.length; i++) { + if (split[i].equals("-") == false) { + array[i] = Double.parseDouble(split[i]); + } + } + return array; + } + }; + private static final Double[] EMPTY = new Double[0]; + } + + //----------------------------------------------------------------------- + enum FloatArrayStringConverter implements StringConverter<Float[]> { + INSTANCE { + @Override + public String convertToString(Float[] array) { + if (array.length == 0) { + return ""; + } + StringBuilder buf = new StringBuilder(array.length * 8); + buf.append(array[0] != null ? array[0] : "-"); + for (int i = 1; i < array.length; i++) { + buf.append(',').append(array[i] != null ? array[i] : "-"); + } + return buf.toString(); + } + @Override + public Float[] convertFromString(Class<? extends Float[]> cls, String str) { + if (str.length() == 0) { + return EMPTY; + } + String[] split = DELIMITER.split(str); + Float[] array = new Float[split.length]; + for (int i = 0; i < split.length; i++) { + if (split[i].equals("-") == false) { + array[i] = Float.parseFloat(split[i]); + } + } + return array; + } + }; + private static final Float[] EMPTY = new Float[0]; + } + +} diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index c1b2154..a71e6d2 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -72,12 +72,12 @@ Various documentation is available: <section name="Releases"> <p> -<a href="download.html">Release 1.4</a> is the current latest release. +<a href="download.html">Release 1.5</a> is the current latest release. This release is considered stable and worthy of the 1.x tag. It depends on JDK 1.6 or later. </p> <p> -Available in the <a href="http://search.maven.org/#artifactdetails|org.joda|joda-convert|1.4|jar">Maven Central repository</a>. +Available in the <a href="http://search.maven.org/#artifactdetails|org.joda|joda-convert|1.5|jar">Maven Central repository</a>. </p> </section> diff --git a/src/site/xdoc/userguide.xml b/src/site/xdoc/userguide.xml index 2c089e4..a32bd2a 100644 --- a/src/site/xdoc/userguide.xml +++ b/src/site/xdoc/userguide.xml @@ -54,6 +54,10 @@ These cover all the standard JDK types for which conversion to and from a string The set also includes JSR-310 types, but these are optional and loaded by reflection. The system will run without any dependency. </p> <p> +Arrays of <code>byte</code> are handled as a standard JDK type using Base64. +Arrays of <code>char</code> are handled by a standard JDK type by conversion to a string. +</p> +<p> Each <code>StringConvert</code> instance, other than the global singleton, may have additional converters registered manually. Each converter implements the <code>StringConverter</code> interface, which is self explanatory. </p> @@ -62,8 +66,25 @@ Converters may also be manually added by method name. This is equivalent to using annotations, but suitable when you don't own the code to add them. See <code>StringConvert.registerMethods</code> and <code>StringConvert.registerMethodConstructor</code>. </p> +</subsection> + +<subsection name="Factories"> +<p> +In addition to manual registration of individual converters, each instance of <code>StringConvert</code> +has a list of factories to use. The <code>StringConverterFactory</code> interface defines the factory. +This allows either bulk registration or dynamic lookup of converters. +</p> +<p> +A factory is provided to allow numeric arrays to be converted to/from a comma separated list. +A separate factory handles numeric object arrays. +Another factory is provided to allow boolean arrays to be converted to/from a string such as 'TTFFT'. +Again, a separate factory handles boolean object arrays. +Primitive byte and char arrays are handled by default, but the primitive object arrays are +handled via their own factories. +</p> <p> -A converter can only be registered if one is not already registered for that type. +These extra factories must be manually registered, unless the <code>StringConvert.create()</code> +static method is used, which defines an "extended" converter with the factories included. </p> </subsection> diff --git a/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameter.java b/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameter.java index c250fbc..2e39bfe 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameter.java +++ b/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameterCount.java b/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameterCount.java index 91a8730..d720775 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameterCount.java +++ b/src/test/java/org/joda/convert/DistanceFromStringConstructorInvalidParameterCount.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceFromStringException.java b/src/test/java/org/joda/convert/DistanceFromStringException.java index b8dd645..9e322c5 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringException.java +++ b/src/test/java/org/joda/convert/DistanceFromStringException.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceFromStringInvalidParameter.java b/src/test/java/org/joda/convert/DistanceFromStringInvalidParameter.java index c1dee91..a845796 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringInvalidParameter.java +++ b/src/test/java/org/joda/convert/DistanceFromStringInvalidParameter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceFromStringInvalidParameterCount.java b/src/test/java/org/joda/convert/DistanceFromStringInvalidParameterCount.java index 352cac0..583d4a9 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringInvalidParameterCount.java +++ b/src/test/java/org/joda/convert/DistanceFromStringInvalidParameterCount.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceFromStringInvalidReturnType.java b/src/test/java/org/joda/convert/DistanceFromStringInvalidReturnType.java index d0a5a55..6ec25bd 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringInvalidReturnType.java +++ b/src/test/java/org/joda/convert/DistanceFromStringInvalidReturnType.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceFromStringNoToString.java b/src/test/java/org/joda/convert/DistanceFromStringNoToString.java index 1749fcf..db05528 100644 --- a/src/test/java/org/joda/convert/DistanceFromStringNoToString.java +++ b/src/test/java/org/joda/convert/DistanceFromStringNoToString.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceMethodAndConstructorAnnotations.java b/src/test/java/org/joda/convert/DistanceMethodAndConstructorAnnotations.java index d1529f0..81c94e3 100644 --- a/src/test/java/org/joda/convert/DistanceMethodAndConstructorAnnotations.java +++ b/src/test/java/org/joda/convert/DistanceMethodAndConstructorAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceMethodConstructor.java b/src/test/java/org/joda/convert/DistanceMethodConstructor.java index d559dab..b6674ce 100644 --- a/src/test/java/org/joda/convert/DistanceMethodConstructor.java +++ b/src/test/java/org/joda/convert/DistanceMethodConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceMethodConstructorCharSequence.java b/src/test/java/org/joda/convert/DistanceMethodConstructorCharSequence.java index a7ad0ad..ce53587 100644 --- a/src/test/java/org/joda/convert/DistanceMethodConstructorCharSequence.java +++ b/src/test/java/org/joda/convert/DistanceMethodConstructorCharSequence.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceMethodMethod.java b/src/test/java/org/joda/convert/DistanceMethodMethod.java index e8ba0fc..a995e44 100644 --- a/src/test/java/org/joda/convert/DistanceMethodMethod.java +++ b/src/test/java/org/joda/convert/DistanceMethodMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceMethodMethodCharSequence.java b/src/test/java/org/joda/convert/DistanceMethodMethodCharSequence.java index b0b2e65..57aa2b4 100644 --- a/src/test/java/org/joda/convert/DistanceMethodMethodCharSequence.java +++ b/src/test/java/org/joda/convert/DistanceMethodMethodCharSequence.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceNoAnnotations.java b/src/test/java/org/joda/convert/DistanceNoAnnotations.java index 58b3b59..29159cb 100644 --- a/src/test/java/org/joda/convert/DistanceNoAnnotations.java +++ b/src/test/java/org/joda/convert/DistanceNoAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceNoAnnotationsCharSequence.java b/src/test/java/org/joda/convert/DistanceNoAnnotationsCharSequence.java index a9413bc..1349fe3 100644 --- a/src/test/java/org/joda/convert/DistanceNoAnnotationsCharSequence.java +++ b/src/test/java/org/joda/convert/DistanceNoAnnotationsCharSequence.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceToStringException.java b/src/test/java/org/joda/convert/DistanceToStringException.java index e29c7ab..99934df 100644 --- a/src/test/java/org/joda/convert/DistanceToStringException.java +++ b/src/test/java/org/joda/convert/DistanceToStringException.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceToStringInvalidParameters.java b/src/test/java/org/joda/convert/DistanceToStringInvalidParameters.java index 91d36ee..12af26f 100644 --- a/src/test/java/org/joda/convert/DistanceToStringInvalidParameters.java +++ b/src/test/java/org/joda/convert/DistanceToStringInvalidParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceToStringInvalidReturnType.java b/src/test/java/org/joda/convert/DistanceToStringInvalidReturnType.java index 7cabbab..bfd2628 100644 --- a/src/test/java/org/joda/convert/DistanceToStringInvalidReturnType.java +++ b/src/test/java/org/joda/convert/DistanceToStringInvalidReturnType.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceToStringNoFromString.java b/src/test/java/org/joda/convert/DistanceToStringNoFromString.java index f87b7d0..cfb3a0e 100644 --- a/src/test/java/org/joda/convert/DistanceToStringNoFromString.java +++ b/src/test/java/org/joda/convert/DistanceToStringNoFromString.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceTwoFromStringMethodAnnotations.java b/src/test/java/org/joda/convert/DistanceTwoFromStringMethodAnnotations.java index 4a11f27..f1f4423 100644 --- a/src/test/java/org/joda/convert/DistanceTwoFromStringMethodAnnotations.java +++ b/src/test/java/org/joda/convert/DistanceTwoFromStringMethodAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceTwoToStringAnnotations.java b/src/test/java/org/joda/convert/DistanceTwoToStringAnnotations.java index 1f3a465..b2d1144 100644 --- a/src/test/java/org/joda/convert/DistanceTwoToStringAnnotations.java +++ b/src/test/java/org/joda/convert/DistanceTwoToStringAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceWithFactory.java b/src/test/java/org/joda/convert/DistanceWithFactory.java index 8627929..9c73a04 100644 --- a/src/test/java/org/joda/convert/DistanceWithFactory.java +++ b/src/test/java/org/joda/convert/DistanceWithFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/DistanceWithFactoryFactory.java b/src/test/java/org/joda/convert/DistanceWithFactoryFactory.java index 88fa2e9..3631531 100644 --- a/src/test/java/org/joda/convert/DistanceWithFactoryFactory.java +++ b/src/test/java/org/joda/convert/DistanceWithFactoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/MockDistanceStringConverter.java b/src/test/java/org/joda/convert/MockDistanceStringConverter.java index 1e75ea3..a98fdaa 100644 --- a/src/test/java/org/joda/convert/MockDistanceStringConverter.java +++ b/src/test/java/org/joda/convert/MockDistanceStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/MockIntegerStringConverter.java b/src/test/java/org/joda/convert/MockIntegerStringConverter.java index 79de32f..47b4cb2 100644 --- a/src/test/java/org/joda/convert/MockIntegerStringConverter.java +++ b/src/test/java/org/joda/convert/MockIntegerStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/SubMethodConstructor.java b/src/test/java/org/joda/convert/SubMethodConstructor.java index ce6df54..2eb5184 100644 --- a/src/test/java/org/joda/convert/SubMethodConstructor.java +++ b/src/test/java/org/joda/convert/SubMethodConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/SubMethodMethod.java b/src/test/java/org/joda/convert/SubMethodMethod.java index d3bae48..5dc9013 100644 --- a/src/test/java/org/joda/convert/SubMethodMethod.java +++ b/src/test/java/org/joda/convert/SubMethodMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/SubNoAnnotations.java b/src/test/java/org/joda/convert/SubNoAnnotations.java index af58042..098aaf3 100644 --- a/src/test/java/org/joda/convert/SubNoAnnotations.java +++ b/src/test/java/org/joda/convert/SubNoAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/SuperFactorySub.java b/src/test/java/org/joda/convert/SuperFactorySub.java index 6525382..2262e9d 100644 --- a/src/test/java/org/joda/convert/SuperFactorySub.java +++ b/src/test/java/org/joda/convert/SuperFactorySub.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/SuperFactorySuper.java b/src/test/java/org/joda/convert/SuperFactorySuper.java index 3e9be17..8a0dd89 100644 --- a/src/test/java/org/joda/convert/SuperFactorySuper.java +++ b/src/test/java/org/joda/convert/SuperFactorySuper.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/TestBooleanArrayStringConverterFactory.java b/src/test/java/org/joda/convert/TestBooleanArrayStringConverterFactory.java new file mode 100644 index 0000000..c6f84e3 --- /dev/null +++ b/src/test/java/org/joda/convert/TestBooleanArrayStringConverterFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.joda.convert.factory.BooleanArrayStringConverterFactory; +import org.junit.Test; + +/** + * Test BooleanArrayStringConverterFactory. + */ +public class TestBooleanArrayStringConverterFactory { + + @Test + public void test_longArray() { + doTest(new boolean[0], ""); + doTest(new boolean[] {true}, "T"); + doTest(new boolean[] {false}, "F"); + doTest(new boolean[] {true, true, false, true, false, false}, "TTFTFF"); + } + + private void doTest(boolean[] array, String str) { + StringConvert test = new StringConvert(true, BooleanArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(boolean[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(boolean[].class, str))); + } + +} diff --git a/src/test/java/org/joda/convert/TestBooleanObjectArrayStringConverterFactory.java b/src/test/java/org/joda/convert/TestBooleanObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..0d73041 --- /dev/null +++ b/src/test/java/org/joda/convert/TestBooleanObjectArrayStringConverterFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.joda.convert.factory.BooleanObjectArrayStringConverterFactory; +import org.junit.Test; + +/** + * Test BooleanObjectArrayStringConverterFactory. + */ +public class TestBooleanObjectArrayStringConverterFactory { + + @Test + public void test_longArray() { + doTest(new Boolean[0], ""); + doTest(new Boolean[] {true}, "T"); + doTest(new Boolean[] {false}, "F"); + doTest(new Boolean[] {null}, "-"); + doTest(new Boolean[] {true, true, false, null, true, false, null, null, false}, "TTF-TF--F"); + } + + private void doTest(Boolean[] array, String str) { + StringConvert test = new StringConvert(true, BooleanObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Boolean[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Boolean[].class, str))); + } + +} diff --git a/src/test/java/org/joda/convert/TestByteObjectArrayStringConverterFactory.java b/src/test/java/org/joda/convert/TestByteObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..dcfc92e --- /dev/null +++ b/src/test/java/org/joda/convert/TestByteObjectArrayStringConverterFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.joda.convert.factory.ByteObjectArrayStringConverterFactory; +import org.junit.Test; + +/** + * Test ByteObjectArrayStringConverterFactory. + */ +public class TestByteObjectArrayStringConverterFactory { + + @Test + public void test_ByteArray() { + doTest(new Byte[0], ""); + doTest(new Byte[] {(byte) 0}, "00"); + doTest(new Byte[] {null}, "--"); + doTest(new Byte[] {(byte) 0, (byte) 1, null, null, (byte) 15, (byte) 16, (byte) 127, (byte) -128, (byte) -1}, "0001----0F107F80FF"); + } + + private void doTest(Byte[] array, String str) { + StringConvert test = new StringConvert(true, ByteObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Byte[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Byte[].class, str))); + } + +} diff --git a/src/test/java/org/joda/convert/TestCharObjectArrayStringConverterFactory.java b/src/test/java/org/joda/convert/TestCharObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..8e6bc67 --- /dev/null +++ b/src/test/java/org/joda/convert/TestCharObjectArrayStringConverterFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.joda.convert.factory.CharObjectArrayStringConverterFactory; +import org.junit.Test; + +/** + * Test CharObjectArrayStringConverterFactory. + */ +public class TestCharObjectArrayStringConverterFactory { + + @Test + public void test_CharacterArray() { + doTest(new Character[0], ""); + doTest(new Character[] {'T'}, "T"); + doTest(new Character[] {'-'}, "-"); + doTest(new Character[] {null}, "\\-"); + doTest(new Character[] {'J', '-', 'T'}, "J-T"); + doTest(new Character[] {'\\', '\\', null}, "\\\\\\\\\\-"); + doTest(new Character[] {'-', 'H', 'e', null, null, 'o'}, "-He\\-\\-o"); + } + + private void doTest(Character[] array, String str) { + StringConvert test = new StringConvert(true, CharObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Character[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Character[].class, str))); + } + +} diff --git a/src/test/java/org/joda/convert/TestJDKStringConverters.java b/src/test/java/org/joda/convert/TestJDKStringConverters.java index 540bd0d..427dfbe 100644 --- a/src/test/java/org/joda/convert/TestJDKStringConverters.java +++ b/src/test/java/org/joda/convert/TestJDKStringConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.joda.convert; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.File; import java.math.BigDecimal; @@ -24,6 +25,7 @@ import java.math.RoundingMode; import java.net.InetAddress; import java.net.URI; import java.net.URL; +import java.util.Arrays; import java.util.Calendar; import java.util.Currency; import java.util.Date; @@ -107,12 +109,42 @@ public class TestJDKStringConverters { } @Test + public void test_charArray() { + JDKStringConverter test = JDKStringConverter.CHAR_ARRAY; + char[] array = new char[] {'M', 'a', 'p'}; + String str = "Map"; + assertEquals(char[].class, test.getType()); + assertEquals(str, test.convertToString(array)); + assertTrue(Arrays.equals(array, (char[]) test.convertFromString(char[].class, str))); + } + + @Test public void test_Byte() { JDKStringConverter test = JDKStringConverter.BYTE; doTest(test, Byte.class, Byte.valueOf((byte) 12), "12"); } @Test + public void test_byteArray1() { + JDKStringConverter test = JDKStringConverter.BYTE_ARRAY; + byte[] array = new byte[] {77, 97, 112}; + String str = "TWFw"; + assertEquals(byte[].class, test.getType()); + assertEquals(str, test.convertToString(array)); + assertTrue(Arrays.equals(array, (byte[]) test.convertFromString(byte[].class, str))); + } + + @Test + public void test_byteArray2() { + JDKStringConverter test = JDKStringConverter.BYTE_ARRAY; + byte[] array = new byte[] {77, 97}; + String str = "TWE="; + assertEquals(byte[].class, test.getType()); + assertEquals(str, test.convertToString(array)); + assertTrue(Arrays.equals(array, (byte[]) test.convertFromString(byte[].class, str))); + } + + @Test public void test_Boolean() { JDKStringConverter test = JDKStringConverter.BOOLEAN; doTest(test, Boolean.class, Boolean.TRUE, "true"); diff --git a/src/test/java/org/joda/convert/TestNumericArrayStringConverterFactory.java b/src/test/java/org/joda/convert/TestNumericArrayStringConverterFactory.java new file mode 100644 index 0000000..bbc4c66 --- /dev/null +++ b/src/test/java/org/joda/convert/TestNumericArrayStringConverterFactory.java @@ -0,0 +1,112 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.joda.convert.factory.NumericArrayStringConverterFactory; +import org.junit.Test; + +/** + * Test NumericArrayStringConverterFactory. + */ +public class TestNumericArrayStringConverterFactory { + + @Test + public void test_longArray() { + doTest(new long[0], ""); + doTest(new long[] {5}, "5"); + doTest(new long[] {-1234, 56789}, "-1234,56789"); + doTest(new long[] {12345678912345L, 12345678912345L}, "12345678912345,12345678912345"); + } + + private void doTest(long[] array, String str) { + StringConvert test = new StringConvert(true, NumericArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(long[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(long[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_intArray() { + doTest(new int[0], ""); + doTest(new int[] {5}, "5"); + doTest(new int[] {-1234, 56789}, "-1234,56789"); + } + + private void doTest(int[] array, String str) { + StringConvert test = new StringConvert(true, NumericArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(int[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(int[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_shortArray() { + doTest(new short[0], ""); + doTest(new short[] {5}, "5"); + doTest(new short[] {-1234, 5678}, "-1234,5678"); + } + + private void doTest(short[] array, String str) { + StringConvert test = new StringConvert(true, NumericArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(short[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(short[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_doubleArray() { + doTest(new double[0], ""); + doTest(new double[] {5d}, "5.0"); + doTest(new double[] {5.123456789d}, "5.123456789"); + doTest(new double[] {-1234d, 5678d}, "-1234.0,5678.0"); + doTest(new double[] {Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, -0.0d, +0.0d, 0d}, "NaN,-Infinity,Infinity,-0.0,0.0,0.0"); + doTest(new double[] {0.0000006d, 6000000000d}, "6.0E-7,6.0E9"); + } + + private void doTest(double[] array, String str) { + StringConvert test = new StringConvert(true, NumericArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(double[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(double[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_floatArray() { + doTest(new float[0], ""); + doTest(new float[] {5f}, "5.0"); + doTest(new float[] {5.1234f}, "5.1234"); + doTest(new float[] {-1234f, 5678f}, "-1234.0,5678.0"); + doTest(new float[] {Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, -0.0f, +0.0f, 0f}, "NaN,-Infinity,Infinity,-0.0,0.0,0.0"); + doTest(new float[] {0.0000006f, 6000000000f}, "6.0E-7,6.0E9"); + } + + private void doTest(float[] array, String str) { + StringConvert test = new StringConvert(true, NumericArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(float[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(float[].class, str))); + } + +} diff --git a/src/test/java/org/joda/convert/TestNumericObjectArrayStringConverterFactory.java b/src/test/java/org/joda/convert/TestNumericObjectArrayStringConverterFactory.java new file mode 100644 index 0000000..3fde3f1 --- /dev/null +++ b/src/test/java/org/joda/convert/TestNumericObjectArrayStringConverterFactory.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.joda.convert.factory.NumericObjectArrayStringConverterFactory; +import org.junit.Test; + +/** + * Test NumericObjectArrayStringConverterFactory. + */ +public class TestNumericObjectArrayStringConverterFactory { + + @Test + public void test_LongArray() { + doTest(new Long[0], ""); + doTest(new Long[] {5L}, "5"); + doTest(new Long[] {null}, "-"); + doTest(new Long[] {-1234L, null, 56789L, null, null, 5L}, "-1234,-,56789,-,-,5"); + doTest(new Long[] {12345678912345L, 12345678912345L}, "12345678912345,12345678912345"); + } + + private void doTest(Long[] array, String str) { + StringConvert test = new StringConvert(true, NumericObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Long[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Long[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_IntegerArray() { + doTest(new Integer[0], ""); + doTest(new Integer[] {5}, "5"); + doTest(new Integer[] {null}, "-"); + doTest(new Integer[] {-1234, null, 56789, null, null, 5}, "-1234,-,56789,-,-,5"); + } + + private void doTest(Integer[] array, String str) { + StringConvert test = new StringConvert(true, NumericObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Integer[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Integer[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_ShortArray() { + doTest(new Short[0], ""); + doTest(new Short[] {5}, "5"); + doTest(new Short[] {null}, "-"); + doTest(new Short[] {-1234, null, 5678, null, null, 5}, "-1234,-,5678,-,-,5"); + } + + private void doTest(Short[] array, String str) { + StringConvert test = new StringConvert(true, NumericObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Short[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Short[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_DoubleArray() { + doTest(new Double[0], ""); + doTest(new Double[] {5d}, "5.0"); + doTest(new Double[] {null}, "-"); + doTest(new Double[] {5.123456789d}, "5.123456789"); + doTest(new Double[] {-1234d, null, 5678d, null, null, 5d}, "-1234.0,-,5678.0,-,-,5.0"); + doTest(new Double[] {Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, -0.0d, +0.0d, 0d}, "NaN,-Infinity,Infinity,-0.0,0.0,0.0"); + doTest(new Double[] {0.0000006d, 6000000000d}, "6.0E-7,6.0E9"); + } + + private void doTest(Double[] array, String str) { + StringConvert test = new StringConvert(true, NumericObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Double[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Double[].class, str))); + } + + //----------------------------------------------------------------------- + @Test + public void test_FloatArray() { + doTest(new Float[0], ""); + doTest(new Float[] {5f}, "5.0"); + doTest(new Float[] {null}, "-"); + doTest(new Float[] {5.1234f}, "5.1234"); + doTest(new Float[] {-1234f, null, 5678f, null, null, 5f}, "-1234.0,-,5678.0,-,-,5.0"); + doTest(new Float[] {Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, -0.0f, +0.0f, 0f}, "NaN,-Infinity,Infinity,-0.0,0.0,0.0"); + doTest(new Float[] {0.0000006f, 6000000000f}, "6.0E-7,6.0E9"); + } + + private void doTest(Float[] array, String str) { + StringConvert test = new StringConvert(true, NumericObjectArrayStringConverterFactory.INSTANCE); + assertEquals(str, test.convertToString(array)); + assertEquals(str, test.convertToString(Float[].class, array)); + assertTrue(Arrays.equals(array, test.convertFromString(Float[].class, str))); + } + +} diff --git a/src/test/java/org/joda/convert/TestStringConvert.java b/src/test/java/org/joda/convert/TestStringConvert.java index ddca01d..f3a6580 100644 --- a/src/test/java/org/joda/convert/TestStringConvert.java +++ b/src/test/java/org/joda/convert/TestStringConvert.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.joda.convert; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; @@ -58,6 +60,14 @@ public class TestStringConvert { //----------------------------------------------------------------------- @Test + public void test_isConvertible() { + assertTrue(StringConvert.INSTANCE.isConvertible(Integer.class)); + assertTrue(StringConvert.INSTANCE.isConvertible(String.class)); + assertFalse(StringConvert.INSTANCE.isConvertible(Object.class)); + } + + //----------------------------------------------------------------------- + @Test public void test_convertToString() { Integer i = 6; assertEquals("6", StringConvert.INSTANCE.convertToString(i)); @@ -87,6 +97,13 @@ public class TestStringConvert { } @Test + public void test_convertToString_withType_noGenerics() { + Integer i = 6; + Class<?> cls = Integer.class; + assertEquals("6", StringConvert.INSTANCE.convertToString(cls, i)); + } + + @Test public void test_convertToString_withType_primitive1() { int i = 6; assertEquals("6", StringConvert.INSTANCE.convertToString(Integer.class, i)); @@ -150,6 +167,14 @@ public class TestStringConvert { } //----------------------------------------------------------------------- + @Test + public void test_findConverter() { + Class<Integer> cls = Integer.class; + StringConverter<Integer> conv = StringConvert.INSTANCE.findConverter(cls); + assertEquals(Integer.valueOf(12), conv.convertFromString(cls, "12")); + assertEquals("12", conv.convertToString(12)); + } + @Test(expected=IllegalArgumentException.class) public void test_findConverter_null() { StringConvert.INSTANCE.findConverter(null); @@ -162,6 +187,25 @@ public class TestStringConvert { //----------------------------------------------------------------------- @Test + public void test_findConverterNoGenerics() { + Class<?> cls = Integer.class; + StringConverter<Object> conv = StringConvert.INSTANCE.findConverterNoGenerics(cls); + assertEquals(Integer.valueOf(12), conv.convertFromString(cls, "12")); + assertEquals("12", conv.convertToString(12)); + } + + @Test(expected=IllegalArgumentException.class) + public void test_findConverterNoGenerics_null() { + StringConvert.INSTANCE.findConverterNoGenerics(null); + } + + @Test(expected=IllegalStateException.class) + public void test_findConverterNoGenerics_Object() { + StringConvert.INSTANCE.findConverterNoGenerics(Object.class); + } + + //----------------------------------------------------------------------- + @Test public void test_convert_annotationMethodMethod() { StringConvert test = new StringConvert(); DistanceMethodMethod d = new DistanceMethodMethod(25); diff --git a/src/test/java/org/joda/convert/TestStringConverterFactory.java b/src/test/java/org/joda/convert/TestStringConverterFactory.java new file mode 100644 index 0000000..884926a --- /dev/null +++ b/src/test/java/org/joda/convert/TestStringConverterFactory.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010-present Stephen Colebourne + * + * 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 org.joda.convert; + +import static org.junit.Assert.assertSame; + +import org.junit.Test; + +/** + * Test StringConvert factory. + */ +public class TestStringConverterFactory { + + @Test + public void test_constructor() { + StringConvert test = new StringConvert(true, new Factory1()); + assertSame(MockDistanceStringConverter.INSTANCE, test.findConverter(DistanceMethodMethod.class)); + } + + @Test(expected = IllegalArgumentException.class) + public void test_constructor_null() { + new StringConvert(true, (StringConverterFactory[]) null); + } + + @Test(expected = IllegalArgumentException.class) + public void test_constructor_nullInArray() { + new StringConvert(true, new StringConverterFactory[] {null}); + } + + @Test + public void test_registerFactory() { + StringConvert test = new StringConvert(); + test.registerFactory(new Factory1()); + assertSame(MockDistanceStringConverter.INSTANCE, test.findConverter(DistanceMethodMethod.class)); + } + + static class Factory1 implements StringConverterFactory { + @Override + public StringConverter<?> findConverter(Class<?> cls) { + if (cls == DistanceMethodMethod.class) { + return MockDistanceStringConverter.INSTANCE; + } + return null; + } + + } + +} diff --git a/src/test/java/org/joda/convert/test1/Test1Class.java b/src/test/java/org/joda/convert/test1/Test1Class.java index 46e29e1..964dc70 100644 --- a/src/test/java/org/joda/convert/test1/Test1Class.java +++ b/src/test/java/org/joda/convert/test1/Test1Class.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test1/Test1Interface.java b/src/test/java/org/joda/convert/test1/Test1Interface.java index 34624aa..a20f12e 100644 --- a/src/test/java/org/joda/convert/test1/Test1Interface.java +++ b/src/test/java/org/joda/convert/test1/Test1Interface.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test2/Test2Class.java b/src/test/java/org/joda/convert/test2/Test2Class.java index 2cfe734..df90aac 100644 --- a/src/test/java/org/joda/convert/test2/Test2Class.java +++ b/src/test/java/org/joda/convert/test2/Test2Class.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test2/Test2Factory.java b/src/test/java/org/joda/convert/test2/Test2Factory.java index 8e83ca4..c5fe8e9 100644 --- a/src/test/java/org/joda/convert/test2/Test2Factory.java +++ b/src/test/java/org/joda/convert/test2/Test2Factory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test2/Test2Interface.java b/src/test/java/org/joda/convert/test2/Test2Interface.java index f8937f5..d68189a 100644 --- a/src/test/java/org/joda/convert/test2/Test2Interface.java +++ b/src/test/java/org/joda/convert/test2/Test2Interface.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test3/Test3Class.java b/src/test/java/org/joda/convert/test3/Test3Class.java index 3c4ed74..45d2627 100644 --- a/src/test/java/org/joda/convert/test3/Test3Class.java +++ b/src/test/java/org/joda/convert/test3/Test3Class.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test3/Test3Factory.java b/src/test/java/org/joda/convert/test3/Test3Factory.java index bd364c6..d3e2719 100644 --- a/src/test/java/org/joda/convert/test3/Test3Factory.java +++ b/src/test/java/org/joda/convert/test3/Test3Factory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test3/Test3Interface.java b/src/test/java/org/joda/convert/test3/Test3Interface.java index ac69dc1..06aab3f 100644 --- a/src/test/java/org/joda/convert/test3/Test3Interface.java +++ b/src/test/java/org/joda/convert/test3/Test3Interface.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test3/Test3SuperClass.java b/src/test/java/org/joda/convert/test3/Test3SuperClass.java index b0225ee..83ff91b 100644 --- a/src/test/java/org/joda/convert/test3/Test3SuperClass.java +++ b/src/test/java/org/joda/convert/test3/Test3SuperClass.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test4/Test4Class.java b/src/test/java/org/joda/convert/test4/Test4Class.java index c026a2f..a386ce0 100644 --- a/src/test/java/org/joda/convert/test4/Test4Class.java +++ b/src/test/java/org/joda/convert/test4/Test4Class.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test4/Test4Factory.java b/src/test/java/org/joda/convert/test4/Test4Factory.java index dd5de49..dff11fd 100644 --- a/src/test/java/org/joda/convert/test4/Test4Factory.java +++ b/src/test/java/org/joda/convert/test4/Test4Factory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/org/joda/convert/test4/Test4Interface.java b/src/test/java/org/joda/convert/test4/Test4Interface.java index fd8d64f..8602f5a 100644 --- a/src/test/java/org/joda/convert/test4/Test4Interface.java +++ b/src/test/java/org/joda/convert/test4/Test4Interface.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 Stephen Colebourne + * Copyright 2010-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/joda-convert.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

