JUNEAU-128 Code improvements around DynamicSwaps
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
index 30c51a2..08b66e9 100644
--- a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
@@ -450,20 +450,20 @@
@Test
public void getFromStringMethod() throws Exception {
- check("DA1.create(String)", da1.getFromStringMethod());
- check(null, da2.getFromStringMethod());
- check(null, da3.getFromStringMethod());
- check(null, da4.getFromStringMethod());
- check(null, da5.getFromStringMethod());
- check(null, da6.getFromStringMethod());
- check(null, da7.getFromStringMethod());
- check(null, da8.getFromStringMethod());
+ check("DA1.create(String)", da1.getStaticCreateMethod(String.class));
+ check(null, da2.getStaticCreateMethod(String.class));
+ check(null, da3.getStaticCreateMethod(String.class));
+ check(null, da4.getStaticCreateMethod(String.class));
+ check(null, da5.getStaticCreateMethod(String.class));
+ check(null, da6.getStaticCreateMethod(String.class));
+ check(null, da7.getStaticCreateMethod(String.class));
+ check(null, da8.getStaticCreateMethod(String.class));
}
@Test
public void getFromStringMethod_onType() throws Exception {
- check(null, aTypeInfo.getFromStringMethod());
- check(null, pTypeGenericArgInfo.getFromStringMethod());
+ check(null, aTypeInfo.getStaticCreateMethod(String.class));
+ check(null, pTypeGenericArgInfo.getStaticCreateMethod(String.class));
}
static class DBx {}
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/TransformCacheTest.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MutatersTest.java
similarity index 81%
rename from juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/TransformCacheTest.java
rename to juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MutatersTest.java
index ccad9e6..2f9c9d5 100644
--- a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/TransformCacheTest.java
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/MutatersTest.java
@@ -12,12 +12,12 @@
// ***************************************************************************************************************************
package org.apache.juneau.utils;
-import static org.apache.juneau.internal.TransformCache.*;
+import static org.apache.juneau.reflect.Mutaters.*;
import static org.junit.Assert.*;
import org.junit.*;
-public class TransformCacheTest {
+public class MutatersTest {
//-----------------------------------------------------------------------------------------------------------------
// Constructors.
@@ -37,15 +37,15 @@
}
@Test
public void stringConstructor() {
- assertEquals("foo", get(String.class, A.class).transform("foo").f);
+ assertEquals("foo", get(String.class, A.class).mutate("foo").f);
}
@Test
public void intConstructor() {
- assertEquals("1", get(int.class, A.class).transform(1).f);
+ assertEquals("1", get(int.class, A.class).mutate(1).f);
}
@Test
public void integerConstructor() {
- assertEquals("2", get(Integer.class, A.class).transform(2).f);
+ assertEquals("2", get(Integer.class, A.class).mutate(2).f);
}
//-----------------------------------------------------------------------------------------------------------------
@@ -60,7 +60,7 @@
}
@Test
public void fromString_create() {
- assertEquals("foo", get(String.class, D1.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D1.class).mutate("foo").f);
}
public static class D2 {
@@ -71,7 +71,7 @@
}
@Test
public void fromString_fromString() {
- assertEquals("foo", get(String.class, D2.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D2.class).mutate("foo").f);
}
public static class D3 {
@@ -82,7 +82,7 @@
}
@Test
public void fromString_fromValue() {
- assertEquals("foo", get(String.class, D3.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D3.class).mutate("foo").f);
}
public static class D4 {
@@ -93,7 +93,7 @@
}
@Test
public void fromString_valueOf() {
- assertEquals("foo", get(String.class, D4.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D4.class).mutate("foo").f);
}
public static class D5 {
@@ -104,7 +104,7 @@
}
@Test
public void fromString_parse() {
- assertEquals("foo", get(String.class, D5.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D5.class).mutate("foo").f);
}
public static class D6 {
@@ -115,7 +115,7 @@
}
@Test
public void fromString_parseString() {
- assertEquals("foo", get(String.class, D6.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D6.class).mutate("foo").f);
}
public static class D7 {
@@ -126,7 +126,7 @@
}
@Test
public void fromString_forName() {
- assertEquals("foo", get(String.class, D7.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D7.class).mutate("foo").f);
}
public static class D8 {
@@ -137,7 +137,7 @@
}
@Test
public void fromString_forString() {
- assertEquals("foo", get(String.class, D8.class).transform("foo").f);
+ assertEquals("foo", get(String.class, D8.class).mutate("foo").f);
}
//-----------------------------------------------------------------------------------------------------------------
@@ -154,7 +154,7 @@
}
@Test
public void fromX_create() {
- assertEquals("ok", get(X.class, E1.class).transform(new X()).f);
+ assertEquals("ok", get(X.class, E1.class).mutate(new X()).f);
}
public static class E2 {
@@ -165,6 +165,6 @@
}
@Test
public void fromX_fromX() {
- assertEquals("ok", get(X.class, E2.class).transform(new X()).f);
+ assertEquals("ok", get(X.class, E2.class).mutate(new X()).f);
}
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
index 9f0a2f4..8ada5d3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
@@ -428,7 +428,7 @@
return (T)new AtomicLong(b ? 1 : 0);
} else if (isNullOrEmpty(value)) {
return null;
- } else if (! hasTransform(from, to)) {
+ } else if (! hasMutater(from, to)) {
String s = value.toString();
int multiplier = (tc == Integer.class || tc == Short.class || tc == Long.class) ? getMultiplier(s) : 1;
@@ -487,10 +487,10 @@
return (T)toArray(to, Arrays.asList((Object[])value));
else if (startsWith(value.toString(), '['))
return (T)toArray(to, new ObjectList(value.toString()).setBeanSession(this));
- else if (to.hasTransformFrom(from))
- return to.transformFrom(value);
- else if (from.hasTransformTo(to))
- return from.transformTo(value, to);
+ else if (to.hasMutaterFrom(from))
+ return to.mutateFrom(value);
+ else if (from.hasMutaterTo(to))
+ return from.mutateTo(value, to);
else
return (T)toArray(to, new ObjectList((Object[])StringUtils.split(value.toString())).setBeanSession(this));
}
@@ -603,7 +603,7 @@
return (T)(Boolean.valueOf(((Number)value).intValue() != 0));
if (isNullOrEmpty(value))
return null;
- if (! hasTransform(from, to))
+ if (! hasMutater(from, to))
return (T)Boolean.valueOf(value.toString());
}
@@ -669,11 +669,11 @@
return (T)((Calendar)value).getTime();
}
- if (to.hasTransformFrom(from))
- return to.transformFrom(value);
+ if (to.hasMutaterFrom(from))
+ return to.mutateFrom(value);
- if (from.hasTransformTo(to))
- return from.transformTo(value, to);
+ if (from.hasMutaterTo(to))
+ return from.mutateTo(value, to);
if (to.isBean())
return newBeanMap(to.getInnerClass()).load(value.toString()).getBean();
@@ -688,8 +688,8 @@
throw new InvalidDataConversionException(value, to, null);
}
- private static boolean hasTransform(ClassMeta<?> from, ClassMeta<?> to) {
- return to.hasTransformFrom(from) || from.hasTransformTo(to);
+ private static boolean hasMutater(ClassMeta<?> from, ClassMeta<?> to) {
+ return to.hasMutaterFrom(from) || from.hasMutaterTo(to);
}
private static final boolean isNullOrEmpty(Object o) {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 746067f..bd59a8e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -109,9 +109,9 @@
private final BeanRegistry beanRegistry; // The bean registry of this class meta (if it has one).
private final ClassMeta<?>[] args; // Arg types if this is an array of args.
private final Object example; // Example object.
- private final Map<Class<?>,Transform<?,T>> fromTransforms = new ConcurrentHashMap<>();
- private final Map<Class<?>,Transform<T,?>> toTransforms = new ConcurrentHashMap<>();
- private final Transform<String,T> stringTransform;
+ private final Map<Class<?>,Mutater<?,T>> fromMutaters = new ConcurrentHashMap<>();
+ private final Map<Class<?>,Mutater<T,?>> toMutaters = new ConcurrentHashMap<>();
+ private final Mutater<String,T> stringMutater;
private ReadWriteLock lock = new ReentrantReadWriteLock(false);
private Lock rLock = lock.readLock(), wLock = lock.writeLock();
@@ -186,7 +186,7 @@
this.exampleField = builder.exampleField;
this.example = builder.example;
this.args = null;
- this.stringTransform = builder.stringTransform;
+ this.stringMutater = builder.stringMutater;
} catch (ClassMetaRuntimeException e) {
notABeanReason = e.getMessage();
throw e;
@@ -247,7 +247,7 @@
this.exampleField = mainType.exampleField;
this.example = mainType.example;
this.args = null;
- this.stringTransform = mainType.stringTransform;
+ this.stringMutater = mainType.stringMutater;
}
/**
@@ -291,7 +291,7 @@
this.exampleMethod = null;
this.exampleField = null;
this.example = null;
- this.stringTransform = null;
+ this.stringMutater = null;
}
@SuppressWarnings({"unchecked","rawtypes","hiding"})
@@ -337,7 +337,7 @@
Method exampleMethod;
Field exampleField;
Object example;
- Transform<String,T> stringTransform;
+ Mutater<String,T> stringMutater;
ClassMetaBuilder(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] pojoSwaps, PojoSwap<?,?>[] childPojoSwaps, Object example) {
this.innerClass = innerClass;
@@ -661,7 +661,7 @@
this.example = example;
- this.stringTransform = TransformCache.get(String.class, c);
+ this.stringMutater = Mutaters.get(String.class, c);
}
private BeanFilter findBeanFilter() {
@@ -1848,8 +1848,8 @@
*
* @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader.
*/
- public boolean hasReaderTransform() {
- return hasTransformFrom(Reader.class);
+ public boolean hasReaderMutater() {
+ return hasMutaterFrom(Reader.class);
}
/**
@@ -1857,8 +1857,8 @@
*
* @return The transform, or <jk>null</jk> if no such transform exists.
*/
- public Transform<Reader,T> getReaderTransform() {
- return getFromTransform(Reader.class);
+ public Mutater<Reader,T> getReaderMutater() {
+ return getFromMutater(Reader.class);
}
/**
@@ -1866,8 +1866,8 @@
*
* @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream.
*/
- public boolean hasInputStreamTransform() {
- return hasTransformFrom(InputStream.class);
+ public boolean hasInputStreamMutater() {
+ return hasMutaterFrom(InputStream.class);
}
/**
@@ -1875,8 +1875,8 @@
*
* @return The transform, or <jk>null</jk> if no such transform exists.
*/
- public Transform<InputStream,T> getInputStreamTransform() {
- return getFromTransform(InputStream.class);
+ public Mutater<InputStream,T> getInputStreamMutater() {
+ return getFromMutater(InputStream.class);
}
/**
@@ -1884,8 +1884,8 @@
*
* @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String.
*/
- public boolean hasStringTransform() {
- return stringTransform != null;
+ public boolean hasStringMutater() {
+ return stringMutater != null;
}
/**
@@ -1893,8 +1893,8 @@
*
* @return The transform, or <jk>null</jk> if no such transform exists.
*/
- public Transform<String,T> getStringTransform() {
- return stringTransform;
+ public Mutater<String,T> getStringMutater() {
+ return stringMutater;
}
/**
@@ -1903,8 +1903,8 @@
* @param c The class type to convert from.
* @return <jk>true</jk> if this class can be instantiated from the specified type.
*/
- public boolean hasTransformFrom(Class<?> c) {
- return getFromTransform(c) != null;
+ public boolean hasMutaterFrom(Class<?> c) {
+ return getFromMutater(c) != null;
}
/**
@@ -1913,8 +1913,8 @@
* @param c The class type to convert from.
* @return <jk>true</jk> if this class can be instantiated from the specified type.
*/
- public boolean hasTransformFrom(ClassMeta<?> c) {
- return getFromTransform(c.getInnerClass()) != null;
+ public boolean hasMutaterFrom(ClassMeta<?> c) {
+ return getFromMutater(c.getInnerClass()) != null;
}
/**
@@ -1923,8 +1923,8 @@
* @param c The class type to convert from.
* @return <jk>true</jk> if this class can be transformed to the specified type.
*/
- public boolean hasTransformTo(Class<?> c) {
- return getToTransform(c) != null;
+ public boolean hasMutaterTo(Class<?> c) {
+ return getToMutater(c) != null;
}
/**
@@ -1933,8 +1933,8 @@
* @param c The class type to convert from.
* @return <jk>true</jk> if this class can be transformed to the specified type.
*/
- public boolean hasTransformTo(ClassMeta<?> c) {
- return getToTransform(c.getInnerClass()) != null;
+ public boolean hasMutaterTo(ClassMeta<?> c) {
+ return getToMutater(c.getInnerClass()) != null;
}
/**
@@ -1944,9 +1944,9 @@
* @return The transformed object.
*/
@SuppressWarnings({"unchecked","rawtypes"})
- public T transformFrom(Object o) {
- Transform t = getFromTransform(o.getClass());
- return (T)(t == null ? null : t.transform(o));
+ public T mutateFrom(Object o) {
+ Mutater t = getFromMutater(o.getClass());
+ return (T)(t == null ? null : t.mutate(o));
}
/**
@@ -1957,9 +1957,9 @@
* @return The transformed object.
*/
@SuppressWarnings({"unchecked","rawtypes"})
- public <O> O transformTo(Object o, Class<O> c) {
- Transform t = getToTransform(c);
- return (O)(t == null ? null : t.transform(o));
+ public <O> O mutateTo(Object o, Class<O> c) {
+ Mutater t = getToMutater(c);
+ return (O)(t == null ? null : t.mutate(o));
}
/**
@@ -1969,8 +1969,8 @@
* @param c The class
* @return The transformed object.
*/
- public <O> O transformTo(Object o, ClassMeta<O> c) {
- return transformTo(o, c.getInnerClass());
+ public <O> O mutateTo(Object o, ClassMeta<O> c) {
+ return mutateTo(o, c.getInnerClass());
}
/**
@@ -1980,17 +1980,17 @@
* @return The transform, or <jk>null</jk> if no such transform exists.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- public <I> Transform<I,T> getFromTransform(Class<I> c) {
- Transform t = fromTransforms.get(c);
- if (t == TransformCache.NULL)
+ public <I> Mutater<I,T> getFromMutater(Class<I> c) {
+ Mutater t = fromMutaters.get(c);
+ if (t == Mutaters.NULL)
return null;
if (t == null) {
- t = TransformCache.get(c, innerClass);
+ t = Mutaters.get(c, innerClass);
if (t == null)
- t = TransformCache.NULL;
- fromTransforms.put(c, t);
+ t = Mutaters.NULL;
+ fromMutaters.put(c, t);
}
- return t == TransformCache.NULL ? null : t;
+ return t == Mutaters.NULL ? null : t;
}
/**
@@ -2000,17 +2000,17 @@
* @return The transform, or <jk>null</jk> if no such transform exists.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- public <O> Transform<T,O> getToTransform(Class<O> c) {
- Transform t = toTransforms.get(c);
- if (t == TransformCache.NULL)
+ public <O> Mutater<T,O> getToMutater(Class<O> c) {
+ Mutater t = toMutaters.get(c);
+ if (t == Mutaters.NULL)
return null;
if (t == null) {
- t = TransformCache.get(innerClass, c);
+ t = Mutaters.get(innerClass, c);
if (t == null)
- t = TransformCache.NULL;
- toTransforms.put(c, t);
+ t = Mutaters.NULL;
+ toMutaters.put(c, t);
}
- return t == TransformCache.NULL ? null : t;
+ return t == Mutaters.NULL ? null : t;
}
/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 4c69fb4..b2d72e1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -379,7 +379,6 @@
* <ul>
* <li>Have a public constructor that takes in a single <c>String</c> argument.
* <li>Have a static <c>fromString(String)</c> (or related) method.
- * <br>See {@link ClassInfo#getFromStringMethod()} for the list of possible static method names.
* <li>Be an <c>enum</c>.
* </ul>
*
@@ -388,8 +387,8 @@
* @return A new object instance, or <jk>null</jk> if a method for converting the string to an object could not be found.
*/
public static <T> T fromString(Class<T> c, String s) {
- Transform<String,T> t = TransformCache.get(String.class, c);
- return t == null ? null : t.transform(s);
+ Mutater<String,T> t = Mutaters.get(String.class, c);
+ return t == null ? null : t.mutate(s);
}
/**
@@ -407,8 +406,8 @@
public static String toString(Object o) {
if (o == null)
return null;
- Transform<Object,String> t = (Transform<Object,String>)TransformCache.get(o.getClass(), String.class);
- return t == null ? o.toString() : t.transform(o);
+ Mutater<Object,String> t = (Mutater<Object,String>)Mutaters.get(o.getClass(), String.class);
+ return t == null ? o.toString() : t.mutate(o);
}
/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/TransformCache.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/TransformCache.java
deleted file mode 100644
index 5795eb9..0000000
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/TransformCache.java
+++ /dev/null
@@ -1,226 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
-// * to you 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.apache.juneau.internal;
-
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.reflect.ReflectFlags.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.reflect.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-/**
- * Cache of object that convert POJOs to and from common types such as strings, readers, and input streams.
- */
-public class TransformCache {
- private static final ConcurrentHashMap<Class<?>,Map<Class<?>,Transform<?,?>>> CACHE = new ConcurrentHashMap<>();
-
- /**
- * Represents a non-existent transform.
- */
- public static final Transform<Object,Object> NULL = new Transform<Object,Object>() {
- @Override
- public Object transform(Object outer, Object in) {
- return null;
- }
- };
-
- // Special cases.
- static {
-
- // TimeZone doesn't follow any standard conventions.
- add(String.class, TimeZone.class,
- new Transform<String,TimeZone>() {
- @Override public TimeZone transform(Object outer, String in) {
- return TimeZone.getTimeZone(in);
- }
- }
- );
- add(TimeZone.class, String.class,
- new Transform<TimeZone,String>() {
- @Override public String transform(Object outer, TimeZone in) {
- return in.getID();
- }
- }
- );
-
- // Locale(String) doesn't work on strings like "ja_JP".
- add(String.class, Locale.class,
- new Transform<String,Locale>() {
- @Override
- public Locale transform(Object outer, String in) {
- return Locale.forLanguageTag(in.replace('_', '-'));
- }
- }
- );
-
- // String-to-Boolean transform should allow for "null" keyword.
- add(String.class, Boolean.class,
- new Transform<String,Boolean>() {
- @Override
- public Boolean transform(Object outer, String in) {
- if (in == null || "null".equals(in) || in.isEmpty())
- return null;
- return Boolean.valueOf(in);
- }
- }
- );
- }
-
- /**
- * Adds a transform for the specified input/output types.
- *
- * @param ic The input type.
- * @param oc The output type.
- * @param t The transform for converting the input to the output.
- */
- public static synchronized void add(Class<?> ic, Class<?> oc, Transform<?,?> t) {
- Map<Class<?>,Transform<?,?>> m = CACHE.get(oc);
- if (m == null) {
- m = new ConcurrentHashMap<>();
- CACHE.put(oc, m);
- }
- m.put(ic, t);
- }
-
- /**
- * Returns the transform for converting the specified input type to the specified output type.
- *
- * @param ic The input type.
- * @param oc The output type.
- * @return The transform for performing the conversion, or <jk>null</jk> if the conversion cannot be made.
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static <I,O> Transform<I,O> get(final Class<I> ic, final Class<O> oc) {
-
- if (ic == null || oc == null)
- return null;
-
- Map<Class<?>,Transform<?,?>> m = CACHE.get(oc);
- if (m == null) {
- m = new ConcurrentHashMap<>();
- CACHE.putIfAbsent(oc, m);
- m = CACHE.get(oc);
- }
-
- Transform t = m.get(ic);
- if (t != null)
- return t == NULL ? null : t;
-
- ClassInfo ici = getClassInfo(ic), oci = getClassInfo(oc);
-
- for (ClassInfo pic : ici.getAllParents()) {
- t = m.get(pic.inner());
- if (t != null) {
- m.put(pic.inner(), t);
- return t == NULL ? null : t;
- }
- }
-
- if (ic == oc) {
- t = new Transform<I,O>() {
- @Override public O transform(Object outer, I in) {
- return (O)in;
- }
- };
- } else if (ic == String.class) {
- final Class<?> oc2 = oci.hasPrimitiveWrapper() ? oci.getPrimitiveWrapper() : oc;
- ClassInfo oc2i = getClassInfo(oc2);
- final MethodInfo fromStringMethod = oc2i.getFromStringMethod();
- if (oc2.isEnum() && fromStringMethod == null) {
- t = new Transform<String,O>() {
- @Override
- public O transform(Object outer, String in) {
- return (O)Enum.valueOf((Class<? extends Enum>)oc2, in);
- }
- };
- } else {
- if (fromStringMethod != null) {
- t = new Transform<String,O>() {
- @Override
- public O transform(Object outer, String in) {
- try {
- return (O)fromStringMethod.invoke(null, in);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- };
- }
- }
- }
-
- if (t == null) {
- MethodInfo createMethod = oci.getStaticCreateMethod(ic);
- if (createMethod != null) {
- final Method cm = createMethod.inner();
- t = new Transform<I,O>() {
- @Override
- public O transform(Object context, I in) {
- try {
- return (O)cm.invoke(null, in);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- };
- } else {
- final ConstructorInfo c = oci.getPublicConstructor(ic);
- final boolean isMemberClass = oci.isMemberClass() && ! oci.isStatic();
- if (c != null && ! c.hasAnnotation(Deprecated.class)) {
- t = new Transform<I,O>() {
- @Override
- public O transform(Object outer, I in) {
- try {
- if (isMemberClass)
- return c.<O>invoke(outer, in);
- return c.<O>invoke(in);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- };
- }
-
- }
- }
-
- if (t == null) {
- for (MethodInfo m2 : ici.getAllMethods()) {
- if (m2.isAll(PUBLIC, NOT_STATIC, HAS_NO_PARAMS, NOT_DEPRECATED) && m2.getSimpleName().startsWith("to") && m2.hasReturnType(oc)) {
- final Method m3 = m2.inner();
- t = new Transform<I,O>() {
- @Override
- public O transform(Object outer, I in) {
- try {
- return (O)m3.invoke(in);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- };
- break;
- }
- }
- }
- if (t == null)
- t = NULL;
-
- m.put(ic, t);
-
- return t == NULL ? null : t;
- }
-}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
index fd9d227..035bcb7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
@@ -149,7 +149,7 @@
Object[] o = new Object[ss.length];
for (int i = 0; i < ss.length; i++)
o[i] = parse(partType, items, ss[i], eType);
- if (type.hasTransformFrom(schema.getParsedType()) || schema.getParsedType().hasTransformTo(type))
+ if (type.hasMutaterFrom(schema.getParsedType()) || schema.getParsedType().hasMutaterTo(type))
return toType(toType(o, schema.getParsedType()), type);
return toType(o, type);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
index a72f691..59cb5da 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
@@ -106,7 +106,7 @@
schema.validateOutput(value, ctx);
- if (type.hasTransformTo(schema.getParsedType()) || schema.getParsedType().hasTransformFrom(type)) {
+ if (type.hasMutaterTo(schema.getParsedType()) || schema.getParsedType().hasMutaterFrom(type)) {
value = toType(value, schema.getParsedType());
type = schema.getParsedType();
}
@@ -151,7 +151,7 @@
} else if (type.isCollection()) {
for (Object o : (Collection<?>)value)
l.add(serialize(partType, items, o));
- } else if (vt.hasTransformTo(String[].class)) {
+ } else if (vt.hasMutaterTo(String[].class)) {
String[] ss = toType(value, CM_StringArray);
for (int i = 0; i < ss.length; i++)
l.add(serialize(partType, items, ss[i]));
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index 51ee0bd..f226c67 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -410,34 +410,6 @@
//-----------------------------------------------------------------------------------------------------------------
/**
- * Finds the public static "fromString" method on this class.
- *
- * <p>
- * Looks for the following method names:
- * <ul>
- * <li><c>fromString</c>
- * <li><c>fromValue</c>
- * <li><c>valueOf</c>
- * <li><c>parse</c>
- * <li><c>parseString</c>
- * <li><c>forName</c>
- * <li><c>forString</c>
- * </ul>
- *
- * @return The static method, or <jk>null</jk> if it couldn't be found.
- */
- public MethodInfo getFromStringMethod() {
- if (c != null)
- for (MethodInfo m : getPublicMethods())
- if (m.isAll(STATIC, PUBLIC, NOT_DEPRECATED)
- && m.hasReturnType(c)
- && m.hasParamTypes(String.class)
- && isOneOf(m.getSimpleName(), "create","fromString","fromValue","valueOf","parse","parseString","forName","forString"))
- return m;
- return null;
- }
-
- /**
* Find the public static creator method on this class.
*
* <p>
@@ -445,7 +417,12 @@
* <ul>
* <li><c>create</c>
* <li><c>from</c>
- * <li><c>fromIC</c>
+ * <li><c>fromValue</c>
+ * <li><c>parse</c>
+ * <li><c>valueOf</c>
+ * <li><c>fromX</c>
+ * <li><c>forX</c>
+ * <li><c>parseX</c>
* </ul>
*
* @param ic The argument type.
@@ -458,7 +435,7 @@
if (m.isAll(STATIC, PUBLIC, NOT_DEPRECATED) && m.hasReturnType(c) && m.hasParamTypes(ic)) {
String n = m.getSimpleName(), cn = ic.getSimpleName();
if (
- isOneOf(n, "create","from","parse","valueOf")
+ isOneOf(n, "create","from","fromValue","parse","valueOf")
|| isOneOf(n, additionalNames)
|| (n.startsWith("from") && n.substring(4).equals(cn))
|| (n.startsWith("for") && n.substring(3).equals(cn))
@@ -1767,6 +1744,25 @@
return c != null ? c.getName() : t.getTypeName();
}
+ /**
+ * Same as {@link #getSimpleName()} but uses <js>"Array"</j> instead of <js>"[]"</js>.
+ *
+ * @return The readable name for this class.
+ */
+ public String getReadableName() {
+ if (c == null)
+ return t.getTypeName();
+ if (! c.isArray())
+ return c.getSimpleName();
+ Class<?> c = this.c;
+ StringBuilder sb = new StringBuilder();
+ while (c.isArray()) {
+ sb.append("Array");
+ c = c.getComponentType();
+ }
+ return c.getSimpleName() + sb;
+ }
+
//-----------------------------------------------------------------------------------------------------------------
// Hierarchy
//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Transform.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutater.java
similarity index 91%
rename from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Transform.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutater.java
index 28239b7..6b6741a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Transform.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutater.java
@@ -10,7 +10,7 @@
// * "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.apache.juneau.internal;
+package org.apache.juneau.reflect;
/**
* An interface for creating objects from other objects such as a <c>String</c> or <c>Reader</c>.
@@ -18,7 +18,7 @@
* @param <I> Input type.
* @param <O> Output type.
*/
-public abstract class Transform<I,O> {
+public abstract class Mutater<I,O> {
/**
* Method for instantiating an object from another object.
@@ -26,8 +26,8 @@
* @param in The input object.
* @return The output object.
*/
- public O transform(I in) {
- return transform(null, in);
+ public O mutate(I in) {
+ return mutate(null, in);
}
/**
@@ -37,5 +37,5 @@
* @param in The input object.
* @return The output object.
*/
- public abstract O transform(Object outer, I in);
+ public abstract O mutate(Object outer, I in);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java
new file mode 100644
index 0000000..fd95726
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java
@@ -0,0 +1,246 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.reflect;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.reflect.ReflectFlags.*;
+
+import java.util.concurrent.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Cache of object that convert POJOs to and from common types such as strings, readers, and input streams.
+ */
+public class Mutaters {
+ private static final ConcurrentHashMap<Class<?>,Map<Class<?>,Mutater<?,?>>> CACHE = new ConcurrentHashMap<>();
+
+ /**
+ * Represents a non-existent transform.
+ */
+ public static final Mutater<Object,Object> NULL = new Mutater<Object,Object>() {
+ @Override
+ public Object mutate(Object outer, Object in) {
+ return null;
+ }
+ };
+
+ // Special cases.
+ static {
+
+ // TimeZone doesn't follow any standard conventions.
+ add(String.class, TimeZone.class,
+ new Mutater<String,TimeZone>() {
+ @Override public TimeZone mutate(Object outer, String in) {
+ return TimeZone.getTimeZone(in);
+ }
+ }
+ );
+ add(TimeZone.class, String.class,
+ new Mutater<TimeZone,String>() {
+ @Override public String mutate(Object outer, TimeZone in) {
+ return in.getID();
+ }
+ }
+ );
+
+ // Locale(String) doesn't work on strings like "ja_JP".
+ add(String.class, Locale.class,
+ new Mutater<String,Locale>() {
+ @Override
+ public Locale mutate(Object outer, String in) {
+ return Locale.forLanguageTag(in.replace('_', '-'));
+ }
+ }
+ );
+
+ // String-to-Boolean transform should allow for "null" keyword.
+ add(String.class, Boolean.class,
+ new Mutater<String,Boolean>() {
+ @Override
+ public Boolean mutate(Object outer, String in) {
+ if (in == null || "null".equals(in) || in.isEmpty())
+ return null;
+ return Boolean.valueOf(in);
+ }
+ }
+ );
+ }
+
+ /**
+ * Adds a transform for the specified input/output types.
+ *
+ * @param ic The input type.
+ * @param oc The output type.
+ * @param t The transform for converting the input to the output.
+ */
+ public static synchronized void add(Class<?> ic, Class<?> oc, Mutater<?,?> t) {
+ Map<Class<?>,Mutater<?,?>> m = CACHE.get(oc);
+ if (m == null) {
+ m = new ConcurrentHashMap<>();
+ CACHE.put(oc, m);
+ }
+ m.put(ic, t);
+ }
+
+ /**
+ * Returns the transform for converting the specified input type to the specified output type.
+ *
+ * @param ic The input type.
+ * @param oc The output type.
+ * @return The transform for performing the conversion, or <jk>null</jk> if the conversion cannot be made.
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <I,O> Mutater<I,O> get(Class<I> ic, Class<O> oc) {
+
+ if (ic == null || oc == null)
+ return null;
+
+ Map<Class<?>,Mutater<?,?>> m = CACHE.get(oc);
+ if (m == null) {
+ m = new ConcurrentHashMap<>();
+ CACHE.putIfAbsent(oc, m);
+ m = CACHE.get(oc);
+ }
+
+ Mutater t = m.get(ic);
+
+ if (t == null) {
+ t = find(ic, oc, m);
+ m.put(ic, t);
+ }
+
+ return t == NULL ? null : t;
+ }
+
+ /**
+ * Returns the transform for converting the specified input type to the specified output type.
+ *
+ * @param ic The input type.
+ * @param oc The output type.
+ * @return The transform for performing the conversion, or <jk>null</jk> if the conversion cannot be made.
+ */
+ public static <I,O> boolean hasMutate(Class<I> ic, Class<O> oc) {
+ return get(ic, oc) != NULL;
+ }
+
+ @SuppressWarnings({"unchecked","rawtypes"})
+ private static Mutater find(Class<?> ic, Class<?> oc, Map<Class<?>,Mutater<?,?>> m) {
+
+ if (ic == oc) {
+ return new Mutater() {
+ @Override public Object mutate(Object outer, Object in) {
+ return in;
+ }
+ };
+ }
+
+ ClassInfo ici = getClassInfo(ic), oci = getClassInfo(oc);
+
+ for (ClassInfo pic : ici.getAllParents()) {
+ Mutater t = m.get(pic.inner());
+ if (t != null)
+ return t;
+ }
+
+ if (ic == String.class) {
+ Class<?> oc2 = oci.hasPrimitiveWrapper() ? oci.getPrimitiveWrapper() : oc;
+ ClassInfo oc2i = getClassInfo(oc2);
+
+ final MethodInfo createMethod = oc2i.getStaticCreateMethod(ic, "forName");
+
+ if (oc2.isEnum() && createMethod == null) {
+ return new Mutater<String,Object>() {
+ @Override
+ public Object mutate(Object outer, String in) {
+ return Enum.valueOf((Class<? extends Enum>)oc2, in);
+ }
+ };
+ }
+
+ if (createMethod != null) {
+ return new Mutater<String,Object>() {
+ @Override
+ public Object mutate(Object outer, String in) {
+ try {
+ return createMethod.invoke(null, in);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ } else {
+ MethodInfo createMethod = oci.getStaticCreateMethod(ic);
+ if (createMethod != null) {
+ Method cm = createMethod.inner();
+ return new Mutater() {
+ @Override
+ public Object mutate(Object context, Object in) {
+ try {
+ return cm.invoke(null, in);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ }
+
+ ConstructorInfo c = oci.getPublicConstructor(ic);
+ if (c != null && c.isNotDeprecated()) {
+ boolean isMemberClass = oci.isNonStaticMemberClass();
+ return new Mutater() {
+ @Override
+ public Object mutate(Object outer, Object in) {
+ try {
+ if (isMemberClass)
+ return c.invoke(outer, in);
+ return c.invoke(in);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ MethodInfo toXMethod = findToXMethod(ici, oci);
+ if (toXMethod != null) {
+ return new Mutater() {
+ @Override
+ public Object mutate(Object outer, Object in) {
+ try {
+ return toXMethod.invoke(in);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ return NULL;
+ }
+
+ private static MethodInfo findToXMethod(ClassInfo ic, ClassInfo oc) {
+ String tn = oc.getReadableName();
+ for (MethodInfo m : ic.getAllMethods()) {
+ if (m.isAll(PUBLIC, NOT_STATIC, HAS_NO_PARAMS, NOT_DEPRECATED)
+ && m.getSimpleName().startsWith("to")
+ && m.getSimpleName().substring(2).equalsIgnoreCase(tn))
+ return m;
+ }
+ return null;
+ }
+
+}
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
index b01fe49..ea9f2f5 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
@@ -2275,8 +2275,8 @@
MediaType mt = MediaType.forString(ct);
if (parser == null || (mt.toString().equals("text/plain") && ! parser.canHandle(ct))) {
- if (type.hasStringTransform())
- return type.getStringTransform().transform(getResponseAsString());
+ if (type.hasStringMutater())
+ return type.getStringMutater().mutate(getResponseAsString());
}
if (parser != null) {
@@ -2307,11 +2307,11 @@
}
}
- if (type.hasReaderTransform())
- return type.getReaderTransform().transform(getReader());
+ if (type.hasReaderMutater())
+ return type.getReaderMutater().mutate(getReader());
- if (type.hasInputStreamTransform())
- return type.getInputStreamTransform().transform(getInputStream());
+ if (type.hasInputStreamMutater())
+ return type.getInputStreamMutater().mutate(getInputStream());
throw new ParseException(
"Unsupported media-type in request header ''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
index fd9f146..7dd7a0b 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
@@ -202,14 +202,14 @@
@Response(schema=@Schema(format="byte"))
public static class D06 {
- public byte[] toBytes() {
+ public byte[] toByteArray() {
return "foo".getBytes();
}
}
@Response(schema=@Schema(format="byte"))
public static class D07 extends Exception {
- public byte[] toBytes() {
+ public byte[] toByteArray() {
return "foo".getBytes();
}
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
index 2d2d61e..fe38358 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -453,16 +453,16 @@
}
}
- if (cm.hasReaderTransform())
- return cm.getReaderTransform().transform(getReader());
+ if (cm.hasReaderMutater())
+ return cm.getReaderMutater().mutate(getReader());
- if (cm.hasInputStreamTransform())
- return cm.getInputStreamTransform().transform(getInputStream());
+ if (cm.hasInputStreamMutater())
+ return cm.getInputStreamMutater().mutate(getInputStream());
MediaType mt = getMediaType();
- if ((isEmpty(mt) || mt.toString().startsWith("text/plain")) && cm.hasStringTransform())
- return cm.getStringTransform().transform(asString());
+ if ((isEmpty(mt) || mt.toString().startsWith("text/plain")) && cm.hasStringMutater())
+ return cm.getStringMutater().mutate(asString());
throw new UnsupportedMediaType(
"Unsupported media-type in request header ''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index 19e41e5..5d2542a 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -785,8 +785,8 @@
example = jp.parse(sex, type);
} else {
ClassMeta<?> cm = js.getClassMeta(type);
- if (cm.hasStringTransform()) {
- example = cm.getStringTransform().transform(sex);
+ if (cm.hasStringMutater()) {
+ example = cm.getStringMutater().mutate(sex);
}
}