diff --git a/vcell-util/src/main/java/org/vcell/util/CastingUtils.java b/vcell-util/src/main/java/org/vcell/util/CastingUtils.java index fe60aaabc6..b9dc91ec27 100644 --- a/vcell-util/src/main/java/org/vcell/util/CastingUtils.java +++ b/vcell-util/src/main/java/org/vcell/util/CastingUtils.java @@ -9,12 +9,8 @@ public class CastingUtils { * @return obj as T or null if obj is null or not of type T */ public static <T> T downcast(Class<? extends T> clzz, Object obj) { - if (obj != null && clzz.isAssignableFrom(obj.getClass())) { - @SuppressWarnings("unchecked") - T rval = (T) obj; - return rval; - } - return null; + if (clzz == null || !clzz.isInstance(obj)) return null; + return clzz.cast(obj); } /** @@ -24,16 +20,12 @@ public static <T> T downcast(Class<? extends T> clzz, Object obj) { * @return CastInfo<T> object describing results */ public static <T> CastInfo<T> attemptCast(Class<T> clzz, Object obj) { - final String rname = clzz.getName(); - if (obj != null) { - final String aname = obj.getClass().getName(); - T result = downcast(clzz, obj); - if (result == null) { - return new FailInfo<>(rname, aname); - } - return new SucceedInfo<>(rname,aname,result); - } - return new FailInfo<>(rname, "null"); + final String requiredTypeName = clzz.getName(); + if (obj == null) return new FailInfo<>(requiredTypeName, "null"); + final String actualTypeName = obj.getClass().getName(); + T result = CastingUtils.downcast(clzz, obj); + if (result == null) return new FailInfo<>(requiredTypeName, actualTypeName); + return new SucceedInfo<>(requiredTypeName,actualTypeName,result); } public interface CastInfo <T> { @@ -63,23 +55,23 @@ public interface CastInfo <T> { } private abstract static class CiBase<T> implements CastInfo<T> { - final String rname; - final String aname; - protected CiBase(String rname, String aname) { - this.rname = rname; - this.aname = aname; + final String requiredTypeName; + final String actualTypeName; + protected CiBase(String requiredTypeName, String actualTypeName) { + this.requiredTypeName = requiredTypeName; + this.actualTypeName = actualTypeName; } - public String requiredName() { return rname; } - public String actualName() { return aname; } + public String requiredName() { return requiredTypeName; } + public String actualName() { return actualTypeName; } public String castMessage( ) { - return "cast from " + aname + " to " + rname; + return "cast from " + actualTypeName + " to " + requiredTypeName; } } private static class FailInfo<T> extends CiBase<T> { - FailInfo(String rname, String aname) { - super(rname,aname); + FailInfo(String requiredTypeName, String actualTypeName) { + super(requiredTypeName,actualTypeName); } public boolean isGood() { return false; @@ -93,8 +85,8 @@ public T get() { private static class SucceedInfo<T> extends CiBase<T> { final T obj; - SucceedInfo(String rname,String aname, T obj) { - super(rname,aname); + SucceedInfo(String requiredTypeName,String actualTypeName, T obj) { + super(requiredTypeName,actualTypeName); this.obj = obj; } public boolean isGood() { diff --git a/vcell-util/src/test/java/org/vcell/util/CastingUtilsTest.java b/vcell-util/src/test/java/org/vcell/util/CastingUtilsTest.java index d5712583bb..ec2e28169c 100644 --- a/vcell-util/src/test/java/org/vcell/util/CastingUtilsTest.java +++ b/vcell-util/src/test/java/org/vcell/util/CastingUtilsTest.java @@ -2,7 +2,7 @@ import org.junit.Test; -import java.util.*; +import static org.vcell.util.CastingUtils.CastInfo; import static org.junit.Assert.*; @@ -10,12 +10,33 @@ public class CastingUtilsTest { @Test public void downcastTest( ) { - Random rng = new Random(); - String str = rng.nextInt() % 2 > 0 ? "GUI" : "CLI"; // Fake random to satisfy compiler's redundancy complaints - Object objStr = str.substring(0,3); + String str = "VCell"; + Object objStr = str.substring(0, 5); // Ensure second argument is equal to str.length()! String backStr = CastingUtils.downcast(String.class, objStr); assertSame(str, backStr); Integer backInt = CastingUtils.downcast(Integer.class, objStr); assertNull(backInt); } + + @Test + public void attemptCastEtAllTest(){ + Object integer = Integer.parseInt("8"); + Object notInteger = Double.parseDouble("3.14"); + + // Good Cast + CastInfo<Integer> goodCast = CastingUtils.attemptCast(Integer.class, integer); + assertTrue(goodCast.isGood()); + assertEquals("java.lang.Integer", goodCast.requiredName()); + assertEquals("java.lang.Integer", goodCast.actualName()); + assertEquals("cast from java.lang.Integer to java.lang.Integer", goodCast.castMessage()); + assertEquals("8", goodCast.get().toString()); + + // Bad Cast + CastInfo<Integer> badCast = CastingUtils.attemptCast(Integer.class, notInteger); + assertFalse(badCast.isGood()); + assertEquals("java.lang.Integer", badCast.requiredName()); + assertNotEquals("java.lang.Integer", badCast.actualName()); + assertNotEquals("cast from java.lang.Integer to java.lang.Integer", badCast.castMessage()); + assertThrows(ProgrammingException.class, () -> badCast.get().toString()); + } }