You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/02/04 22:53:23 UTC
[1/5] incubator-juneau git commit: Improvements to
ClassMeta/BeanContext.
Repository: incubator-juneau
Updated Branches:
refs/heads/master c8fa4ed45 -> 4bc66a6a9
Improvements to ClassMeta/BeanContext.
Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/61894c85
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/61894c85
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/61894c85
Branch: refs/heads/master
Commit: 61894c857be9a9d0b87a08ac1ce1b1cf9e939184
Parents: bdeb4f0
Author: JamesBognar <ja...@apache.org>
Authored: Sat Feb 4 15:44:34 2017 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Sat Feb 4 17:34:35 2017 -0500
----------------------------------------------------------------------
.../java/org/apache/juneau/BeanContext.java | 62 +++--
.../org/apache/juneau/BeanPropertyMeta.java | 8 +-
.../main/java/org/apache/juneau/ClassMeta.java | 257 +++++++++++++------
.../org/apache/juneau/transform/PojoSwap.java | 6 +
4 files changed, 230 insertions(+), 103 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/61894c85/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
index 7690729..1cb9180 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -1155,8 +1155,8 @@ public class BeanContext extends Context {
if (! cmCacheCache.containsKey(hashCode)) {
ConcurrentHashMap<Class,ClassMeta> cm = new ConcurrentHashMap<Class,ClassMeta>();
- cm.put(String.class, new ClassMeta(String.class, this));
- cm.put(Object.class, new ClassMeta(Object.class, this));
+ cm.put(String.class, new ClassMeta(String.class, this, null, null, findPojoSwap(String.class), findChildPojoSwaps(String.class)));
+ cm.put(Object.class, new ClassMeta(Object.class, this, null, null, findPojoSwap(Object.class), findChildPojoSwaps(Object.class)));
cmCacheCache.putIfAbsent(hashCode, cm);
}
this.cmCache = cmCacheCache.get(hashCode);
@@ -1346,10 +1346,11 @@ public class BeanContext extends Context {
if (oc instanceof Class) {
Class c = (Class)oc;
if (Collection.class.isAssignableFrom(c)) {
+ ClassMeta<?> rawType = getClassMeta(c);
ClassMeta<?> ce = getClassMeta(Array.get(o, 1));
if (ce.isObject())
- return getClassMeta(c);
- return new ClassMeta(c, this).setElementType(ce);
+ return (ClassMeta<T>)rawType;
+ return new ClassMeta(rawType, null, null, ce);
}
}
} else if (len == 3) {
@@ -1357,11 +1358,12 @@ public class BeanContext extends Context {
if (oc instanceof Class) {
Class c = (Class)oc;
if (Map.class.isAssignableFrom(c)) {
+ ClassMeta<?> rawType = getClassMeta(c);
ClassMeta<?> ck = getClassMeta(Array.get(o, 1));
ClassMeta<?> cv = getClassMeta(Array.get(o, 2));
if (ck.isObject() && cv.isObject())
- return getClassMeta(c);
- return new ClassMeta(c, this).setKeyType(ck).setValueType(cv);
+ return (ClassMeta<T>)rawType;
+ return new ClassMeta(rawType, ck, cv, null);
}
}
}
@@ -1383,7 +1385,7 @@ public class BeanContext extends Context {
// Note that if it has a pojo swap, we still want to cache it so that
// we can cache something like byte[] with ByteArrayBase64Swap.
if (c.isArray() && findPojoSwap(c) == null)
- return new ClassMeta(c, this);
+ return new ClassMeta(c, this, findImplClass(c), findBeanFilter(c), findPojoSwap(c), findChildPojoSwaps(c));
// This can happen if we have transforms defined against String or Object.
if (cmCache == null)
@@ -1405,7 +1407,7 @@ public class BeanContext extends Context {
if (pcm.innerClass == c)
return pcm;
- cm = new ClassMeta<T>(c, this, true);
+ cm = new ClassMeta<T>(c, this, findImplClass(c), findBeanFilter(c), findPojoSwap(c), findChildPojoSwaps(c), true);
pendingClassMetas.addLast(cm);
try {
cm.init();
@@ -1601,7 +1603,7 @@ public class BeanContext extends Context {
ClassMeta<?> valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType());
if (keyType.isObject() && valueType.isObject())
return cm2;
- return new ClassMeta<T>(cm2.innerClass, this).setKeyType(keyType).setValueType(valueType);
+ return new ClassMeta<T>(cm2, keyType, valueType, null);
}
if (cm2.isCollection()) {
@@ -1611,7 +1613,7 @@ public class BeanContext extends Context {
ClassMeta<?> elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType());
if (elementType.isObject())
return cm2;
- return new ClassMeta<T>(cm2.innerClass, this).setElementType(elementType);
+ return new ClassMeta<T>(cm2, null, null, elementType);
}
return cm2;
@@ -1749,7 +1751,7 @@ public class BeanContext extends Context {
* @param c The class associated with the swap.
* @return The swap associated with the class, or null if there is no association.
*/
- protected final <T> PojoSwap findPojoSwap(Class<T> c) {
+ private final <T> PojoSwap findPojoSwap(Class<T> c) {
// Note: On first
if (c != null)
for (PojoSwap f : pojoSwaps)
@@ -1763,12 +1765,18 @@ public class BeanContext extends Context {
* @param c The class to check.
* @return <jk>true</jk> if the specified class or one of its subclasses has a {@link PojoSwap} associated with it.
*/
- protected final boolean hasChildPojoSwaps(Class<?> c) {
- if (c != null)
- for (PojoSwap f : pojoSwaps)
- if (isParentClass(c, f.getNormalClass()))
- return true;
- return false;
+ private final PojoSwap[] findChildPojoSwaps(Class<?> c) {
+ if (c == null || pojoSwaps.length == 0)
+ return null;
+ List<PojoSwap> l = null;
+ for (PojoSwap f : pojoSwaps) {
+ if (isParentClass(c, f.getNormalClass())) {
+ if (l == null)
+ l = new ArrayList<PojoSwap>();
+ l.add(f);
+ }
+ }
+ return l == null ? null : l.toArray(new PojoSwap[l.size()]);
}
/**
@@ -1779,7 +1787,7 @@ public class BeanContext extends Context {
* @param c The class associated with the bean filter.
* @return The bean filter associated with the class, or null if there is no association.
*/
- protected final <T> BeanFilter findBeanFilter(Class<T> c) {
+ private final <T> BeanFilter findBeanFilter(Class<T> c) {
if (c != null)
for (BeanFilter f : beanFilters)
if (isParentClass(f.getBeanClass(), c))
@@ -1831,6 +1839,24 @@ public class BeanContext extends Context {
return null;
}
+ private final <T> Class<? extends T> findImplClass(Class<T> c) {
+ if (implClasses.isEmpty())
+ return null;
+ Class cc = c;
+ while (cc != null) {
+ Class implClass = implClasses.get(cc);
+ if (implClass != null)
+ return implClass;
+ for (Class ic : cc.getInterfaces()) {
+ implClass = implClasses.get(ic);
+ if (implClass != null)
+ return implClass;
+ }
+ cc = cc.getSuperclass();
+ }
+ return null;
+ }
+
/**
* Returns a reusable {@link ClassMeta} representation for the class <code>Object</code>.
* <p>
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/61894c85/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index ce7fdb5..a9e52f0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -848,9 +848,7 @@ public class BeanPropertyMeta {
return null;
// Otherwise, look it up via bean context.
if (rawTypeMeta.hasChildPojoSwaps()) {
- Class c = o.getClass();
- ClassMeta<?> cm = rawTypeMeta.innerClass == c ? rawTypeMeta : beanContext.getClassMeta(c);
- PojoSwap f = cm.getPojoSwap();
+ PojoSwap f = rawTypeMeta.getChildPojoSwapForSwap(o.getClass());
if (f != null)
return f.swap(session, o);
}
@@ -863,9 +861,7 @@ public class BeanPropertyMeta {
if (o == null)
return null;
if (rawTypeMeta.hasChildPojoSwaps()) {
- Class c = o.getClass();
- ClassMeta<?> cm = rawTypeMeta.innerClass == c ? rawTypeMeta : beanContext.getClassMeta(c);
- PojoSwap f = cm.getPojoSwap();
+ PojoSwap f = rawTypeMeta.getChildPojoSwapForUnswap(o.getClass());
if (f != null)
return f.unswap(session, o, rawTypeMeta);
}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/61894c85/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index c36ffd8..f103b2a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -21,6 +21,7 @@ import java.lang.reflect.Proxy;
import java.net.*;
import java.net.URI;
import java.util.*;
+import java.util.concurrent.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;
@@ -57,9 +58,10 @@ public final class ClassMeta<T> implements Type {
}
final Class<T> innerClass; // The class being wrapped.
+ final Class<? extends T> implClass; // The implementation class to use if this is an interface.
final ClassCategory cc; // The class category.
final Method fromStringMethod; // The static valueOf(String) or fromString(String) or forString(String) method (if it has one).
- Constructor<? extends T>
+ final Constructor<? extends T>
noArgConstructor; // The no-arg constructor for this class (if it has one).
final Constructor<T>
stringConstructor, // The X(String) constructor (if it has one).
@@ -82,7 +84,10 @@ public final class ClassMeta<T> implements Type {
final Map<String,Method>
remoteableMethods, // Methods annotated with @Remoteable. Contains all public methods if class is annotated with @Remotable.
publicMethods; // All public methods, including static methods.
-
+ final PojoSwap<?,?>[] childPojoSwaps; // Any PojoSwaps where the normal type is a subclass of this class.
+ final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
+ childSwapMap, // Maps normal subclasses to PojoSwaps.
+ childUnswapMap; // Maps swap subclasses to PojoSwaps.
final BeanContext beanContext; // The bean context that created this object.
ClassMeta<?>
@@ -99,7 +104,6 @@ public final class ClassMeta<T> implements Type {
private MetadataMap extMeta = new MetadataMap(); // Extended metadata
private Throwable initException; // Any exceptions thrown in the init() method.
- private boolean hasChildPojoSwaps; // True if this class or any subclass of this class has a PojoSwap associated with it.
private static final Boolean BOOLEAN_DEFAULT = false;
private static final Character CHARACTER_DEFAULT = (char)0;
@@ -113,8 +117,8 @@ public final class ClassMeta<T> implements Type {
/**
* Shortcut for calling <code>ClassMeta(innerClass, beanContext, <jk>false</jk>)</code>.
*/
- ClassMeta(Class<T> innerClass, BeanContext beanContext) {
- this(innerClass, beanContext, false);
+ ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?> pojoSwap, PojoSwap<?,?>[] childPojoSwaps) {
+ this(innerClass, beanContext, implClass, beanFilter, pojoSwap, childPojoSwaps, false);
}
/**
@@ -122,13 +126,26 @@ public final class ClassMeta<T> implements Type {
*
* @param innerClass The class being wrapped.
* @param beanContext The bean context that created this object.
+ * @param implClass For interfaces and abstract classes, this represents the "real" class to instantiate.
+ * Can be <jk>null</jk>.
+ * @param beanFilter The {@link BeanFilter} programmatically associated with this class.
+ * Can be <jk>null</jk>.
+ * @param pojoSwap The {@link PojoSwap} programmatically associated with this class.
+ * Can be <jk>null</jk>.
+ * @param childPojoSwap The child {@link PojoSwap PojoSwaps} programmatically associated with this class.
+ * These are the <code>PojoSwaps</code> that have normal classes that are subclasses of this class.
+ * Can be <jk>null</jk>.
* @param delayedInit Don't call init() in constructor.
* Used for delayed initialization when the possibility of class reference loops exist.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- ClassMeta(Class<T> innerClass, BeanContext beanContext, boolean delayedInit) {
+ ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?> pojoSwap, PojoSwap<?,?>[] childPojoSwaps, boolean delayedInit) {
this.innerClass = innerClass;
this.beanContext = beanContext;
+ this.implClass = implClass;
+ this.childPojoSwaps = childPojoSwaps;
+ this.childSwapMap = childPojoSwaps == null ? null : new ConcurrentHashMap<Class<?>,PojoSwap<?,?>>();
+ this.childUnswapMap = childPojoSwaps == null ? null : new ConcurrentHashMap<Class<?>,PojoSwap<?,?>>();
Class<T> c = innerClass;
ClassCategory _cc = ClassCategory.OTHER;
@@ -351,6 +368,41 @@ public final class ClassMeta<T> implements Type {
}
}
+ if (innerClass != Object.class) {
+ _noArgConstructor = (Constructor<T>)findNoArgConstructor(implClass == null ? innerClass : implClass, Visibility.PUBLIC);
+ }
+
+ if (beanFilter == null)
+ beanFilter = findBeanFilter();
+
+ PojoSwap ps = null;
+ if (_swapMethod != null) {
+ ps = new PojoSwap<T,Object>(c, _swapMethod.getReturnType()) {
+ @Override
+ public Object swap(BeanSession session, Object o) throws SerializeException {
+ try {
+ return swapMethod.invoke(o, session);
+ } catch (Exception e) {
+ throw new SerializeException(e);
+ }
+ }
+ @Override
+ public T unswap(BeanSession session, Object f, ClassMeta<?> hint) throws ParseException {
+ try {
+ if (swapConstructor != null)
+ return swapConstructor.newInstance(f);
+ return super.unswap(session, f, hint);
+ } catch (Exception e) {
+ throw new ParseException(e);
+ }
+ }
+ };
+ }
+ if (ps == null)
+ ps = findPojoSwap();
+ if (ps == null)
+ ps = pojoSwap;
+
this.cc = _cc;
this.isDelegate = _isDelegate;
this.fromStringMethod = _fromStringMethod;
@@ -368,6 +420,8 @@ public final class ClassMeta<T> implements Type {
this.primitiveDefault = _primitiveDefault;
this.publicMethods = _publicMethods;
this.remoteableMethods = _remoteableMethods;
+ this.beanFilter = beanFilter;
+ this.pojoSwap = ps;
if (! delayedInit)
init();
@@ -379,6 +433,10 @@ public final class ClassMeta<T> implements Type {
*/
ClassMeta(ClassMeta<T> mainType, ClassMeta<?> keyType, ClassMeta<?> valueType, ClassMeta<?> elementType) {
this.innerClass = mainType.innerClass;
+ this.implClass = mainType.implClass;
+ this.childPojoSwaps = mainType.childPojoSwaps;
+ this.childSwapMap = mainType.childSwapMap;
+ this.childUnswapMap = mainType.childUnswapMap;
this.cc = mainType.cc;
this.fromStringMethod = mainType.fromStringMethod;
this.noArgConstructor = mainType.noArgConstructor;
@@ -412,76 +470,40 @@ public final class ClassMeta<T> implements Type {
this.beanFilter = mainType.beanFilter;
this.extMeta = mainType.extMeta;
this.initException = mainType.initException;
- this.hasChildPojoSwaps = mainType.hasChildPojoSwaps;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
ClassMeta init() {
try {
- beanFilter = findBeanFilter(beanContext);
- pojoSwap = findPojoSwap(beanContext);
-
- if (innerClass != Object.class) {
- this.noArgConstructor = beanContext.getImplClassConstructor(innerClass, Visibility.PUBLIC);
- if (noArgConstructor == null)
- noArgConstructor = findNoArgConstructor(innerClass, Visibility.PUBLIC);
- }
-
- this.hasChildPojoSwaps = beanContext.hasChildPojoSwaps(innerClass);
-
- Class c = innerClass;
-
- if (swapMethod != null) {
- this.pojoSwap = new PojoSwap<T,Object>(c, swapMethod.getReturnType()) {
- @Override
- public Object swap(BeanSession session, Object o) throws SerializeException {
- try {
- return swapMethod.invoke(o, session);
- } catch (Exception e) {
- throw new SerializeException(e);
- }
- }
- @Override
- public T unswap(BeanSession session, Object f, ClassMeta<?> hint) throws ParseException {
- try {
- if (swapConstructor != null)
- return swapConstructor.newInstance(f);
- return super.unswap(session, f, hint);
- } catch (Exception e) {
- throw new ParseException(e);
- }
- }
- };
- }
- serializedClassMeta = (pojoSwap == null ? this : beanContext.getClassMeta(pojoSwap.getSwapClass()));
+ serializedClassMeta = (pojoSwap == null ? this : findClassMeta(pojoSwap.getSwapClass()));
if (serializedClassMeta == null)
serializedClassMeta = this;
// If this is an array, get the element type.
if (cc == ARRAY)
- elementType = beanContext.getClassMeta(innerClass.getComponentType());
+ elementType = findClassMeta(innerClass.getComponentType());
// If this is a MAP, see if it's parameterized (e.g. AddressBook extends HashMap<String,Person>)
else if (cc == MAP) {
- ClassMeta[] parameters = beanContext.findParameters(innerClass, innerClass);
+ ClassMeta[] parameters = findParameters();
if (parameters != null && parameters.length == 2) {
keyType = parameters[0];
valueType = parameters[1];
} else {
- keyType = beanContext.getClassMeta(Object.class);
- valueType = beanContext.getClassMeta(Object.class);
+ keyType = findClassMeta(Object.class);
+ valueType = findClassMeta(Object.class);
}
}
// If this is a COLLECTION, see if it's parameterized (e.g. AddressBook extends LinkedList<Person>)
else if (cc == COLLECTION) {
- ClassMeta[] parameters = beanContext.findParameters(innerClass, innerClass);
+ ClassMeta[] parameters = findParameters();
if (parameters != null && parameters.length == 1) {
elementType = parameters[0];
} else {
- elementType = beanContext.getClassMeta(Object.class);
+ elementType = findClassMeta(Object.class);
}
}
@@ -520,6 +542,43 @@ public final class ClassMeta<T> implements Type {
return this;
}
+ private ClassMeta<?> findClassMeta(Class<?> c) {
+ return beanContext.getClassMeta(c);
+ }
+
+ private ClassMeta<?>[] findParameters() {
+ return beanContext.findParameters(innerClass, innerClass);
+ }
+
+ private BeanFilter findBeanFilter() {
+ try {
+ List<Bean> ba = ReflectionUtils.findAnnotations(Bean.class, innerClass);
+ if (! ba.isEmpty())
+ return new AnnotationBeanFilterBuilder(innerClass, ba).build();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private PojoSwap<T,?> findPojoSwap() {
+ try {
+ Pojo p = innerClass.getAnnotation(Pojo.class);
+ if (p != null) {
+ Class<?> c = p.swap();
+ if (c != Null.class) {
+ if (ClassUtils.isParentClass(PojoSwap.class, c))
+ return (PojoSwap<T,?>)c.newInstance();
+ throw new RuntimeException("TODO - Surrogate classes not yet supported.");
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/**
* Returns the bean dictionary name associated with this class.
* <p>
@@ -589,45 +648,58 @@ public final class ClassMeta<T> implements Type {
*
* @return <jk>true</jk> if this class or any child classes has a {@link PojoSwap} associated with it.
*/
- public boolean hasChildPojoSwaps() {
- return hasChildPojoSwaps;
+ protected boolean hasChildPojoSwaps() {
+ return childPojoSwaps != null;
}
- private BeanFilter findBeanFilter(BeanContext context) {
- try {
- if (context == null)
+ /**
+ * Returns the {@link PojoSwap} where the specified class is the same/subclass of the normal class of
+ * one of the child pojo swaps associated with this class.
+ *
+ * @param normalClass The normal class being resolved.
+ * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found.
+ */
+ protected PojoSwap<?,?> getChildPojoSwapForSwap(Class<?> normalClass) {
+ if (childSwapMap != null) {
+ PojoSwap<?,?> s = childSwapMap.get(normalClass);
+ if (s == null) {
+ for (PojoSwap<?,?> f : childPojoSwaps)
+ if (s == null && isParentClass(f.getNormalClass(), normalClass))
+ s = f;
+ if (s == null)
+ s = PojoSwap.NULL;
+ childSwapMap.putIfAbsent(normalClass, s);
+ }
+ if (s == PojoSwap.NULL)
return null;
- BeanFilter f = context.findBeanFilter(innerClass);
- if (f != null)
- return f;
- List<Bean> ba = ReflectionUtils.findAnnotations(Bean.class, innerClass);
- if (! ba.isEmpty())
- f = new AnnotationBeanFilterBuilder(innerClass, ba).build();
- return f;
- } catch (Exception e) {
- throw new RuntimeException(e);
+ return s;
}
+ return null;
}
- @SuppressWarnings("unchecked")
- private PojoSwap<T,?> findPojoSwap(BeanContext context) {
- try {
- Pojo p = innerClass.getAnnotation(Pojo.class);
- if (p != null) {
- Class<?> c = p.swap();
- if (c != Null.class) {
- if (ClassUtils.isParentClass(PojoSwap.class, c))
- return (PojoSwap<T,?>)c.newInstance();
- throw new RuntimeException("TODO - Surrogate classes not yet supported.");
- }
+ /**
+ * Returns the {@link PojoSwap} where the specified class is the same/subclass of the swap class of
+ * one of the child pojo swaps associated with this class.
+ *
+ * @param swapClass The swap class being resolved.
+ * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found.
+ */
+ protected PojoSwap<?,?> getChildPojoSwapForUnswap(Class<?> swapClass) {
+ if (childUnswapMap != null) {
+ PojoSwap<?,?> s = childUnswapMap.get(swapClass);
+ if (s == null) {
+ for (PojoSwap<?,?> f : childPojoSwaps)
+ if (s == null && isParentClass(f.getSwapClass(), swapClass))
+ s = f;
+ if (s == null)
+ s = PojoSwap.NULL;
+ childUnswapMap.putIfAbsent(swapClass, s);
}
- if (context == null)
+ if (s == PojoSwap.NULL)
return null;
- PojoSwap<T,?> f = context.findPojoSwap(innerClass);
- return f;
- } catch (Exception e) {
- throw new RuntimeException(e);
+ return s;
}
+ return null;
}
/**
@@ -1504,4 +1576,31 @@ public final class ClassMeta<T> implements Type {
public int hashCode() {
return super.hashCode();
}
+//
+// public abstract static class CreateSession {
+// LinkedList<ClassMeta<?>> stack;
+//
+// public CreateSession push(ClassMeta<?> cm) {
+// if (stack == null)
+// stack = new LinkedList<ClassMeta<?>>();
+// stack.add(cm);
+// return this;
+// }
+//
+// public CreateSession pop(ClassMeta<?> expected) {
+// if (stack == null || stack.removeLast() != expected)
+// throw new BeanRuntimeException("ClassMetaSession creation stack corruption!");
+// return this;
+// }
+//
+// public <T> ClassMeta<T> getClassMeta(Class<T> c) {
+// if (stack != null)
+// for (ClassMeta<?> cm : stack)
+// if (cm.innerClass == c)
+// return (ClassMeta<T>)cm;
+// return createClassMeta(c);
+// }
+//
+// public abstract <T> ClassMeta<T> createClassMeta(Class<T> c);
+// }
}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/61894c85/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
index ec97dd8..5a1d104 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
@@ -98,6 +98,12 @@ import org.apache.juneau.serializer.*;
*/
public abstract class PojoSwap<T,S> {
+ /**
+ * Represents a non-existent pojo swap.
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public final static PojoSwap NULL = new PojoSwap(null, null) {};
+
private final Class<T> normalClass;
private final Class<?> swapClass;
private ClassMeta<?> swapClassMeta;
[3/5] incubator-juneau git commit: Improvements to ClassMeta class.
Posted by ja...@apache.org.
Improvements to ClassMeta class.
Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/96cf56b4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/96cf56b4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/96cf56b4
Branch: refs/heads/master
Commit: 96cf56b4aa448d34b86aa96631d65886db241b2a
Parents: 062d7dd
Author: JamesBognar <ja...@apache.org>
Authored: Sat Feb 4 17:49:42 2017 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Sat Feb 4 17:49:42 2017 -0500
----------------------------------------------------------------------
.../main/java/org/apache/juneau/ClassMeta.java | 35 ++++----------------
1 file changed, 6 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/96cf56b4/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index 5e079c4..586d0b5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -88,6 +88,11 @@ public final class ClassMeta<T> implements Type {
final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
childSwapMap, // Maps normal subclasses to PojoSwaps.
childUnswapMap; // Maps swap subclasses to PojoSwaps.
+ final PojoSwap<T,?> pojoSwap; // The object POJO swap associated with this bean (if it has one).
+ final BeanFilter beanFilter; // The bean filter associated with this bean (if it has one).
+
+ private final MetadataMap extMeta; // Extended metadata
+
final BeanContext beanContext; // The bean context that created this object.
ClassMeta<?>
@@ -99,10 +104,6 @@ public final class ClassMeta<T> implements Type {
BeanMeta<T> beanMeta; // The bean meta for this bean class (if it's a bean).
String dictionaryName, resolvedDictionaryName; // The dictionary name of this class if it has one.
String notABeanReason; // If this isn't a bean, the reason why.
- PojoSwap<T,?> pojoSwap; // The object POJO swap associated with this bean (if it has one).
- BeanFilter beanFilter; // The bean filter associated with this bean (if it has one).
-
- private MetadataMap extMeta = new MetadataMap(); // Extended metadata
private Throwable initException; // Any exceptions thrown in the init() method.
private static final Boolean BOOLEAN_DEFAULT = false;
@@ -422,6 +423,7 @@ public final class ClassMeta<T> implements Type {
this.remoteableMethods = _remoteableMethods;
this.beanFilter = beanFilter;
this.pojoSwap = ps;
+ this.extMeta = new MetadataMap();
if (! delayedInit)
init();
@@ -477,31 +479,6 @@ public final class ClassMeta<T> implements Type {
try {
- Class c = innerClass;
-
- if (swapMethod != null) {
- this.pojoSwap = new PojoSwap<T,Object>(c, swapMethod.getReturnType()) {
- @Override
- public Object swap(BeanSession session, Object o) throws SerializeException {
- try {
- return swapMethod.invoke(o, session);
- } catch (Exception e) {
- throw new SerializeException(e);
- }
- }
- @Override
- public T unswap(BeanSession session, Object f, ClassMeta<?> hint) throws ParseException {
- try {
- if (swapConstructor != null)
- return swapConstructor.newInstance(f);
- return super.unswap(session, f, hint);
- } catch (Exception e) {
- throw new ParseException(e);
- }
- }
- };
- }
-
serializedClassMeta = (pojoSwap == null ? this : findClassMeta(pojoSwap.getSwapClass()));
if (serializedClassMeta == null)
serializedClassMeta = this;
[5/5] incubator-juneau git commit: Fix merge issue.
Posted by ja...@apache.org.
Fix merge issue.
Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/4bc66a6a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/4bc66a6a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/4bc66a6a
Branch: refs/heads/master
Commit: 4bc66a6a9ec549fc00ff2581d7ff68dfa9997adc
Parents: 23dc784
Author: JamesBognar <ja...@apache.org>
Authored: Sat Feb 4 17:52:58 2017 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Sat Feb 4 17:52:58 2017 -0500
----------------------------------------------------------------------
.../src/main/java/org/apache/juneau/ClassMeta.java | 10 ----------
1 file changed, 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4bc66a6a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index 47e3ca5..90cdd49 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -85,7 +85,6 @@ public final class ClassMeta<T> implements Type {
remoteableMethods, // Methods annotated with @Remoteable. Contains all public methods if class is annotated with @Remotable.
publicMethods; // All public methods, including static methods.
final PojoSwap<?,?>[] childPojoSwaps; // Any PojoSwaps where the normal type is a subclass of this class.
-<<<<<<< HEAD
final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
childSwapMap, // Maps normal subclasses to PojoSwaps.
childUnswapMap; // Maps swap subclasses to PojoSwaps.
@@ -94,12 +93,6 @@ public final class ClassMeta<T> implements Type {
private final MetadataMap extMeta; // Extended metadata
-=======
- final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
- childSwapMap, // Maps normal subclasses to PojoSwaps.
- childUnswapMap; // Maps swap subclasses to PojoSwaps.
->>>>>>> master
-
final BeanContext beanContext; // The bean context that created this object.
ClassMeta<?>
serializedClassMeta, // The transformed class type (if class has swap associated with it).
@@ -429,10 +422,7 @@ public final class ClassMeta<T> implements Type {
this.remoteableMethods = _remoteableMethods;
this.beanFilter = beanFilter;
this.pojoSwap = ps;
-<<<<<<< HEAD
this.extMeta = new MetadataMap();
-=======
->>>>>>> master
if (! delayedInit)
init();
[4/5] incubator-juneau git commit: Merge branch 'master' into HEAD
Posted by ja...@apache.org.
Merge branch 'master' into HEAD
# Conflicts:
# juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/23dc784a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/23dc784a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/23dc784a
Branch: refs/heads/master
Commit: 23dc784adcf80ad00b39332495bbedf2a344f875
Parents: 96cf56b 61894c8
Author: JamesBognar <ja...@apache.org>
Authored: Sat Feb 4 17:51:41 2017 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Sat Feb 4 17:51:41 2017 -0500
----------------------------------------------------------------------
.../main/java/org/apache/juneau/ClassMeta.java | 9 ++++++
.../org/apache/juneau/utils/ObjectUtils.java | 32 ++++++++++++++++++++
2 files changed, 41 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/23dc784a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --cc juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index 586d0b5,f103b2a..47e3ca5
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@@ -85,14 -85,9 +85,20 @@@ public final class ClassMeta<T> impleme
remoteableMethods, // Methods annotated with @Remoteable. Contains all public methods if class is annotated with @Remotable.
publicMethods; // All public methods, including static methods.
final PojoSwap<?,?>[] childPojoSwaps; // Any PojoSwaps where the normal type is a subclass of this class.
++<<<<<<< HEAD
+ final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
+ childSwapMap, // Maps normal subclasses to PojoSwaps.
+ childUnswapMap; // Maps swap subclasses to PojoSwaps.
+ final PojoSwap<T,?> pojoSwap; // The object POJO swap associated with this bean (if it has one).
+ final BeanFilter beanFilter; // The bean filter associated with this bean (if it has one).
+
+ private final MetadataMap extMeta; // Extended metadata
+
++=======
+ final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
+ childSwapMap, // Maps normal subclasses to PojoSwaps.
+ childUnswapMap; // Maps swap subclasses to PojoSwaps.
++>>>>>>> master
final BeanContext beanContext; // The bean context that created this object.
ClassMeta<?>
@@@ -423,7 -422,6 +429,10 @@@
this.remoteableMethods = _remoteableMethods;
this.beanFilter = beanFilter;
this.pojoSwap = ps;
++<<<<<<< HEAD
+ this.extMeta = new MetadataMap();
++=======
++>>>>>>> master
if (! delayedInit)
init();
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/23dc784a/juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java
----------------------------------------------------------------------
diff --cc juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java
index 0000000,0000000..7cd68fe
new file mode 100644
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java
@@@ -1,0 -1,0 +1,32 @@@
++// ***************************************************************************************************************************
++// * 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.utils;
++
++/**
++ * TODO
++ */
++public class ObjectUtils {
++//
++// private static final ConcurrentHashMap<Class<?>,ClassMetaSimple> metaCache = new ConcurrentHashMap<Class<?>,ClassMetaSimple>();
++//
++// public static <T> T convertToType(Class<T> c, Object value, Object outer) {
++// return null;
++//
++// ClassMetaSimple<T> type = metaCache.get(c);
++// if (type == null) {
++// metaCache.putIfAbsent(c, new ClassMetaSimple<T>(c));
++// type = metaCache.get(c);
++// }
++//
++// }
++}
[2/5] incubator-juneau git commit: Improvements to
ClassMeta/BeanContext (2).
Posted by ja...@apache.org.
Improvements to ClassMeta/BeanContext (2).
Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/062d7ddc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/062d7ddc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/062d7ddc
Branch: refs/heads/master
Commit: 062d7ddc65b462128c43b9673c20104dcfd58e80
Parents: c8fa4ed
Author: JamesBognar <ja...@apache.org>
Authored: Sat Feb 4 17:44:09 2017 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Sat Feb 4 17:44:09 2017 -0500
----------------------------------------------------------------------
.../java/org/apache/juneau/BeanContext.java | 48 +++-
.../org/apache/juneau/BeanPropertyMeta.java | 8 +-
.../main/java/org/apache/juneau/ClassMeta.java | 237 +++++++++++++------
.../org/apache/juneau/transform/PojoSwap.java | 6 +
4 files changed, 207 insertions(+), 92 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/062d7ddc/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
index 05006f3..1cb9180 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -1155,8 +1155,8 @@ public class BeanContext extends Context {
if (! cmCacheCache.containsKey(hashCode)) {
ConcurrentHashMap<Class,ClassMeta> cm = new ConcurrentHashMap<Class,ClassMeta>();
- cm.put(String.class, new ClassMeta(String.class, this));
- cm.put(Object.class, new ClassMeta(Object.class, this));
+ cm.put(String.class, new ClassMeta(String.class, this, null, null, findPojoSwap(String.class), findChildPojoSwaps(String.class)));
+ cm.put(Object.class, new ClassMeta(Object.class, this, null, null, findPojoSwap(Object.class), findChildPojoSwaps(Object.class)));
cmCacheCache.putIfAbsent(hashCode, cm);
}
this.cmCache = cmCacheCache.get(hashCode);
@@ -1385,7 +1385,7 @@ public class BeanContext extends Context {
// Note that if it has a pojo swap, we still want to cache it so that
// we can cache something like byte[] with ByteArrayBase64Swap.
if (c.isArray() && findPojoSwap(c) == null)
- return new ClassMeta(c, this);
+ return new ClassMeta(c, this, findImplClass(c), findBeanFilter(c), findPojoSwap(c), findChildPojoSwaps(c));
// This can happen if we have transforms defined against String or Object.
if (cmCache == null)
@@ -1407,7 +1407,7 @@ public class BeanContext extends Context {
if (pcm.innerClass == c)
return pcm;
- cm = new ClassMeta<T>(c, this, true);
+ cm = new ClassMeta<T>(c, this, findImplClass(c), findBeanFilter(c), findPojoSwap(c), findChildPojoSwaps(c), true);
pendingClassMetas.addLast(cm);
try {
cm.init();
@@ -1751,7 +1751,7 @@ public class BeanContext extends Context {
* @param c The class associated with the swap.
* @return The swap associated with the class, or null if there is no association.
*/
- protected final <T> PojoSwap findPojoSwap(Class<T> c) {
+ private final <T> PojoSwap findPojoSwap(Class<T> c) {
// Note: On first
if (c != null)
for (PojoSwap f : pojoSwaps)
@@ -1765,12 +1765,18 @@ public class BeanContext extends Context {
* @param c The class to check.
* @return <jk>true</jk> if the specified class or one of its subclasses has a {@link PojoSwap} associated with it.
*/
- protected final boolean hasChildPojoSwaps(Class<?> c) {
- if (c != null)
- for (PojoSwap f : pojoSwaps)
- if (isParentClass(c, f.getNormalClass()))
- return true;
- return false;
+ private final PojoSwap[] findChildPojoSwaps(Class<?> c) {
+ if (c == null || pojoSwaps.length == 0)
+ return null;
+ List<PojoSwap> l = null;
+ for (PojoSwap f : pojoSwaps) {
+ if (isParentClass(c, f.getNormalClass())) {
+ if (l == null)
+ l = new ArrayList<PojoSwap>();
+ l.add(f);
+ }
+ }
+ return l == null ? null : l.toArray(new PojoSwap[l.size()]);
}
/**
@@ -1781,7 +1787,7 @@ public class BeanContext extends Context {
* @param c The class associated with the bean filter.
* @return The bean filter associated with the class, or null if there is no association.
*/
- protected final <T> BeanFilter findBeanFilter(Class<T> c) {
+ private final <T> BeanFilter findBeanFilter(Class<T> c) {
if (c != null)
for (BeanFilter f : beanFilters)
if (isParentClass(f.getBeanClass(), c))
@@ -1833,6 +1839,24 @@ public class BeanContext extends Context {
return null;
}
+ private final <T> Class<? extends T> findImplClass(Class<T> c) {
+ if (implClasses.isEmpty())
+ return null;
+ Class cc = c;
+ while (cc != null) {
+ Class implClass = implClasses.get(cc);
+ if (implClass != null)
+ return implClass;
+ for (Class ic : cc.getInterfaces()) {
+ implClass = implClasses.get(ic);
+ if (implClass != null)
+ return implClass;
+ }
+ cc = cc.getSuperclass();
+ }
+ return null;
+ }
+
/**
* Returns a reusable {@link ClassMeta} representation for the class <code>Object</code>.
* <p>
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/062d7ddc/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index ce7fdb5..a9e52f0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -848,9 +848,7 @@ public class BeanPropertyMeta {
return null;
// Otherwise, look it up via bean context.
if (rawTypeMeta.hasChildPojoSwaps()) {
- Class c = o.getClass();
- ClassMeta<?> cm = rawTypeMeta.innerClass == c ? rawTypeMeta : beanContext.getClassMeta(c);
- PojoSwap f = cm.getPojoSwap();
+ PojoSwap f = rawTypeMeta.getChildPojoSwapForSwap(o.getClass());
if (f != null)
return f.swap(session, o);
}
@@ -863,9 +861,7 @@ public class BeanPropertyMeta {
if (o == null)
return null;
if (rawTypeMeta.hasChildPojoSwaps()) {
- Class c = o.getClass();
- ClassMeta<?> cm = rawTypeMeta.innerClass == c ? rawTypeMeta : beanContext.getClassMeta(c);
- PojoSwap f = cm.getPojoSwap();
+ PojoSwap f = rawTypeMeta.getChildPojoSwapForUnswap(o.getClass());
if (f != null)
return f.unswap(session, o, rawTypeMeta);
}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/062d7ddc/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index e98f595..5e079c4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -21,6 +21,7 @@ import java.lang.reflect.Proxy;
import java.net.*;
import java.net.URI;
import java.util.*;
+import java.util.concurrent.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;
@@ -57,9 +58,10 @@ public final class ClassMeta<T> implements Type {
}
final Class<T> innerClass; // The class being wrapped.
+ final Class<? extends T> implClass; // The implementation class to use if this is an interface.
final ClassCategory cc; // The class category.
final Method fromStringMethod; // The static valueOf(String) or fromString(String) or forString(String) method (if it has one).
- Constructor<? extends T>
+ final Constructor<? extends T>
noArgConstructor; // The no-arg constructor for this class (if it has one).
final Constructor<T>
stringConstructor, // The X(String) constructor (if it has one).
@@ -82,7 +84,10 @@ public final class ClassMeta<T> implements Type {
final Map<String,Method>
remoteableMethods, // Methods annotated with @Remoteable. Contains all public methods if class is annotated with @Remotable.
publicMethods; // All public methods, including static methods.
-
+ final PojoSwap<?,?>[] childPojoSwaps; // Any PojoSwaps where the normal type is a subclass of this class.
+ final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
+ childSwapMap, // Maps normal subclasses to PojoSwaps.
+ childUnswapMap; // Maps swap subclasses to PojoSwaps.
final BeanContext beanContext; // The bean context that created this object.
ClassMeta<?>
@@ -99,7 +104,6 @@ public final class ClassMeta<T> implements Type {
private MetadataMap extMeta = new MetadataMap(); // Extended metadata
private Throwable initException; // Any exceptions thrown in the init() method.
- private boolean hasChildPojoSwaps; // True if this class or any subclass of this class has a PojoSwap associated with it.
private static final Boolean BOOLEAN_DEFAULT = false;
private static final Character CHARACTER_DEFAULT = (char)0;
@@ -113,8 +117,8 @@ public final class ClassMeta<T> implements Type {
/**
* Shortcut for calling <code>ClassMeta(innerClass, beanContext, <jk>false</jk>)</code>.
*/
- ClassMeta(Class<T> innerClass, BeanContext beanContext) {
- this(innerClass, beanContext, false);
+ ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?> pojoSwap, PojoSwap<?,?>[] childPojoSwaps) {
+ this(innerClass, beanContext, implClass, beanFilter, pojoSwap, childPojoSwaps, false);
}
/**
@@ -122,13 +126,26 @@ public final class ClassMeta<T> implements Type {
*
* @param innerClass The class being wrapped.
* @param beanContext The bean context that created this object.
+ * @param implClass For interfaces and abstract classes, this represents the "real" class to instantiate.
+ * Can be <jk>null</jk>.
+ * @param beanFilter The {@link BeanFilter} programmatically associated with this class.
+ * Can be <jk>null</jk>.
+ * @param pojoSwap The {@link PojoSwap} programmatically associated with this class.
+ * Can be <jk>null</jk>.
+ * @param childPojoSwap The child {@link PojoSwap PojoSwaps} programmatically associated with this class.
+ * These are the <code>PojoSwaps</code> that have normal classes that are subclasses of this class.
+ * Can be <jk>null</jk>.
* @param delayedInit Don't call init() in constructor.
* Used for delayed initialization when the possibility of class reference loops exist.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- ClassMeta(Class<T> innerClass, BeanContext beanContext, boolean delayedInit) {
+ ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?> pojoSwap, PojoSwap<?,?>[] childPojoSwaps, boolean delayedInit) {
this.innerClass = innerClass;
this.beanContext = beanContext;
+ this.implClass = implClass;
+ this.childPojoSwaps = childPojoSwaps;
+ this.childSwapMap = childPojoSwaps == null ? null : new ConcurrentHashMap<Class<?>,PojoSwap<?,?>>();
+ this.childUnswapMap = childPojoSwaps == null ? null : new ConcurrentHashMap<Class<?>,PojoSwap<?,?>>();
Class<T> c = innerClass;
ClassCategory _cc = ClassCategory.OTHER;
@@ -351,6 +368,41 @@ public final class ClassMeta<T> implements Type {
}
}
+ if (innerClass != Object.class) {
+ _noArgConstructor = (Constructor<T>)findNoArgConstructor(implClass == null ? innerClass : implClass, Visibility.PUBLIC);
+ }
+
+ if (beanFilter == null)
+ beanFilter = findBeanFilter();
+
+ PojoSwap ps = null;
+ if (_swapMethod != null) {
+ ps = new PojoSwap<T,Object>(c, _swapMethod.getReturnType()) {
+ @Override
+ public Object swap(BeanSession session, Object o) throws SerializeException {
+ try {
+ return swapMethod.invoke(o, session);
+ } catch (Exception e) {
+ throw new SerializeException(e);
+ }
+ }
+ @Override
+ public T unswap(BeanSession session, Object f, ClassMeta<?> hint) throws ParseException {
+ try {
+ if (swapConstructor != null)
+ return swapConstructor.newInstance(f);
+ return super.unswap(session, f, hint);
+ } catch (Exception e) {
+ throw new ParseException(e);
+ }
+ }
+ };
+ }
+ if (ps == null)
+ ps = findPojoSwap();
+ if (ps == null)
+ ps = pojoSwap;
+
this.cc = _cc;
this.isDelegate = _isDelegate;
this.fromStringMethod = _fromStringMethod;
@@ -368,6 +420,8 @@ public final class ClassMeta<T> implements Type {
this.primitiveDefault = _primitiveDefault;
this.publicMethods = _publicMethods;
this.remoteableMethods = _remoteableMethods;
+ this.beanFilter = beanFilter;
+ this.pojoSwap = ps;
if (! delayedInit)
init();
@@ -379,6 +433,10 @@ public final class ClassMeta<T> implements Type {
*/
ClassMeta(ClassMeta<T> mainType, ClassMeta<?> keyType, ClassMeta<?> valueType, ClassMeta<?> elementType) {
this.innerClass = mainType.innerClass;
+ this.implClass = mainType.implClass;
+ this.childPojoSwaps = mainType.childPojoSwaps;
+ this.childSwapMap = mainType.childSwapMap;
+ this.childUnswapMap = mainType.childUnswapMap;
this.cc = mainType.cc;
this.fromStringMethod = mainType.fromStringMethod;
this.noArgConstructor = mainType.noArgConstructor;
@@ -412,23 +470,12 @@ public final class ClassMeta<T> implements Type {
this.beanFilter = mainType.beanFilter;
this.extMeta = mainType.extMeta;
this.initException = mainType.initException;
- this.hasChildPojoSwaps = mainType.hasChildPojoSwaps;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
ClassMeta init() {
try {
- beanFilter = findBeanFilter(beanContext);
- pojoSwap = findPojoSwap(beanContext);
-
- if (innerClass != Object.class) {
- this.noArgConstructor = beanContext.getImplClassConstructor(innerClass, Visibility.PUBLIC);
- if (noArgConstructor == null)
- noArgConstructor = findNoArgConstructor(innerClass, Visibility.PUBLIC);
- }
-
- this.hasChildPojoSwaps = beanContext.hasChildPojoSwaps(innerClass);
Class c = innerClass;
@@ -528,6 +575,35 @@ public final class ClassMeta<T> implements Type {
return beanContext.findParameters(innerClass, innerClass);
}
+ private BeanFilter findBeanFilter() {
+ try {
+ List<Bean> ba = ReflectionUtils.findAnnotations(Bean.class, innerClass);
+ if (! ba.isEmpty())
+ return new AnnotationBeanFilterBuilder(innerClass, ba).build();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private PojoSwap<T,?> findPojoSwap() {
+ try {
+ Pojo p = innerClass.getAnnotation(Pojo.class);
+ if (p != null) {
+ Class<?> c = p.swap();
+ if (c != Null.class) {
+ if (ClassUtils.isParentClass(PojoSwap.class, c))
+ return (PojoSwap<T,?>)c.newInstance();
+ throw new RuntimeException("TODO - Surrogate classes not yet supported.");
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/**
* Returns the bean dictionary name associated with this class.
* <p>
@@ -597,45 +673,58 @@ public final class ClassMeta<T> implements Type {
*
* @return <jk>true</jk> if this class or any child classes has a {@link PojoSwap} associated with it.
*/
- public boolean hasChildPojoSwaps() {
- return hasChildPojoSwaps;
+ protected boolean hasChildPojoSwaps() {
+ return childPojoSwaps != null;
}
- private BeanFilter findBeanFilter(BeanContext context) {
- try {
- if (context == null)
+ /**
+ * Returns the {@link PojoSwap} where the specified class is the same/subclass of the normal class of
+ * one of the child pojo swaps associated with this class.
+ *
+ * @param normalClass The normal class being resolved.
+ * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found.
+ */
+ protected PojoSwap<?,?> getChildPojoSwapForSwap(Class<?> normalClass) {
+ if (childSwapMap != null) {
+ PojoSwap<?,?> s = childSwapMap.get(normalClass);
+ if (s == null) {
+ for (PojoSwap<?,?> f : childPojoSwaps)
+ if (s == null && isParentClass(f.getNormalClass(), normalClass))
+ s = f;
+ if (s == null)
+ s = PojoSwap.NULL;
+ childSwapMap.putIfAbsent(normalClass, s);
+ }
+ if (s == PojoSwap.NULL)
return null;
- BeanFilter f = context.findBeanFilter(innerClass);
- if (f != null)
- return f;
- List<Bean> ba = ReflectionUtils.findAnnotations(Bean.class, innerClass);
- if (! ba.isEmpty())
- f = new AnnotationBeanFilterBuilder(innerClass, ba).build();
- return f;
- } catch (Exception e) {
- throw new RuntimeException(e);
+ return s;
}
+ return null;
}
- @SuppressWarnings("unchecked")
- private PojoSwap<T,?> findPojoSwap(BeanContext context) {
- try {
- Pojo p = innerClass.getAnnotation(Pojo.class);
- if (p != null) {
- Class<?> c = p.swap();
- if (c != Null.class) {
- if (ClassUtils.isParentClass(PojoSwap.class, c))
- return (PojoSwap<T,?>)c.newInstance();
- throw new RuntimeException("TODO - Surrogate classes not yet supported.");
- }
+ /**
+ * Returns the {@link PojoSwap} where the specified class is the same/subclass of the swap class of
+ * one of the child pojo swaps associated with this class.
+ *
+ * @param swapClass The swap class being resolved.
+ * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found.
+ */
+ protected PojoSwap<?,?> getChildPojoSwapForUnswap(Class<?> swapClass) {
+ if (childUnswapMap != null) {
+ PojoSwap<?,?> s = childUnswapMap.get(swapClass);
+ if (s == null) {
+ for (PojoSwap<?,?> f : childPojoSwaps)
+ if (s == null && isParentClass(f.getSwapClass(), swapClass))
+ s = f;
+ if (s == null)
+ s = PojoSwap.NULL;
+ childUnswapMap.putIfAbsent(swapClass, s);
}
- if (context == null)
+ if (s == PojoSwap.NULL)
return null;
- PojoSwap<T,?> f = context.findPojoSwap(innerClass);
- return f;
- } catch (Exception e) {
- throw new RuntimeException(e);
+ return s;
}
+ return null;
}
/**
@@ -1512,31 +1601,31 @@ public final class ClassMeta<T> implements Type {
public int hashCode() {
return super.hashCode();
}
-
- public abstract static class CreateSession {
- LinkedList<ClassMeta<?>> stack;
-
- public CreateSession push(ClassMeta<?> cm) {
- if (stack == null)
- stack = new LinkedList<ClassMeta<?>>();
- stack.add(cm);
- return this;
- }
-
- public CreateSession pop(ClassMeta<?> expected) {
- if (stack == null || stack.removeLast() != expected)
- throw new BeanRuntimeException("ClassMetaSession creation stack corruption!");
- return this;
- }
-
- public <T> ClassMeta<T> getClassMeta(Class<T> c) {
- if (stack != null)
- for (ClassMeta<?> cm : stack)
- if (cm.innerClass == c)
- return (ClassMeta<T>)cm;
- return createClassMeta(c);
- }
-
- public abstract <T> ClassMeta<T> createClassMeta(Class<T> c);
- }
+//
+// public abstract static class CreateSession {
+// LinkedList<ClassMeta<?>> stack;
+//
+// public CreateSession push(ClassMeta<?> cm) {
+// if (stack == null)
+// stack = new LinkedList<ClassMeta<?>>();
+// stack.add(cm);
+// return this;
+// }
+//
+// public CreateSession pop(ClassMeta<?> expected) {
+// if (stack == null || stack.removeLast() != expected)
+// throw new BeanRuntimeException("ClassMetaSession creation stack corruption!");
+// return this;
+// }
+//
+// public <T> ClassMeta<T> getClassMeta(Class<T> c) {
+// if (stack != null)
+// for (ClassMeta<?> cm : stack)
+// if (cm.innerClass == c)
+// return (ClassMeta<T>)cm;
+// return createClassMeta(c);
+// }
+//
+// public abstract <T> ClassMeta<T> createClassMeta(Class<T> c);
+// }
}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/062d7ddc/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
index ec97dd8..5a1d104 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
@@ -98,6 +98,12 @@ import org.apache.juneau.serializer.*;
*/
public abstract class PojoSwap<T,S> {
+ /**
+ * Represents a non-existent pojo swap.
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public final static PojoSwap NULL = new PojoSwap(null, null) {};
+
private final Class<T> normalClass;
private final Class<?> swapClass;
private ClassMeta<?> swapClassMeta;