Repository: incubator-juneau Updated Branches: refs/heads/master fc1e3fcfc -> 495c648d1
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaType.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaType.java index 5d8070d..6f9c3db 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaType.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaType.java @@ -12,6 +12,8 @@ // *************************************************************************************************************************** package org.apache.juneau.http; +import static org.apache.juneau.internal.StringUtils.*; + import java.util.*; import java.util.concurrent.*; @@ -64,9 +66,10 @@ public class MediaType implements Comparable<MediaType> { private final String type; // The media type (e.g. "text" for Accept, "utf-8" for Accept-Charset) private final String subType; // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset) private final String[] subTypes; // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset) + private final String[] subTypesSorted; // Same as subTypes, but sorted so that it can be used for comparison. private final List<String> subTypesList; // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset) private final Map<String,Set<String>> parameters; // The media type parameters (e.g. "text/html;level=1"). Does not include q! - + private final boolean hasSubtypeMeta; // The media subtype contains meta-character '*'. /** * Returns the media type for the specified string. @@ -87,11 +90,11 @@ public class MediaType implements Comparable<MediaType> { * @param s * The media type string. * Will be lowercased. - * Returns <jk>null</jk> if input is null. + * Returns <jk>null</jk> if input is null or empty. * @return A cached media type object. */ public static MediaType forString(String s) { - if (s == null) + if (isEmpty(s)) return null; MediaType mt = cache.get(s); if (mt == null) { @@ -103,20 +106,40 @@ public class MediaType implements Comparable<MediaType> { return cache.get(s); } + /** + * Same as {@link #forString(String)} but allows you to construct an array of <code>MediaTypes</code> from an + * array of strings. + * + * @param s + * The media type strings. + * @return + * An array of <code>MediaType</code> objects. + * <br>Always the same length as the input string array. + */ + public static MediaType[] forStrings(String...s) { + MediaType[] mt = new MediaType[s.length]; + for (int i = 0; i < s.length; i++) + mt[i] = forString(s[i]); + return mt; + } + MediaType(String mt) { Builder b = new Builder(mt); this.mediaType = b.mediaType; this.type = b.type; this.subType = b.subType; this.subTypes = b.subTypes; + this.subTypesSorted = b.subTypesSorted; this.subTypesList = Collections.unmodifiableList(Arrays.asList(subTypes)); this.parameters = (b.parameters == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(b.parameters)); + this.hasSubtypeMeta = b.hasSubtypeMeta; } private static class Builder { private String mediaType, type, subType; - private String[] subTypes; + private String[] subTypes, subTypesSorted; private Map<String,Set<String>> parameters; + private boolean hasSubtypeMeta; private Builder(String mt) { mt = mt.trim(); @@ -149,6 +172,9 @@ public class MediaType implements Comparable<MediaType> { subType = (i == -1 ? "*" : mt.substring(i+1)); } this.subTypes = StringUtils.split(subType, '+'); + this.subTypesSorted = Arrays.copyOf(subTypes, subTypes.length); + Arrays.sort(this.subTypesSorted); + hasSubtypeMeta = ArrayUtils.contains("*", this.subTypes); } } @@ -200,33 +226,28 @@ public class MediaType implements Comparable<MediaType> { } /** - * Returns <jk>true</jk> if this media type is a match for the specified media type. - * - * <p> - * Matches if any of the following is true: - * <ul> - * <li>Both type and subtype are the same. - * <li>One or both types are <js>'*'</js> and the subtypes are the same. - * <li>One or both subtypes are <js>'*'</js> and the types are the same. - * <li>Either is <js>'*\/*'</js>. - * </ul> + * Returns <jk>true</jk> if this media type contains the <js>'*'</js> meta character. * - * @param o The media type to compare with. - * @return <jk>true</jk> if the media types match. + * @return <jk>true</jk> if this media type contains the <js>'*'</js> meta character. */ - public final boolean matches(MediaType o) { - return match(o) > 0; + public final boolean isMeta() { + return hasSubtypeMeta; } /** * Returns a match metric against the specified media type where a larger number represents a better match. * + * <p> + * This media type can contain <js>'*'</js> metacharacters. + * <br>The comparison media type must not. + * * <ul> * <li>Exact matches (e.g. <js>"text/json"<js>/</js>"text/json"</js>) should match * better than meta-character matches (e.g. <js>"text/*"<js>/</js>"text/json"</js>) * <li>The comparison media type can have additional subtype tokens (e.g. <js>"text/json+foo"</js>) - * that will not prevent a match. The reverse is not true, e.g. the comparison media type - * must contain all subtype tokens found in the comparing media type. + * that will not prevent a match if the <code>allowExtraSubTypes</code> flag is set. + * The reverse is not true, e.g. the comparison media type must contain all subtype tokens found in the + * comparing media type. * <ul> * <li>We want the {@link JsonSerializer} (<js>"text/json"</js>) class to be able to handle requests for <js>"text/json+foo"</js>. * <li>We want to make sure {@link org.apache.juneau.json.JsonSerializer.Simple} (<js>"text/json+simple"</js>) does not handle @@ -235,43 +256,70 @@ public class MediaType implements Comparable<MediaType> { * More token matches should result in a higher match number. * </ul> * + * The formula is as follows for <code>type/subTypes</code>: + * <ul> + * <li>An exact match is <code>100,000</code>. + * <li>Add the following for type (assuming subtype match is <0): + * <ul> + * <li><code>10,000</code> for an exact match (e.g. <js>"text"</js>==<js>"text"</js>). + * <li><code>5,000</code> for a meta match (e.g. <js>"*"</js>==<js>"text"</js>). + * <ul> + * <li>Add the following for subtype (assuming type match is <0): + * <ul> + * <li><code>7,500</code> for an exact match (e.g. <js>"json+foo"</js>==<js>"json+foo"</js> or <js>"json+foo"</js>==<js>"foo+json"</js>) + * <li><code>100</code> for every subtype entry match (e.g. <js>"json"</js>/<js>"json+foo"</js>) + * <li><code>10</code> for a subtype entry meta match (e.g. <js>"*"</js>/<js>"json"</js> or <js>"json+*"</js>/<js>"json+foo"</js>) + * </ul> + * </ul> + * * @param o The media type to compare with. + * @param allowExtraSubTypes If <jk>true</jk>, * @return <jk>true</jk> if the media types match. */ - public final int match(MediaType o) { + public final int match(MediaType o, boolean allowExtraSubTypes) { // Perfect match if (this == o || (type.equals(o.type) && subType.equals(o.subType))) - return Integer.MAX_VALUE; + return 100000; - int c1 = 0, c2 = 0; + int c = 0; if (type.equals(o.type)) - c1 += 10000; + c += 10000; else if ("*".equals(type) || "*".equals(o.type)) - c1 += 5000; + c += 5000; - if (c1 == 0) + if (c == 0) return 0; - // Give type slightly higher comparison value than subtype simply for deterministic results. - if (subType.equals(o.subType)) - return c1 + 9999; - - int c3 = 0; + // Subtypes match but are ordered different + if (ArrayUtils.equals(subTypesSorted, o.subTypesSorted)) + return c + 7500; for (String st1 : subTypes) { if ("*".equals(st1)) - c1++; + c += 0; else if (ArrayUtils.contains(st1, o.subTypes)) - c1 += 100; - else if (ArrayUtils.contains("*", o.subTypes)) - c1 += 10; + c += 100; + else if (o.hasSubtypeMeta) + c += 10; else return 0; } + for (String st2 : o.subTypes) { + if ("*".equals(st2)) + c += 0; + else if (ArrayUtils.contains(st2, subTypes)) + c += 100; + else if (hasSubtypeMeta) + c += 10; + else if (! allowExtraSubTypes) + return 0; + else + c += 10; + } - return c1 + c2 + c3; + return c; } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaTypeRange.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaTypeRange.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaTypeRange.java index 0267b3d..0cdfd99 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaTypeRange.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/MediaTypeRange.java @@ -278,17 +278,4 @@ public final class MediaTypeRange implements Comparable<MediaTypeRange> { int i = o.mediaType.toString().compareTo(mediaType.toString()); return i; } - - /** - * Matches the specified media type against this range and returns a q-value between 0 and 1 indicating the - * quality of the match. - * - * @param o The media type to match against. - * @return A float between 0 and 1. 1 is a perfect match. 0 is no match at all. - */ - public float matches(MediaType o) { - if (this.mediaType == o || mediaType.matches(o)) - return qValue; - return 0; - } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java index c088cf8..9221bff 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java @@ -416,4 +416,20 @@ public final class ArrayUtils { r[i++] = StringUtils.toString(o); return r; } + + /** + * Returns <jk>true</jk> if the following sorted arrays are equals. + * + * @param a1 Array #1. + * @param a2 Array #2. + * @return <jk>true</jk> if the following sorted arrays are equals. + */ + public static boolean equals(String[] a1, String[] a2) { + if (a1.length != a2.length) + return false; + for (int i = 0; i < a1.length; i++) + if (! StringUtils.isEquals(a1[i], a2[i])) + return false; + return true; + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java ---------------------------------------------------------------------- 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 ba25f7a..a42684c 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 @@ -456,7 +456,13 @@ public final class ClassUtils { oc = oc.getSuperclass(); } - ParameterizedType opt = (ParameterizedType)oc.getGenericSuperclass(); + Type gsc = oc.getGenericSuperclass(); + + // Not actually a parameterized type. + if (! (gsc instanceof ParameterizedType)) + return Object.class; + + ParameterizedType opt = (ParameterizedType)gsc; Type actualType = opt.getActualTypeArguments()[index]; if (typeMap.containsKey(actualType)) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java index 6cb332a..00eeae4 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java @@ -109,8 +109,8 @@ public final class JsonParserSession extends ReaderParserSession { if (eType == null) eType = (ClassMeta<T>)object(); - PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(); - ClassMeta<?> sType = eType.getSerializedClassMeta(); + PojoSwap<T,Object> swap = (PojoSwap<T,Object>)eType.getPojoSwap(this); + ClassMeta<?> sType = swap == null ? eType : swap.getSwapClassMeta(this); setCurrentClass(sType); String wrapperAttr = sType.getExtendedMeta(JsonClassMeta.class).getWrapperAttr(); @@ -205,8 +205,8 @@ public final class JsonParserSession extends ReaderParserSession { if (wrapperAttr != null) skipWrapperAttrEnd(r); - if (transform != null && o != null) - o = transform.unswap(this, o, eType); + if (swap != null && o != null) + o = swap.unswap(this, o, eType); if (outer != null) setParent(eType, o, outer); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java index 17e3a31..9a782ae 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java @@ -72,7 +72,7 @@ public class JsonSchemaSerializerSession extends JsonSerializerSession { aType = push(attrName, eType, null); - sType = eType.getSerializedClassMeta(); + sType = eType.getSerializedClassMeta(this); String type = null; if (sType.isEnum() || sType.isCharSequence() || sType.isChar()) @@ -90,7 +90,7 @@ public class JsonSchemaSerializerSession extends JsonSerializerSession { out.put("type", type); out.put("description", eType.toString()); - PojoSwap f = eType.getPojoSwap(); + PojoSwap f = eType.getPojoSwap(this); if (f != null) out.put("transform", f); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java index 0709660..5336f7b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java @@ -148,7 +148,7 @@ public class JsonSerializer extends WriterSerializer { .append(JSON_simpleMode, true) .append(SERIALIZER_quoteChar, '\''), "application/json", - "application/json+simple", "text/json+simple" + "application/json+simple", "application/json+simple+*", "text/json+simple", "text/json+simple+*" ); } } @@ -204,7 +204,7 @@ public class JsonSerializer extends WriterSerializer { * The property store containing all the settings for this object. */ public JsonSerializer(PropertyStore propertyStore) { - this(propertyStore, "application/json", "application/json", "text/json"); + this(propertyStore, "application/json", "application/json", "application/json+*", "text/json", "text/json+*"); } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java index c9266a2..e1eeec0 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java @@ -94,13 +94,14 @@ public class JsonSerializerSession extends WriterSerializerSession { aType = object(); } - sType = aType.getSerializedClassMeta(); + sType = aType; String typeName = getBeanTypeName(eType, aType, pMeta); // Swap if necessary - PojoSwap swap = aType.getPojoSwap(); + PojoSwap swap = aType.getPojoSwap(this); if (swap != null) { o = swap.swap(this, o); + sType = swap.getSwapClassMeta(this); // If the getSwapClass() method returns Object, we need to figure out // the actual type now. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java index 8827370..bd4e708 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java @@ -57,8 +57,8 @@ public final class MsgPackParserSession extends InputStreamParserSession { if (eType == null) eType = (ClassMeta<T>)object(); - PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(); - ClassMeta<?> sType = eType.getSerializedClassMeta(); + PojoSwap<T,Object> swap = (PojoSwap<T,Object>)eType.getPojoSwap(this); + ClassMeta<?> sType = swap == null ? eType : swap.getSwapClassMeta(this); setCurrentClass(sType); Object o = null; @@ -186,8 +186,8 @@ public final class MsgPackParserSession extends InputStreamParserSession { } } - if (transform != null && o != null) - o = transform.unswap(this, o, eType); + if (swap != null && o != null) + o = swap.unswap(this, o, eType); if (outer != null) setParent(eType, o, outer); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java index 9b81a16..6a2f4f4 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java @@ -107,13 +107,14 @@ public final class MsgPackSerializerSession extends OutputStreamSerializerSessio aType = object(); } - sType = aType.getSerializedClassMeta(); + sType = aType; String typeName = getBeanTypeName(eType, aType, pMeta); // Swap if necessary - PojoSwap swap = aType.getPojoSwap(); + PojoSwap swap = aType.getPojoSwap(this); if (swap != null) { o = swap.swap(this, o); + sType = swap.getSwapClassMeta(this); // If the getSwapClass() method returns Object, we need to figure out // the actual type now. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java index cbb2a85..7992a2e 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java @@ -692,8 +692,8 @@ public abstract class ParserSession extends BeanSession { if (type == null) type = (ClassMeta<T>)object(); - PojoSwap transform = type.getPojoSwap(); - ClassMeta<?> sType = type.getSerializedClassMeta(); + PojoSwap swap = type.getPojoSwap(this); + ClassMeta<?> sType = swap == null ? type : swap.getSwapClassMeta(this); Object o = s; if (sType.isChar()) @@ -712,8 +712,8 @@ public abstract class ParserSession extends BeanSession { throw new ParseException(getLastLocation(), "Invalid conversion from string to class ''{0}''", type); } - if (transform != null) - o = transform.unswap(this, o, type); + if (swap != null) + o = swap.unswap(this, o, type); return (T)o; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java index a243fcc..450fc2f 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java @@ -535,7 +535,7 @@ public abstract class SerializerSession extends BeanSession { try { if (o == null) return null; - PojoSwap f = (type == null || type.isObject() ? getClassMeta(o.getClass()).getPojoSwap() : type.getPojoSwap()); + PojoSwap f = (type == null || type.isObject() ? getClassMeta(o.getClass()).getPojoSwap(this) : type.getPojoSwap(this)); if (f == null) return o; return f.swap(this, o); @@ -744,8 +744,8 @@ public abstract class SerializerSession extends BeanSession { StringBuilder sb = new StringBuilder().append('[').append(depth).append(']'); sb.append(isEmpty(name) ? "<noname>" : name).append(':'); sb.append(aType.toString(simple)); - if (aType != aType.getSerializedClassMeta()) - sb.append('/').append(aType.getSerializedClassMeta().toString(simple)); + if (aType != aType.getSerializedClassMeta(null)) + sb.append('/').append(aType.getSerializedClassMeta(null).toString(simple)); return sb.toString(); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/PojoSwap.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/PojoSwap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/PojoSwap.java index 8db7b53..d3d7859 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/PojoSwap.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/PojoSwap.java @@ -17,6 +17,8 @@ import static org.apache.juneau.internal.ClassUtils.*; import java.util.*; import org.apache.juneau.*; +import org.apache.juneau.http.*; +import org.apache.juneau.internal.*; import org.apache.juneau.parser.*; import org.apache.juneau.serializer.*; @@ -114,25 +116,31 @@ import org.apache.juneau.serializer.*; * @param <T> The normal form of the class. * @param <S> The swapped form of the class. */ +@SuppressWarnings({"unchecked","rawtypes","hiding"}) public abstract class PojoSwap<T,S> { /** * Represents a non-existent pojo swap. */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public final static PojoSwap NULL = new PojoSwap(null, null) {}; + public final static PojoSwap NULL = new PojoSwap((Class)null, (Class)null) {}; private final Class<T> normalClass; private final Class<?> swapClass; private ClassMeta<?> swapClassMeta; + // Unfortunately these cannot be made final because we want to allow for PojoSwaps with no-arg constructors + // which simplifies + private MediaType[] forMediaTypes; + private String template; + /** * Constructor. */ - @SuppressWarnings("unchecked") protected PojoSwap() { normalClass = (Class<T>)resolveParameterType(PojoSwap.class, 0, this.getClass()); swapClass = resolveParameterType(PojoSwap.class, 1, this.getClass()); + forMediaTypes = forMediaTypes(); + template = withTemplate(); } /** @@ -144,6 +152,49 @@ public abstract class PojoSwap<T,S> { protected PojoSwap(Class<T> normalClass, Class<?> swapClass) { this.normalClass = normalClass; this.swapClass = swapClass; + this.forMediaTypes = forMediaTypes(); + this.template = withTemplate(); + } + + protected MediaType[] forMediaTypes() { + return null; + } + + protected String withTemplate() { + return null; + } + + public PojoSwap<T,?> forMediaTypes(MediaType[] mediaTypes) { + if (mediaTypes != null && mediaTypes.length > 0) + this.forMediaTypes = mediaTypes; + return this; + } + + public PojoSwap<T,?> withTemplate(String template) { + if (! StringUtils.isEmpty(template)) + this.template = template; + return this; + } + +// /** +// * Returns <jk>true</jk> if this swap is valid for the specified session. +// * +// * <p> +// * If the swap has a media type associated with it, this method ensures that the media type matches the media +// * type defined on the session. +// * +// * @param session The bean session. +// * @return <jk>true</jk> if this swap is valid for the specified session. +// */ + public int match(BeanSession session) { + if (forMediaTypes == null) + return 1; + int i = 0; + MediaType mt = session.getMediaType(); + if (forMediaTypes != null) + for (MediaType mt2 : forMediaTypes) + i = Math.max(i, mt2.match(mt, false)*2); + return i; } /** @@ -176,6 +227,22 @@ public abstract class PojoSwap<T,S> { * @throws Exception If a problem occurred trying to convert the output. */ public S swap(BeanSession session, T o) throws Exception { + return swap(session, o, template); + } + + /** + * Same as {@link #swap(BeanSession, Object)}, but can be used if your swap has a template associated with it. + * + * @param session + * The bean session to use to get the class meta. + * This is always going to be the same bean context that created this swap. + * @param o The object to be transformed. + * @param template + * The template string associated with this swap. + * @return The transformed object. + * @throws Exception If a problem occurred trying to convert the output. + */ + public S swap(BeanSession session, T o, String template) throws Exception { throw new SerializeException("Swap method not implemented on PojoSwap ''{0}''", this.getClass().getName()); } @@ -195,6 +262,27 @@ public abstract class PojoSwap<T,S> { * @throws Exception If this method is not implemented. */ public T unswap(BeanSession session, S f, ClassMeta<?> hint) throws Exception { + return unswap(session, f, hint, template); + } + + /** + * Same as {@link #unswap(BeanSession, Object, ClassMeta)}, but can be used if your swap has a template associated with it. + * + * @param session + * The bean session to use to get the class meta. + * This is always going to be the same bean context that created this swap. + * @param f The transformed object. + * @param hint + * If possible, the parser will try to tell you the object type being created. + * For example, on a serialized date, this may tell you that the object being created must be of type + * {@code GregorianCalendar}. + * <br>This may be <jk>null</jk> if the parser cannot make this determination. + * @param template + * The template string associated with this swap. + * @return The transformed object. + * @throws Exception If a problem occurred trying to convert the output. + */ + public T unswap(BeanSession session, S f, ClassMeta<?> hint, String template) throws Exception { throw new ParseException("Unswap method not implemented on PojoSwap ''{0}''", this.getClass().getName()); } @@ -226,14 +314,14 @@ public abstract class PojoSwap<T,S> { * <p> * This value is cached for quick lookup. * - * @param beanContext + * @param session * The bean context to use to get the class meta. * This is always going to be the same bean context that created this swap. * @return The {@link ClassMeta} of the transformed class type. */ - public ClassMeta<?> getSwapClassMeta(BeanContext beanContext) { + public ClassMeta<?> getSwapClassMeta(BeanSession session) { if (swapClassMeta == null) - swapClassMeta = beanContext.getClassMeta(swapClass); + swapClassMeta = session.getClassMeta(swapClass); return swapClassMeta; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java index 9f731d4..c4974cd 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java @@ -122,8 +122,8 @@ public class UonParserSession extends ReaderParserSession { if (eType == null) eType = (ClassMeta<T>)object(); - PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(); - ClassMeta<?> sType = eType.getSerializedClassMeta(); + PojoSwap<T,Object> swap = (PojoSwap<T,Object>)eType.getPojoSwap(this); + ClassMeta<?> sType = swap == null ? eType : swap.getSwapClassMeta(this); Object o = null; @@ -248,8 +248,8 @@ public class UonParserSession extends ReaderParserSession { if (o == null && sType.isPrimitive()) o = sType.getPrimitiveDefault(); - if (transform != null && o != null) - o = transform.unswap(this, o, eType); + if (swap != null && o != null) + o = swap.unswap(this, o, eType); if (outer != null) setParent(eType, o, outer); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java index b6e8952..7730f1b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java @@ -129,13 +129,14 @@ public class UonSerializerSession extends WriterSerializerSession { aType = object(); } - sType = aType.getSerializedClassMeta(); + sType = aType; String typeName = getBeanTypeName(eType, aType, pMeta); // Swap if necessary - PojoSwap swap = aType.getPojoSwap(); + PojoSwap swap = aType.getPojoSwap(this); if (swap != null) { o = swap.swap(this, o); + sType = swap.getSwapClassMeta(this); // If the getSwapClass() method returns Object, we need to figure out // the actual type now. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java index f2a0c98..a3ebea4 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java @@ -59,7 +59,7 @@ public class UrlEncodingParserSession extends UonParserSession { * @return <jk>true</jk> if the specified bean property should be expanded as multiple key-value pairs. */ public final boolean shouldUseExpandedParams(BeanPropertyMeta pMeta) { - ClassMeta<?> cm = pMeta.getClassMeta(); + ClassMeta<?> cm = pMeta.getClassMeta().getSerializedClassMeta(this); if (cm.isCollectionOrArray()) { if (expandedParams) return true; @@ -89,8 +89,8 @@ public class UrlEncodingParserSession extends UonParserSession { if (eType == null) eType = (ClassMeta<T>)object(); - PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(); - ClassMeta<?> sType = eType.getSerializedClassMeta(); + PojoSwap<T,Object> swap = (PojoSwap<T,Object>)eType.getPojoSwap(this); + ClassMeta<?> sType = swap == null ? eType : swap.getSwapClassMeta(this); int c = r.peekSkipWs(); if (c == '?') @@ -139,8 +139,8 @@ public class UrlEncodingParserSession extends UonParserSession { } } - if (transform != null && o != null) - o = transform.unswap(this, o, eType); + if (swap != null && o != null) + o = swap.unswap(this, o, eType); if (outer != null) setParent(eType, o, outer); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java index cce9b4d..90e6b09 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java @@ -62,7 +62,7 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { * Returns <jk>true</jk> if the specified bean property should be expanded as multiple key-value pairs. */ private boolean shouldUseExpandedParams(BeanPropertyMeta pMeta) { - ClassMeta<?> cm = pMeta.getClassMeta(); + ClassMeta<?> cm = pMeta.getClassMeta().getSerializedClassMeta(this); if (cm.isCollectionOrArray()) { if (expandedParams) return true; @@ -78,7 +78,7 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { private boolean shouldUseExpandedParams(Object value) { if (value == null || ! expandedParams) return false; - ClassMeta<?> cm = getClassMetaForObject(value).getSerializedClassMeta(); + ClassMeta<?> cm = getClassMetaForObject(value).getSerializedClassMeta(this); if (cm.isCollectionOrArray()) { if (expandedParams) return true; @@ -104,13 +104,14 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { if (aType == null) aType = object(); - sType = aType.getSerializedClassMeta(); + sType = aType; String typeName = getBeanTypeName(object(), aType, null); // Swap if necessary - PojoSwap swap = aType.getPojoSwap(); + PojoSwap swap = aType.getPojoSwap(this); if (swap != null) { o = swap.swap(this, o); + sType = swap.getSwapClassMeta(this); // If the getSwapClass() method returns Object, we need to figure out // the actual type now. @@ -218,6 +219,7 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { for (BeanPropertyValue p : m.getValues(isTrimNulls(), typeName != null ? createBeanTypeNameProperty(m, typeName) : null)) { BeanPropertyMeta pMeta = p.getMeta(); ClassMeta<?> cMeta = p.getClassMeta(); + ClassMeta<?> sMeta = cMeta.getSerializedClassMeta(this); String key = p.getName(); Object value = p.getValue(); @@ -225,13 +227,13 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { if (t != null) onBeanGetterException(pMeta, t); - if (canIgnoreValue(cMeta, key, value)) + if (canIgnoreValue(sMeta, key, value)) continue; if (value != null && shouldUseExpandedParams(pMeta)) { // Transformed object array bean properties may be transformed resulting in ArrayLists, // so we need to check type if we think it's an array. - Iterator i = (cMeta.isCollection() || value instanceof Collection) ? ((Collection)value).iterator() : iterator(value); + Iterator i = (sMeta.isCollection() || value instanceof Collection) ? ((Collection)value).iterator() : iterator(value); while (i.hasNext()) { if (addAmp) out.cr(indent).append('&'); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java index 2a70b52..2b0cfcb 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java @@ -283,8 +283,8 @@ public class XmlParserSession extends ReaderParserSession { if (eType == null) eType = (ClassMeta<T>)object(); - PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(); - ClassMeta<?> sType = eType.getSerializedClassMeta(); + PojoSwap<T,Object> swap = (PojoSwap<T,Object>)eType.getPojoSwap(this); + ClassMeta<?> sType = swap == null ? eType : swap.getSwapClassMeta(this); setCurrentClass(sType); String wrapperAttr = (isRoot && preserveRootElement) ? r.getName().getLocalPart() : null; @@ -377,8 +377,8 @@ public class XmlParserSession extends ReaderParserSession { sType.getInnerClass().getName(), sType.getNotABeanReason(), pMeta == null ? null : pMeta.getName()); } - if (transform != null && o != null) - o = transform.unswap(this, o, eType); + if (swap != null && o != null) + o = swap.unswap(this, o, eType); if (outer != null) setParent(eType, o, outer); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerSession.java index 6de01ec..1046630 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerSession.java @@ -62,7 +62,7 @@ public class XmlSchemaSerializerSession extends XmlSerializerSession { Namespace xs = xsNamespace; Namespace[] allNs = append(new Namespace[]{defaultNamespace}, namespaces); - Schemas schemas = new Schemas(xs, defaultNamespace, allNs); + Schemas schemas = new Schemas(this, xs, defaultNamespace, allNs); schemas.process(o); schemas.serializeTo(out.getWriter()); } @@ -144,12 +144,14 @@ public class XmlSchemaSerializerSession extends XmlSerializerSession { private static final long serialVersionUID = 1L; private Namespace defaultNs; + private BeanSession session; private LinkedList<QueueEntry> elementQueue = new LinkedList<QueueEntry>(), attributeQueue = new LinkedList<QueueEntry>(), typeQueue = new LinkedList<QueueEntry>(); - private Schemas(Namespace xs, Namespace defaultNs, Namespace[] allNs) throws IOException { + private Schemas(BeanSession session, Namespace xs, Namespace defaultNs, Namespace[] allNs) throws IOException { + this.session = session; this.defaultNs = defaultNs; for (Namespace ns : allNs) put(ns, new Schema(this, xs, ns, defaultNs, allNs)); @@ -264,7 +266,7 @@ public class XmlSchemaSerializerSession extends XmlSerializerSession { return false; processedElements.add(name); - ClassMeta<?> ft = cm.getSerializedClassMeta(); + ClassMeta<?> ft = cm.getSerializedClassMeta(schemas.session); if (name == null) name = getElementName(ft); Namespace ns = first(ft.getExtendedMeta(XmlClassMeta.class).getNamespace(), defaultNs); @@ -302,7 +304,7 @@ public class XmlSchemaSerializerSession extends XmlSerializerSession { int i = indent + 1; - cm = cm.getSerializedClassMeta(); + cm = cm.getSerializedClassMeta(schemas.session); XmlBeanMeta xbm = cm.isBean() ? cm.getBeanMeta().getExtendedMeta(XmlBeanMeta.class) : null; w.oTag(i, "complexType") @@ -477,7 +479,7 @@ public class XmlSchemaSerializerSession extends XmlSerializerSession { } private String getElementName(ClassMeta<?> cm) { - cm = cm.getSerializedClassMeta(); + cm = cm.getSerializedClassMeta(schemas.session); String name = cm.getDictionaryName(); if (name == null) { @@ -507,7 +509,7 @@ public class XmlSchemaSerializerSession extends XmlSerializerSession { private String getXmlType(Namespace currentNs, ClassMeta<?> cm) { String name = null; - cm = cm.getSerializedClassMeta(); + cm = cm.getSerializedClassMeta(schemas.session); if (currentNs == targetNs) { if (cm.isPrimitive()) { if (cm.isBoolean()) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java index d1c348d..cf78f14 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java @@ -302,12 +302,13 @@ public class XmlSerializerSession extends WriterSerializerSession { eType = aType = ((Delegate<?>)o).getClassMeta(); } - sType = aType.getSerializedClassMeta(); + sType = aType; // Swap if necessary - PojoSwap swap = aType.getPojoSwap(); + PojoSwap swap = aType.getPojoSwap(this); if (swap != null) { o = swap.swap(this, o); + sType = swap.getSwapClassMeta(this); // If the getSwapClass() method returns Object, we need to figure out // the actual type now. @@ -315,7 +316,7 @@ public class XmlSerializerSession extends WriterSerializerSession { sType = getClassMetaForObject(o); } } else { - sType = eType.getSerializedClassMeta(); + sType = eType.getSerializedClassMeta(this); } // Does the actual type match the expected type? http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Introspectable.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Introspectable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Introspectable.java index b7f0dd1..c26a2d1 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Introspectable.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Introspectable.java @@ -17,6 +17,7 @@ import static javax.servlet.http.HttpServletResponse.*; import org.apache.juneau.*; import org.apache.juneau.json.*; import org.apache.juneau.rest.*; +import org.apache.juneau.transform.*; import org.apache.juneau.utils.*; /** @@ -54,8 +55,10 @@ public final class Introspectable implements RestConverter { if (method == null) return o; try { - if (cm.getPojoSwap() != null) - o = cm.getPojoSwap().swap(req.getBeanSession(), o); + BeanSession bs = req.getBeanSession(); + PojoSwap swap = cm.getPojoSwap(bs); + if (swap != null) + o = swap.swap(bs, o); return new PojoIntrospector(o, JsonParser.DEFAULT).invokeMethod(method, args); } catch (Exception e) { e.printStackTrace(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java index d551aa3..4768da2 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java @@ -16,6 +16,7 @@ import javax.servlet.http.*; import org.apache.juneau.*; import org.apache.juneau.rest.*; +import org.apache.juneau.transform.*; import org.apache.juneau.utils.*; /** @@ -53,8 +54,10 @@ public final class Traversable implements RestConverter { if (req.getPathMatch().getRemainder() != null) { try { - if (cm.getPojoSwap() != null) - o = cm.getPojoSwap().swap(req.getBeanSession(), o); + BeanSession bs = req.getBeanSession(); + PojoSwap swap = cm.getPojoSwap(bs); + if (swap != null) + o = swap.swap(bs, o); PojoRest p = new PojoRest(o, req.getBody().getReaderParser()); o = p.get(req.getPathMatch().getRemainder()); } catch (PojoRestException e) { http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java index 96c7904..327c220 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/labels/BeanDescription.java @@ -67,7 +67,7 @@ public final class BeanDescription { */ public BeanPropertyDescription(String name, ClassMeta<?> type) { this.name = name; - this.type = type.getSerializedClassMeta().toString(); + this.type = type.getSerializedClassMeta(null).toString(); } } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-rest/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/pojos/SwappedPojo.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/pojos/SwappedPojo.java b/juneau-rest/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/pojos/SwappedPojo.java index 25d914c..6d38a7c 100644 --- a/juneau-rest/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/pojos/SwappedPojo.java +++ b/juneau-rest/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/pojos/SwappedPojo.java @@ -14,7 +14,7 @@ package org.apache.juneau.rest.test.pojos; import org.apache.juneau.annotation.*; -@Pojo(swap=SwappedPojoSwap.class) +@Swap(SwappedPojoSwap.class) public class SwappedPojo { public boolean wasUnswapped; } \ No newline at end of file
