Add multi-swap support (part 1). Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/495c648d Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/495c648d Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/495c648d
Branch: refs/heads/master Commit: 495c648d1f8934ebb41ae93c2b9d541371de2dd6 Parents: fc1e3fc Author: JamesBognar <[email protected]> Authored: Mon Sep 4 19:54:11 2017 -0400 Committer: JamesBognar <[email protected]> Committed: Mon Sep 4 19:54:11 2017 -0400 ---------------------------------------------------------------------- .../java/org/apache/juneau/ClassMetaTest.java | 148 +++--- .../a/rttests/RoundTripTransformBeansTest.java | 2 +- .../org/apache/juneau/https/AcceptTest.java | 74 ++- .../juneau/serializer/SerializerGroupTest.java | 6 +- .../apache/juneau/test/pojos/SwappedPojo.java | 2 +- .../juneau/transforms/ReaderObjectSwapTest.java | 8 +- .../transforms/SwapsAnnotationComboTest.java | 478 +++++++++++++++++++ .../apache/juneau/jena/RdfParserSession.java | 8 +- .../juneau/jena/RdfSerializerSession.java | 7 +- .../org/apache/juneau/BeanPropertyMeta.java | 2 +- .../java/org/apache/juneau/BeanSession.java | 16 +- .../main/java/org/apache/juneau/ClassMeta.java | 129 +++-- .../java/org/apache/juneau/annotation/Pojo.java | 84 ---- .../java/org/apache/juneau/annotation/Swap.java | 31 ++ .../org/apache/juneau/annotation/Swaps.java | 27 ++ .../apache/juneau/html/HtmlParserSession.java | 4 +- .../html/HtmlSchemaDocSerializerSession.java | 4 +- .../juneau/html/HtmlSerializerSession.java | 33 +- .../java/org/apache/juneau/http/Accept.java | 3 +- .../org/apache/juneau/http/ContentType.java | 2 +- .../java/org/apache/juneau/http/MediaType.java | 120 +++-- .../org/apache/juneau/http/MediaTypeRange.java | 13 - .../org/apache/juneau/internal/ArrayUtils.java | 16 + .../org/apache/juneau/internal/ClassUtils.java | 8 +- .../apache/juneau/json/JsonParserSession.java | 8 +- .../json/JsonSchemaSerializerSession.java | 4 +- .../org/apache/juneau/json/JsonSerializer.java | 4 +- .../juneau/json/JsonSerializerSession.java | 5 +- .../juneau/msgpack/MsgPackParserSession.java | 8 +- .../msgpack/MsgPackSerializerSession.java | 5 +- .../org/apache/juneau/parser/ParserSession.java | 8 +- .../juneau/serializer/SerializerSession.java | 6 +- .../org/apache/juneau/transform/PojoSwap.java | 100 +++- .../org/apache/juneau/uon/UonParserSession.java | 8 +- .../apache/juneau/uon/UonSerializerSession.java | 5 +- .../urlencoding/UrlEncodingParserSession.java | 10 +- .../UrlEncodingSerializerSession.java | 14 +- .../org/apache/juneau/xml/XmlParserSession.java | 8 +- .../juneau/xml/XmlSchemaSerializerSession.java | 14 +- .../apache/juneau/xml/XmlSerializerSession.java | 7 +- .../juneau/rest/converters/Introspectable.java | 7 +- .../juneau/rest/converters/Traversable.java | 7 +- .../juneau/rest/labels/BeanDescription.java | 2 +- .../juneau/rest/test/pojos/SwappedPojo.java | 2 +- 44 files changed, 1081 insertions(+), 376 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ClassMetaTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ClassMetaTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ClassMetaTest.java index e01e5d5..4559d78 100755 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ClassMetaTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ClassMetaTest.java @@ -114,8 +114,10 @@ public class ClassMetaTest { public void testSwaps() throws Exception { BeanContext bc; ClassMeta<?> ooo, hi1, hc1, hi2, hc2; + BeanSession bs; bc = PropertyStore.create().getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -126,18 +128,19 @@ public class ClassMetaTest { assertFalse(hc1.hasChildPojoSwaps()); assertFalse(hi2.hasChildPojoSwaps()); assertFalse(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertNull(hi1.getPojoSwap()); - assertNull(hc1.getPojoSwap()); - assertNull(hi2.getPojoSwap()); - assertNull(hc2.getPojoSwap()); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), HI1.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), HC1.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), HI2.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), HC2.class); + assertNull(ooo.getPojoSwap(bs)); + assertNull(hi1.getPojoSwap(bs)); + assertNull(hc1.getPojoSwap(bs)); + assertNull(hi2.getPojoSwap(bs)); + assertNull(hc2.getPojoSwap(bs)); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), HI1.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), HC1.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), HI2.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), HC2.class); bc = PropertyStore.create().setPojoSwaps(HI1Swap.class).getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -148,18 +151,19 @@ public class ClassMetaTest { assertFalse(hc1.hasChildPojoSwaps()); assertFalse(hi2.hasChildPojoSwaps()); assertFalse(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertEquals(hi1.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hc1.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hi2.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hc2.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), Map.class); + assertNull(ooo.getPojoSwap(bs)); + assertEquals(hi1.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hc1.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hi2.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hc2.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), Map.class); bc = PropertyStore.create().setPojoSwaps(HC1Swap.class).getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -170,18 +174,19 @@ public class ClassMetaTest { assertTrue(hc1.hasChildPojoSwaps()); assertFalse(hi2.hasChildPojoSwaps()); assertFalse(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertNull(hi1.getPojoSwap()); - assertEquals(hc1.getPojoSwap().getClass(), HC1Swap.class); - assertNull(hi2.getPojoSwap()); - assertEquals(hc2.getPojoSwap().getClass(), HC1Swap.class); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), HI1.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), HI2.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), Map.class); + assertNull(ooo.getPojoSwap(bs)); + assertNull(hi1.getPojoSwap(bs)); + assertEquals(hc1.getPojoSwap(bs).getClass(), HC1Swap.class); + assertNull(hi2.getPojoSwap(bs)); + assertEquals(hc2.getPojoSwap(bs).getClass(), HC1Swap.class); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), HI1.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), HI2.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), Map.class); bc = PropertyStore.create().setPojoSwaps(HI2Swap.class).getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -192,18 +197,19 @@ public class ClassMetaTest { assertFalse(hc1.hasChildPojoSwaps()); assertTrue(hi2.hasChildPojoSwaps()); assertFalse(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertNull(hi1.getPojoSwap()); - assertNull(hc1.getPojoSwap()); - assertEquals(hi2.getPojoSwap().getClass(), HI2Swap.class); - assertEquals(hc2.getPojoSwap().getClass(), HI2Swap.class); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), HI1.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), HC1.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), Map.class); + assertNull(ooo.getPojoSwap(bs)); + assertNull(hi1.getPojoSwap(bs)); + assertNull(hc1.getPojoSwap(bs)); + assertEquals(hi2.getPojoSwap(bs).getClass(), HI2Swap.class); + assertEquals(hc2.getPojoSwap(bs).getClass(), HI2Swap.class); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), HI1.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), HC1.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), Map.class); bc = PropertyStore.create().setPojoSwaps(HC2Swap.class).getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -214,18 +220,19 @@ public class ClassMetaTest { assertTrue(hc1.hasChildPojoSwaps()); assertTrue(hi2.hasChildPojoSwaps()); assertTrue(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertNull(hi1.getPojoSwap()); - assertNull(hc1.getPojoSwap()); - assertNull(hi2.getPojoSwap()); - assertEquals(hc2.getPojoSwap().getClass(), HC2Swap.class); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), HI1.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), HC1.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), HI2.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), Map.class); + assertNull(ooo.getPojoSwap(bs)); + assertNull(hi1.getPojoSwap(bs)); + assertNull(hc1.getPojoSwap(bs)); + assertNull(hi2.getPojoSwap(bs)); + assertEquals(hc2.getPojoSwap(bs).getClass(), HC2Swap.class); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), HI1.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), HC1.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), HI2.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), Map.class); bc = PropertyStore.create().setPojoSwaps(HI1Swap.class,HC1Swap.class,HI2Swap.class,HC2Swap.class).getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -236,18 +243,19 @@ public class ClassMetaTest { assertTrue(hc1.hasChildPojoSwaps()); assertTrue(hi2.hasChildPojoSwaps()); assertTrue(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertEquals(hi1.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hc1.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hi2.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hc2.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), Map.class); + assertNull(ooo.getPojoSwap(bs)); + assertEquals(hi1.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hc1.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hi2.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hc2.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), Map.class); bc = PropertyStore.create().setPojoSwaps(HC2Swap.class,HI2Swap.class,HC1Swap.class,HI1Swap.class).getBeanContext(); + bs = bc.createSession(); ooo = bc.getClassMeta(Object.class); hi1 = bc.getClassMeta(HI1.class); hc1 = bc.getClassMeta(HC1.class); @@ -258,16 +266,16 @@ public class ClassMetaTest { assertTrue(hc1.hasChildPojoSwaps()); assertTrue(hi2.hasChildPojoSwaps()); assertTrue(hc2.hasChildPojoSwaps()); - assertNull(ooo.getPojoSwap()); - assertEquals(hi1.getPojoSwap().getClass(), HI1Swap.class); - assertEquals(hc1.getPojoSwap().getClass(), HC1Swap.class); - assertEquals(hi2.getPojoSwap().getClass(), HI2Swap.class); - assertEquals(hc2.getPojoSwap().getClass(), HC2Swap.class); - assertEquals(ooo.getSerializedClassMeta().getInnerClass(), Object.class); - assertEquals(hi1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc1.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hi2.getSerializedClassMeta().getInnerClass(), Map.class); - assertEquals(hc2.getSerializedClassMeta().getInnerClass(), Map.class); + assertNull(ooo.getPojoSwap(bs)); + assertEquals(hi1.getPojoSwap(bs).getClass(), HI1Swap.class); + assertEquals(hc1.getPojoSwap(bs).getClass(), HC1Swap.class); + assertEquals(hi2.getPojoSwap(bs).getClass(), HI2Swap.class); + assertEquals(hc2.getPojoSwap(bs).getClass(), HC2Swap.class); + assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(), Object.class); + assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(), Map.class); + assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(), Map.class); } public interface HI1 {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java index 7ea011c..f05026c 100755 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java @@ -224,7 +224,7 @@ public class RoundTripTransformBeansTest extends RoundTripTest { assertEquals("bar", t.f1); } - @Pojo(swap=BSwap.class) + @Swap(BSwap.class) public static class B { public String f1; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java index 6f44506..d8fb3a7 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java @@ -47,17 +47,17 @@ public class AcceptTest { { "MetaMatch-1", "text/*", "['text/a','text/b+c','text/b+d+e']", 2 }, { "MetaMatch-2", "text/b+*", "['text/a','text/b+c','text/b+d+e']", 2 }, { "MetaMatch-3", "text/c+*", "['text/a','text/b+c','text/b+d+e']", 1 }, - { "MetaMatch-4", "text/b+d+e", "['text/a','text/b+c','text/b+d']", 2 }, - { "MetaMatch-5", "text/b+*", "['text/a','text/b+c','text/b+d']", 1 }, + { "MetaMatch-4", "text/b+d+e", "['text/a','text/b+c','text/b+d']", -1 }, + { "MetaMatch-5", "text/b+*", "['text/a','text/b+c','text/b+d+e']", 2 }, { "MetaMatch-6", "text/d+e+*", "['text/a','text/b+c','text/b+d+e']", 2 }, - { "MetaMatch-7", "*/a", "['text/a','application/a']", 0 }, + { "MetaMatch-7", "*/a", "['text/a','application/b']", 0 }, { "MetaMatch-8", "*/*", "['text/a','text/b+c']", 1 }, { "MetaMatch-9", "*/*", "['text/b+c','text/a']", 0 }, // Reverse meta-character matches { "RevMetaMatch-1", "text/a", "['text/*']", 0 }, - { "RevMetaMatch-3", "text/a", "['*/a']", 0 }, + { "RevMetaMatch-2", "text/a", "['*/a']", 0 }, { "RevMetaMatch-3", "text/a", "['*/*']", 0 }, // Meta-character mixture matches @@ -72,28 +72,32 @@ public class AcceptTest { { "Fuzzy-1", "text/1+2", "['text/1+2']", 0 }, // Order of subtype parts shouldn't matter. { "Fuzzy-2", "text/2+1", "['text/1+2']", 0 }, + // Should match if Accept has 'extra' subtypes. // For example, "Accept: text/json+activity" should match against the "text/json" serializer. - { "Fuzzy-3", "text/1+2", "['text/1']", 0 }, + { "Fuzzy-3", "text/json+foo", "['text/json+*']", 0 }, + // Shouldn't match because the accept media type must be at least a subset of the real media type // For example, "Accept: text/json" should not match against the "text/json+lax" serializer. - { "Fuzzy-4", "text/1", "['text/1+2']", -1 }, - { "Fuzzy-5", "text/1+2", "['text/1','text/1+3']", 0 }, + { "Fuzzy-4", "text/json", "['text/json+lax']", -1 }, + + { "Fuzzy-5", "text/1+2", "['text/1','text/1+3']", -1 }, + // "text/1+2" should be a better match than just "text/1" { "Fuzzy-6", "text/1+2", "['text/1','text/1+2','text/1+2+3']", 1 }, // Same as last, but mix up the order a bit. { "Fuzzy-7", "text/1+2", "['text/1+2+3','text/1','text/1+2']", 2 }, // Same as last, but mix up the order of the subtypes as well. { "Fuzzy-8", "text/1+2", "['text/3+2+1','text/1','text/2+1']", 2 }, - { "Fuzzy-9", "text/1+2+3+4", "['text/1+2','text/1+2+3']", 1 }, - { "Fuzzy-10", "text/1+2+3+4", "['text/1+2+3','text/1+2']", 0 }, - { "Fuzzy-11", "text/4+2+3+1", "['text/1+2+3','text/1+2']", 0 }, - { "Fuzzy-12", "text/4+2+3+1", "['text/1+2','text/1+2+3']", 1 }, + { "Fuzzy-9", "text/1+2+3+4", "['text/1+2','text/1+2+3']", -1 }, + { "Fuzzy-10", "text/1+2+3+4", "['text/1+2+3','text/1+2']", -1 }, + { "Fuzzy-11", "text/4+2+3+1", "['text/1+2+3','text/1+2']", -1 }, + { "Fuzzy-12", "text/4+2+3+1", "['text/1+2','text/1+2+3']", -1 }, // Q metrics { "Q-1", "text/A;q=0.9,text/B;q=0.1", "['text/A','text/B']", 0 }, { "Q-2", "text/A;q=0.9,text/B;q=0.1", "['text/B','text/A']", 1 }, - { "Q-3", "text/A+1;q=0.9,text/B;q=0.1", "['text/A','text/B']", 0 }, + { "Q-3", "text/A+1;q=0.9,text/B;q=0.1", "['text/A','text/B']", 1 }, { "Q-4", "text/A;q=0.9,text/B+1;q=0.1", "['text/A','text/B+1']", 0 }, { "Q-5", "text/A;q=0.9,text/A+1;q=0.1", "['text/A+1','text/A']", 1 }, @@ -104,6 +108,42 @@ public class AcceptTest { // Test media types with parameters { "Parms-1", "text/A", "['text/A;foo=bar','text/B']", 0 }, { "Parms-2", "text/A;foo=bar", "['text/A','text/B']", 0 }, + + // Real-world JSON + { "Json-1a", "text/json", "['text/json','text/json+*','text/*','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-1b", "text/json", "['text/json+*','text/*','text/json+lax','text/json+lax+*','text/foo','text/json']", 5 }, + { "Json-1c", "text/json", "['text/json+*','text/*','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-1d", "text/json", "['text/*','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-1e", "text/json", "['text/json+lax','text/json+lax+*','text/foo']", -1 }, + + { "Json-2a", "text/json+lax", "['text/json+lax','text/json+lax+*','text/json+*','text/lax+*','text/*','text/json','text/lax']", 0 }, + { "Json-2b", "text/json+lax", "['text/json+lax+*','text/json+*','text/lax+*','text/*','text/json','text/lax']", 0 }, + { "Json-2c", "text/json+lax", "['text/json+*','text/lax+foo+*','text/*','text/json','text/lax']", 0 }, + { "Json-2d", "text/json+lax", "['text/lax+*','text/*','text/json','text/lax']", 0 }, + { "Json-2e", "text/json+lax", "['text/*','text/json','text/lax']", 0 }, + { "Json-2f", "text/json+lax", "['text/json','text/lax']", -1 }, + + { "Json-3a", "text/json+activity", "['text/json+activity','text/activity+json','text/json+activity+*','text/json+*','text/*','text/json','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-3b", "text/json+activity", "['text/activity+json','text/json+activity+*','text/json+*','text/*','text/json','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-3c", "text/json+activity", "['text/json+activity+*','text/json+*','text/*','text/json','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-3d", "text/json+activity", "['text/json+*','text/*','text/json','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-3e", "text/json+activity", "['text/*','text/json','text/json+lax','text/json+lax+*','text/foo']", 0 }, + { "Json-3f", "text/json+activity", "['text/json','text/json+lax','text/json+lax+*','text/foo']", -1 }, + + // Real-world XML + { "Xml-1a", "text/xml", "['text/xml','text/xml+*','text/xml+rdf','text/foo']", 0 }, + { "Xml-1b", "text/xml", "['text/xml+*','text/xml+rdf','text/foo']", 0 }, + { "Xml-1c", "text/xml", "['text/xml+rdf','text/foo']", -1 }, + { "Xml-1d", "text/xml", "['text/foo']", -1 }, + + { "Xml-2a", "text/xml+id", "['text/xml+*','text/xml','text/xml+rdf']", 0 }, + { "Xml-2b", "text/xml+id", "['text/xml','text/xml+rdf']", -1 }, + { "Xml-2c", "text/xml+id", "['text/xml+rdf']", -1 }, + + // Real-world RDF + { "Rdf-1a", "text/xml+rdf", "['text/xml+rdf','text/xml+*','text/xml']", 0 }, + { "Rdf-1b", "text/xml+rdf", "['text/xml+*','text/xml']", 0 }, + { "Rdf-1c", "text/xml+rdf", "['text/xml']", -1 }, }); } @@ -124,4 +164,14 @@ public class AcceptTest { int r = accept.findMatch(mt); TestUtils.assertEquals(expected, r, "{0} failed", label); } + + @Test + public void testReversed() throws Exception { + Accept accept = Accept.forString(this.accept); + MediaType[] mt = JsonParser.DEFAULT.parse(mediaTypes, MediaType[].class); + Collections.reverse(Arrays.asList(mt)); + int r = accept.findMatch(mt); + int expected2 = expected == -1 ? -1 : mt.length-expected-1; + TestUtils.assertEquals(expected2, r, "{0} failed", label); + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java index b5e2db9..a9839d4 100755 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java @@ -52,19 +52,19 @@ public class SerializerGroupTest { public static class SA1 extends JsonSerializer { public SA1(PropertyStore propertyStore) { - super(propertyStore, "application/json", "text/foo", "text/foo_a"); + super(propertyStore, "application/json", "text/foo+*", "text/foo_a+*"); } } public static class SA2 extends JsonSerializer { public SA2(PropertyStore propertyStore) { - super(propertyStore, "application/json", "text/foo+bar", "text/foo+bar_a"); + super(propertyStore, "application/json", "text/foo+bar+*", "text/foo+bar_a+*"); } } public static class SA3 extends JsonSerializer { public SA3(PropertyStore propertyStore) { - super(propertyStore, "application/json", "text/baz", "text/baz_a"); + super(propertyStore, "application/json", "text/baz+*", "text/baz_a+*"); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/test/pojos/SwappedPojo.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/test/pojos/SwappedPojo.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/test/pojos/SwappedPojo.java index 605fd25..2cba47c 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/test/pojos/SwappedPojo.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/test/pojos/SwappedPojo.java @@ -14,7 +14,7 @@ package org.apache.juneau.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 http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/ReaderObjectSwapTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/ReaderObjectSwapTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/ReaderObjectSwapTest.java index 5bc0e65..edd1328 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/ReaderObjectSwapTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/ReaderObjectSwapTest.java @@ -349,7 +349,7 @@ public class ReaderObjectSwapTest extends ComboSerializeTest { super(comboInput); } - @Pojo(swap=PojoToSimpleReaderSwap.class) + @Swap(PojoToSimpleReaderSwap.class) public static class PojoToSimpleReader {} public static class PojoToSimpleReaderSwap extends PojoSwap<PojoToSimpleReader,Reader> { @@ -358,7 +358,7 @@ public class ReaderObjectSwapTest extends ComboSerializeTest { } } - @Pojo(swap=PojoToDynamicReaderSwap.class) + @Swap(PojoToDynamicReaderSwap.class) public static class PojoToDynamicReader { private String f; public PojoToDynamicReader(String f) { @@ -372,7 +372,7 @@ public class ReaderObjectSwapTest extends ComboSerializeTest { } } - @Pojo(swap=SometimesSwappedBeanSwap1.class) + @Swap(SometimesSwappedBeanSwap1.class) public static class SometimesSwappedBean1 { public String f; public SometimesSwappedBean1(String f) { @@ -389,7 +389,7 @@ public class ReaderObjectSwapTest extends ComboSerializeTest { } } - @Pojo(swap=SometimesSwappedBeanSwap2.class) + @Swap(SometimesSwappedBeanSwap2.class) public static class SometimesSwappedBean2 { public String f; public SometimesSwappedBean2(String f) { http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/SwapsAnnotationComboTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/SwapsAnnotationComboTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/SwapsAnnotationComboTest.java new file mode 100644 index 0000000..c873ebe --- /dev/null +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/transforms/SwapsAnnotationComboTest.java @@ -0,0 +1,478 @@ +// *************************************************************************************************************************** +// * 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.transforms; + +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.annotation.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.transform.*; +import org.junit.runner.*; +import org.junit.runners.*; + +/** + * Exhaustive serialization tests for the CalendarSwap class. + */ +@RunWith(Parameterized.class) +@SuppressWarnings({"javadoc"}) +public class SwapsAnnotationComboTest extends ComboSerializeTest { + + @Parameterized.Parameters + public static Collection<Object[]> getParameters() { + return Arrays.asList(new Object[][] { + { /* 0 */ + new ComboInput<TestMediaTypeLiterals>( + "TestMediaTypeLiterals", + TestMediaTypeLiterals.class, + new TestMediaTypeLiterals(), + /* Json */ "'JSON'", + /* JsonT */ "'JSON'", + /* JsonR */ "'JSON'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>HTML</string>", + /* HtmlT */ "<string>HTML</string>", + /* HtmlR */ "<string>HTML</string>", + /* Uon */ "UON", + /* UonT */ "UON", + /* UonR */ "UON", + /* UrlEnc */ "_value=URLENCODING", + /* UrlEncT */ "_value=URLENCODING", + /* UrlEncR */ "_value=URLENCODING", + /* MsgPack */ "A74D53475041434B", + /* MsgPackT */ "A74D53475041434B", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>RDFXML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 1 */ + new ComboInput<TestMediaTypePatterns>( + "TestMediaTypePatterns", + TestMediaTypePatterns.class, + new TestMediaTypePatterns(), + /* Json */ "'JSON'", + /* JsonT */ "'JSON'", + /* JsonR */ "'JSON'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>HTML</string>", + /* HtmlT */ "<string>HTML</string>", + /* HtmlR */ "<string>HTML</string>", + /* Uon */ "UON", + /* UonT */ "UON", + /* UonR */ "UON", + /* UrlEnc */ "_value=URLENCODING", + /* UrlEncT */ "_value=URLENCODING", + /* UrlEncR */ "_value=URLENCODING", + /* MsgPack */ "A74D53475041434B", + /* MsgPackT */ "A74D53475041434B", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>RDFXML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 2 */ + new ComboInput<TestMediaTypePatternsReversed>( + "TestMediaTypePatternsReversed", + TestMediaTypePatternsReversed.class, + new TestMediaTypePatternsReversed(), + /* Json */ "'JSON'", + /* JsonT */ "'JSON'", + /* JsonR */ "'JSON'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>HTML</string>", + /* HtmlT */ "<string>HTML</string>", + /* HtmlR */ "<string>HTML</string>", + /* Uon */ "UON", + /* UonT */ "UON", + /* UonR */ "UON", + /* UrlEnc */ "_value=URLENCODING", + /* UrlEncT */ "_value=URLENCODING", + /* UrlEncR */ "_value=URLENCODING", + /* MsgPack */ "A74D53475041434B", + /* MsgPackT */ "A74D53475041434B", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>RDFXML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 3 */ + new ComboInput<TestMediaTypePatternsMulti>( + "TestMediaTypePatternsMulti", + TestMediaTypePatternsMulti.class, + new TestMediaTypePatternsMulti(), + /* Json */ "'JSON'", + /* JsonT */ "'JSON'", + /* JsonR */ "'JSON'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>HTML</string>", + /* HtmlT */ "<string>HTML</string>", + /* HtmlR */ "<string>HTML</string>", + /* Uon */ "UON", + /* UonT */ "UON", + /* UonR */ "UON", + /* UrlEnc */ "_value=URLENCODING", + /* UrlEncT */ "_value=URLENCODING", + /* UrlEncR */ "_value=URLENCODING", + /* MsgPack */ "A74D53475041434B", + /* MsgPackT */ "A74D53475041434B", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>RDFXML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 4 */ + // In this case, "text/xml" should NOT match "text/xml+rdf". + new ComboInput<TestMediaTypePatternsPartial1>( + "TestMediaTypePatternsPartial1", + TestMediaTypePatternsPartial1.class, + new TestMediaTypePatternsPartial1(), + /* Json */ "'JSON'", + /* JsonT */ "'JSON'", + /* JsonR */ "'JSON'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>HTML</string>", + /* HtmlT */ "<string>HTML</string>", + /* HtmlR */ "<string>HTML</string>", + /* Uon */ "foo", + /* UonT */ "foo", + /* UonR */ "foo", + /* UrlEnc */ "_value=foo", + /* UrlEncT */ "_value=foo", + /* UrlEncR */ "_value=foo", + /* MsgPack */ "A3666F6F", + /* MsgPackT */ "A3666F6F", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>foo</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>foo</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>foo</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 5 */ + // In this case, "text/xml+rdf" should NOT match "text/xml". + new ComboInput<TestMediaTypePatternsPartial2>( + "TestMediaTypePatternsPartial2", + TestMediaTypePatternsPartial2.class, + new TestMediaTypePatternsPartial2(), + /* Json */ "'foo'", + /* JsonT */ "'foo'", + /* JsonR */ "'foo'", + /* Xml */ "<string>foo</string>", + /* XmlT */ "<string>foo</string>", + /* XmlR */ "<string>foo</string>\n", + /* XmlNs */ "<string>foo</string>", + /* Html */ "<string>foo</string>", + /* HtmlT */ "<string>foo</string>", + /* HtmlR */ "<string>foo</string>", + /* Uon */ "UON", + /* UonT */ "UON", + /* UonR */ "UON", + /* UrlEnc */ "_value=URLENCODING", + /* UrlEncT */ "_value=URLENCODING", + /* UrlEncR */ "_value=URLENCODING", + /* MsgPack */ "A74D53475041434B", + /* MsgPackT */ "A74D53475041434B", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>RDFXML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>RDFXML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 6 */ + // In this case, "text/xml+*" should match both the XML and RDF serializers. + new ComboInput<TestMediaTypePatternsXmlPlus>( + "TestMediaTypePatternsXmlPlus", + TestMediaTypePatternsXmlPlus.class, + new TestMediaTypePatternsXmlPlus(), + /* Json */ "'foo'", + /* JsonT */ "'foo'", + /* JsonR */ "'foo'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>foo</string>", + /* HtmlT */ "<string>foo</string>", + /* HtmlR */ "<string>foo</string>", + /* Uon */ "foo", + /* UonT */ "foo", + /* UonR */ "foo", + /* UrlEnc */ "_value=foo", + /* UrlEncT */ "_value=foo", + /* UrlEncR */ "_value=foo", + /* MsgPack */ "A3666F6F", + /* MsgPackT */ "A3666F6F", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>XML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>XML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>XML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 7 */ + // In this case, "text/*+xml" should match both the XML and RDF serializers. + new ComboInput<TestMediaTypePatternsXmlPlusReversed>( + "TestMediaTypePatternsXmlPlusReversed", + TestMediaTypePatternsXmlPlusReversed.class, + new TestMediaTypePatternsXmlPlusReversed(), + /* Json */ "'foo'", + /* JsonT */ "'foo'", + /* JsonR */ "'foo'", + /* Xml */ "<string>XML</string>", + /* XmlT */ "<string>XML</string>", + /* XmlR */ "<string>XML</string>\n", + /* XmlNs */ "<string>XML</string>", + /* Html */ "<string>foo</string>", + /* HtmlT */ "<string>foo</string>", + /* HtmlR */ "<string>foo</string>", + /* Uon */ "foo", + /* UonT */ "foo", + /* UonR */ "foo", + /* UrlEnc */ "_value=foo", + /* UrlEncT */ "_value=foo", + /* UrlEncR */ "_value=foo", + /* MsgPack */ "A3666F6F", + /* MsgPackT */ "A3666F6F", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>XML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>XML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>XML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, + { /* 8 */ + // In this case, "text/rdf+*" should match only the RDF serializer. + new ComboInput<TestMediaTypePatternsRdfPlus>( + "TestMediaTypePatternsRdfPlus", + TestMediaTypePatternsRdfPlus.class, + new TestMediaTypePatternsRdfPlus(), + /* Json */ "'foo'", + /* JsonT */ "'foo'", + /* JsonR */ "'foo'", + /* Xml */ "<string>foo</string>", + /* XmlT */ "<string>foo</string>", + /* XmlR */ "<string>foo</string>\n", + /* XmlNs */ "<string>foo</string>", + /* Html */ "<string>foo</string>", + /* HtmlT */ "<string>foo</string>", + /* HtmlR */ "<string>foo</string>", + /* Uon */ "foo", + /* UonT */ "foo", + /* UonR */ "foo", + /* UrlEnc */ "_value=foo", + /* UrlEncT */ "_value=foo", + /* UrlEncR */ "_value=foo", + /* MsgPack */ "A3666F6F", + /* MsgPackT */ "A3666F6F", + /* RdfXml */ "<rdf:RDF>\n<rdf:Description>\n<j:value>XML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlT */ "<rdf:RDF>\n<rdf:Description>\n<j:value>XML</j:value>\n</rdf:Description>\n</rdf:RDF>\n", + /* RdfXmlR */ "<rdf:RDF>\n <rdf:Description>\n <j:value>XML</j:value>\n </rdf:Description>\n</rdf:RDF>\n" + ) + }, +// { /* 0 */ +// new ComboInput<byte[]>( +// "ByteArray1d", +// byte[].class, +// new byte[] {1,2,3}, +// /* Json */ "xxx", +// /* JsonT */ "xxx", +// /* JsonR */ "xxx", +// /* Xml */ "xxx", +// /* XmlT */ "xxx", +// /* XmlR */ "xxx", +// /* XmlNs */ "xxx", +// /* Html */ "xxx", +// /* HtmlT */ "xxx", +// /* HtmlR */ "xxx", +// /* Uon */ "xxx", +// /* UonT */ "xxx", +// /* UonR */ "xxx", +// /* UrlEnc */ "xxx", +// /* UrlEncT */ "xxx", +// /* UrlEncR */ "xxx", +// /* MsgPack */ "xxx", +// /* MsgPackT */ "xxx", +// /* RdfXml */ "xxx", +// /* RdfXmlT */ "xxx", +// /* RdfXmlR */ "xxx" +// ) +// }, + }); + } + + public SwapsAnnotationComboTest(ComboInput<?> comboInput) { + super(comboInput); + } + + @Override + protected Serializer applySettings(Serializer s) throws Exception { + return s.builder().pojoSwaps(ByteArrayBase64Swap.class).trimNullProperties(false).build(); + } + + @Swaps( + { + @Swap(value=SwapJson.class, mediaTypes={"application/json"}), + @Swap(value=SwapXml.class, mediaTypes={"text/xml"}), + @Swap(value=SwapHtml.class, mediaTypes={"text/html"}), + @Swap(value=SwapUon.class, mediaTypes={"text/uon"}), + @Swap(value=SwapUrlEncoding.class, mediaTypes={"application/x-www-form-urlencoded"}), + @Swap(value=SwapMsgPack.class, mediaTypes={"octal/msgpack"}), + @Swap(value=SwapRdfXml.class, mediaTypes={"text/xml+rdf"}), + } + ) + public static class TestMediaTypeLiterals {} + + @Swaps( + { + @Swap(value=SwapJson.class, mediaTypes={"*/json"}), + @Swap(value=SwapXml.class, mediaTypes={"*/xml"}), + @Swap(value=SwapHtml.class, mediaTypes={"*/html"}), + @Swap(value=SwapUon.class, mediaTypes={"*/uon"}), + @Swap(value=SwapUrlEncoding.class, mediaTypes={"*/x-www-form-urlencoded"}), + @Swap(value=SwapMsgPack.class, mediaTypes={"*/msgpack"}), + @Swap(value=SwapRdfXml.class, mediaTypes={"*/xml+rdf"}), + } + ) + public static class TestMediaTypePatterns {} + + @Swaps( + { + @Swap(value=SwapRdfXml.class, mediaTypes={"*/xml+rdf"}), + @Swap(value=SwapMsgPack.class, mediaTypes={"*/msgpack"}), + @Swap(value=SwapUrlEncoding.class, mediaTypes={"*/x-www-form-urlencoded"}), + @Swap(value=SwapUon.class, mediaTypes={"*/uon"}), + @Swap(value=SwapHtml.class, mediaTypes={"*/html"}), + @Swap(value=SwapXml.class, mediaTypes={"*/xml"}), + @Swap(value=SwapJson.class, mediaTypes={"*/json"}), + } + ) + public static class TestMediaTypePatternsReversed {} + + @Swaps( + { + @Swap(value=SwapJson.class, mediaTypes={"*/foo","*/json","*/bar"}), + @Swap(value=SwapXml.class, mediaTypes={"*/foo","*/xml","*/bar"}), + @Swap(value=SwapHtml.class, mediaTypes={"*/foo","*/html","*/bar"}), + @Swap(value=SwapUon.class, mediaTypes={"*/foo","*/uon","*/bar"}), + @Swap(value=SwapUrlEncoding.class, mediaTypes={"*/foo","*/x-www-form-urlencoded","*/bar"}), + @Swap(value=SwapMsgPack.class, mediaTypes={"*/foo","*/msgpack","*/bar"}), + @Swap(value=SwapRdfXml.class, mediaTypes={"*/foo","*/xml+rdf","*/bar"}), + } + ) + public static class TestMediaTypePatternsMulti {} + + @Swaps( + { + @Swap(value=SwapJson.class, mediaTypes={"*/foo","*/json","*/bar"}), + @Swap(value=SwapXml.class, mediaTypes={"*/foo","*/xml","*/bar"}), + @Swap(value=SwapHtml.class, mediaTypes={"*/foo","*/html","*/bar"}), + } + ) + public static class TestMediaTypePatternsPartial1 { + public String toString() { + return "foo"; + } + } + + @Swaps( + { + @Swap(value=SwapUon.class, mediaTypes={"*/foo","*/uon","*/bar"}), + @Swap(value=SwapUrlEncoding.class, mediaTypes={"*/foo","*/x-www-form-urlencoded","*/bar"}), + @Swap(value=SwapMsgPack.class, mediaTypes={"*/foo","*/msgpack","*/bar"}), + @Swap(value=SwapRdfXml.class, mediaTypes={"*/foo","*/xml+rdf","*/bar"}), + } + ) + public static class TestMediaTypePatternsPartial2 { + public String toString() { + return "foo"; + } + } + + @Swaps( + { + @Swap(value=SwapXml.class, mediaTypes={"text/xml+*"}), + } + ) + public static class TestMediaTypePatternsXmlPlus { + public String toString() { + return "foo"; + } + } + + @Swaps( + { + @Swap(value=SwapXml.class, mediaTypes={"text/*+xml"}), + } + ) + public static class TestMediaTypePatternsXmlPlusReversed { + public String toString() { + return "foo"; + } + } + + @Swaps( + { + @Swap(value=SwapXml.class, mediaTypes={"text/rdf+*"}), + } + ) + public static class TestMediaTypePatternsRdfPlus { + public String toString() { + return "foo"; + } + } + + public static class SwapJson extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "JSON"; + } + } + public static class SwapXml extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "XML"; + } + } + public static class SwapHtml extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "HTML"; + } + } + public static class SwapUon extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "UON"; + } + } + public static class SwapUrlEncoding extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "URLENCODING"; + } + } + public static class SwapMsgPack extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "MSGPACK"; + } + } + public static class SwapRdfXml extends PojoSwap { + public Object swap(BeanSession session, Object o) throws Exception { + return "RDFXML"; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java index 267d06f..04e779f 100644 --- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java +++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java @@ -228,8 +228,8 @@ public class RdfParserSession 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); if (! sType.canCreateNewInstance(outer)) { @@ -341,8 +341,8 @@ public class RdfParserSession extends ReaderParserSession { throw new ParseException("Class ''{0}'' could not be instantiated. Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason()); } - 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-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java index 0f66237..9c0e701 100644 --- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java +++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java @@ -206,12 +206,13 @@ public final class RdfSerializerSession extends WriterSerializerSession { 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. @@ -219,7 +220,7 @@ public final class RdfSerializerSession extends WriterSerializerSession { sType = getClassMetaForObject(o); } } else { - sType = eType.getSerializedClassMeta(); + sType = eType.getSerializedClassMeta(this); } String typeName = getBeanTypeName(eType, aType, bpm); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java index c550408..5464f52 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java @@ -210,7 +210,7 @@ public class BeanPropertyMeta { return false; if (typeMeta == null) - typeMeta = (swap != null ? swap.getSwapClassMeta(beanContext) : rawTypeMeta == null ? beanContext.object() : rawTypeMeta.getSerializedClassMeta()); + typeMeta = (swap != null ? beanContext.getClassMeta(swap.getSwapClass()) : rawTypeMeta == null ? beanContext.object() : rawTypeMeta); if (typeMeta == null) typeMeta = rawTypeMeta; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java index bad3d38..64d165c 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java @@ -357,19 +357,19 @@ public class BeanSession extends Session { if (tc == Class.class) return (T)(ctx.classLoader.loadClass(value.toString())); - if (type.getPojoSwap() != null) { - PojoSwap f = type.getPojoSwap(); - Class<?> nc = f.getNormalClass(), fc = f.getSwapClass(); + PojoSwap swap = type.getPojoSwap(this); + if (swap != null) { + Class<?> nc = swap.getNormalClass(), fc = swap.getSwapClass(); if (isParentClass(nc, tc) && isParentClass(fc, value.getClass())) - return (T)f.unswap(this, value, type); + return (T)swap.unswap(this, value, type); } ClassMeta<?> vt = ctx.getClassMetaForObject(value); - if (vt.getPojoSwap() != null) { - PojoSwap f = vt.getPojoSwap(); - Class<?> nc = f.getNormalClass(), fc = f.getSwapClass(); + swap = vt.getPojoSwap(this); + if (swap != null) { + Class<?> nc = swap.getNormalClass(), fc = swap.getSwapClass(); if (isParentClass(nc, vt.getInnerClass()) && isParentClass(fc, tc)) - return (T)f.swap(this, value); + return (T)swap.swap(this, value); } if (type.isPrimitive()) { http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java index 0e1bd72..036c4ae 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java @@ -22,10 +22,12 @@ import java.lang.reflect.Proxy; import java.net.*; import java.net.URI; import java.util.*; +import java.util.Date; import java.util.concurrent.*; import java.util.concurrent.locks.*; import org.apache.juneau.annotation.*; +import org.apache.juneau.http.*; import org.apache.juneau.internal.*; import org.apache.juneau.parser.*; import org.apache.juneau.remoteable.*; @@ -93,12 +95,11 @@ public final class ClassMeta<T> implements Type { private final ConcurrentHashMap<Class<?>,PojoSwap<?,?>> childSwapMap, // Maps normal subclasses to PojoSwaps. childUnswapMap; // Maps swap subclasses to PojoSwaps. - private final PojoSwap<T,?> pojoSwap; // The object POJO swap associated with this bean (if it has one). + private final PojoSwap<T,?>[] pojoSwaps; // The object POJO swaps associated with this bean (if it has any). private final BeanFilter beanFilter; // The bean filter associated with this bean (if it has one). private final MetadataMap extMeta; // Extended metadata private final BeanContext beanContext; // The bean context that created this object. private final ClassMeta<?> - serializedClassMeta, // The transformed class type (if class has swap associated with it). elementType, // If ARRAY or COLLECTION, the element class type. keyType, // If MAP, the key class type. valueType; // If MAP, the value class type. @@ -167,7 +168,7 @@ public final class ClassMeta<T> implements Type { this.publicMethods = builder.publicMethods; this.remoteableMethods = builder.remoteableMethods; this.beanFilter = beanFilter; - this.pojoSwap = builder.pojoSwap; + this.pojoSwaps = builder.pojoSwaps.isEmpty() ? null : builder.pojoSwaps.toArray(new PojoSwap[builder.pojoSwaps.size()]); this.extMeta = new MetadataMap(); this.keyType = builder.keyType; this.valueType = builder.valueType; @@ -177,7 +178,6 @@ public final class ClassMeta<T> implements Type { this.initException = builder.initException; this.typePropertyName = builder.typePropertyName; this.dictionaryName = builder.dictionaryName; - this.serializedClassMeta = builder.serializedClassMeta; this.invocationHandler = builder.invocationHandler; this.beanRegistry = builder.beanRegistry; this.isMemberClass = builder.isMemberClass; @@ -231,7 +231,6 @@ public final class ClassMeta<T> implements Type { this.remoteableMethods = mainType.remoteableMethods; this.publicMethods = mainType.publicMethods; this.beanContext = mainType.beanContext; - this.serializedClassMeta = this; this.elementType = elementType; this.keyType = keyType; this.valueType = valueType; @@ -240,7 +239,7 @@ public final class ClassMeta<T> implements Type { this.typePropertyName = mainType.typePropertyName; this.dictionaryName = mainType.dictionaryName; this.notABeanReason = mainType.notABeanReason; - this.pojoSwap = mainType.pojoSwap; + this.pojoSwaps = mainType.pojoSwaps; this.beanFilter = mainType.beanFilter; this.extMeta = mainType.extMeta; this.initException = mainType.initException; @@ -278,7 +277,6 @@ public final class ClassMeta<T> implements Type { this.remoteableMethods = null; this.publicMethods = null; this.beanContext = null; - this.serializedClassMeta = this; this.elementType = null; this.keyType = null; this.valueType = null; @@ -287,7 +285,7 @@ public final class ClassMeta<T> implements Type { this.typePropertyName = null; this.dictionaryName = null; this.notABeanReason = null; - this.pojoSwap = null; + this.pojoSwaps = null; this.beanFilter = null; this.extMeta = new MetadataMap(); this.initException = null; @@ -334,7 +332,7 @@ public final class ClassMeta<T> implements Type { dictionaryName = null; Throwable initException = null; BeanMeta beanMeta = null; - PojoSwap pojoSwap = null; + List<PojoSwap> pojoSwaps = new ArrayList<PojoSwap>(); InvocationHandler invocationHandler = null; BeanRegistry beanRegistry = null; PojoSwap<?,?>[] childPojoSwaps; @@ -557,33 +555,36 @@ public final class ClassMeta<T> implements Type { final Method fSwapMethod = swapMethod; final Method fUnswapMethod = unswapMethod; final Constructor<T> fSwapConstructor = swapConstructor; - this.pojoSwap = new PojoSwap<T,Object>(c, swapMethod.getReturnType()) { - @Override - public Object swap(BeanSession session, Object o) throws SerializeException { - try { - return fSwapMethod.invoke(o, session); - } catch (Exception e) { - throw new SerializeException(e); + this.pojoSwaps.add( + new PojoSwap<T,Object>(c, swapMethod.getReturnType()) { + @Override + public Object swap(BeanSession session, Object o) throws SerializeException { + try { + return fSwapMethod.invoke(o, session); + } catch (Exception e) { + throw new SerializeException(e); + } } - } - @Override - public T unswap(BeanSession session, Object f, ClassMeta<?> hint) throws ParseException { - try { - if (fUnswapMethod != null) - return (T)fUnswapMethod.invoke(null, session, f); - if (fSwapConstructor != null) - return fSwapConstructor.newInstance(f); - return super.unswap(session, f, hint); - } catch (Exception e) { - throw new ParseException(e); + @Override + public T unswap(BeanSession session, Object f, ClassMeta<?> hint) throws ParseException { + try { + if (fUnswapMethod != null) + return (T)fUnswapMethod.invoke(null, session, f); + if (fSwapConstructor != null) + return fSwapConstructor.newInstance(f); + return super.unswap(session, f, hint); + } catch (Exception e) { + throw new ParseException(e); + } } } - }; + ); } - if (this.pojoSwap == null) - this.pojoSwap = findPojoSwap(); - if (this.pojoSwap == null) - this.pojoSwap = pojoSwap; + + if (pojoSwap != null) + this.pojoSwaps.add(pojoSwap); + + findPojoSwaps(this.pojoSwaps); try { @@ -644,7 +645,7 @@ public final class ClassMeta<T> implements Type { if (beanMeta != null) dictionaryName = beanMeta.getDictionaryName(); - serializedClassMeta = (this.pojoSwap == null ? ClassMeta.this : findClassMeta(this.pojoSwap.getSwapClass())); + serializedClassMeta = (this.pojoSwaps.isEmpty() ? ClassMeta.this : findClassMeta(this.pojoSwaps.get(0).getSwapClass())); if (serializedClassMeta == null) serializedClassMeta = ClassMeta.this; @@ -667,17 +668,23 @@ public final class ClassMeta<T> implements Type { return null; } - private PojoSwap<T,?> findPojoSwap() { - Pojo p = innerClass.getAnnotation(Pojo.class); - if (p != null) { - Class<?> c = p.swap(); - if (c != Null.class) { - if (isParentClass(PojoSwap.class, c)) - return ClassUtils.newInstance(PojoSwap.class, c); - throw new RuntimeException("TODO - Surrogate classes not yet supported."); - } - } - return null; + private void findPojoSwaps(List<PojoSwap> l) { + Swap swap = innerClass.getAnnotation(Swap.class); + if (swap != null) + l.add(createPojoSwap(swap)); + Swaps swaps = innerClass.getAnnotation(Swaps.class); + if (swaps != null) + for (Swap s : swaps.value()) + l.add(createPojoSwap(s)); + } + + private PojoSwap<T,?> createPojoSwap(Swap s) { + Class<?> c = s.value(); + + if (! isParentClass(PojoSwap.class, c)) + throw new FormattedRuntimeException("Invalid swap class ''{0}'' specified. Must extend from PojoSwap.", c); + + return ClassUtils.newInstance(PojoSwap.class, c).forMediaTypes(MediaType.forStrings(s.mediaTypes())).withTemplate(s.template()); } private ClassMeta<?> findClassMeta(Class<?> c) { @@ -866,11 +873,15 @@ public final class ClassMeta<T> implements Type { /** * Returns the serialized (swapped) form of this class if there is an {@link PojoSwap} associated with it. * + * @param session + * The bean session. + * <br>Required because the swap used may depend on the media type being serialized or parsed. * @return The serialized class type, or this object if no swap is associated with the class. */ @BeanIgnore - public ClassMeta<?> getSerializedClassMeta() { - return serializedClassMeta; + public ClassMeta<?> getSerializedClassMeta(BeanSession session) { + PojoSwap<T,?> ps = getPojoSwap(session); + return (ps == null ? this : ps.getSwapClassMeta(session)); } /** @@ -1226,14 +1237,32 @@ public final class ClassMeta<T> implements Type { } /** - * Returns the {@link PojoSwap} associated with this class. + * Returns the {@link PojoSwap} associated with this class that's the best match for the specified session. * + * @param session + * The current bean session. + * <br>If multiple swaps are associated with a class, only the first one with a matching media type will + * be returned. * @return - * The {@link PojoSwap} associated with this class, or <jk>null</jk> if there is no POJO swap associated with + * The {@link PojoSwap} associated with this class, or <jk>null</jk> if there are no POJO swaps associated with * this class. */ - public PojoSwap<T,?> getPojoSwap() { - return pojoSwap; + public PojoSwap<T,?> getPojoSwap(BeanSession session) { + if (pojoSwaps != null) { + int matchQuant = 0, matchIndex = -1; + + for (int i = 0; i < pojoSwaps.length; i++) { + int q = pojoSwaps[i].match(session); + if (q > matchQuant) { + matchQuant = q; + matchIndex = i; + } + } + + if (matchIndex > -1) + return pojoSwaps[matchIndex]; + } + return null; } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Pojo.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Pojo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Pojo.java deleted file mode 100644 index 0823e6d..0000000 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Pojo.java +++ /dev/null @@ -1,84 +0,0 @@ -// *************************************************************************************************************************** -// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * -// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * -// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * -// * with the License. You may obtain a copy of the License at * -// * * -// * http://www.apache.org/licenses/LICENSE-2.0 * -// * * -// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * -// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * -// * specific language governing permissions and limitations under the License. * -// *************************************************************************************************************************** -package org.apache.juneau.annotation; - -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.*; - -import java.lang.annotation.*; - -import org.apache.juneau.transform.*; - -/** - * Used to tailor how POJOs get interpreted by the framework. - */ -@Documented -@Target(TYPE) -@Retention(RUNTIME) -@Inherited -public @interface Pojo { - - /** - * Associate a {@link PojoSwap} or {@link SurrogateSwap} with this class type. - * - * <p> - * Supports the following class types: - * <ul> - * <li>Subclasses of {@link PojoSwap}. - * <li>Any other class. Will get interpreted as a {@link SurrogateSwap}. - * </ul> - * - * <h5 class='section'>Example:</h5> - * <p> - * In this case, a swap is being applied to a bean that will force it to be serialized as a <code>String</code>: - * <p class='bcode'> - * <jc>// Our bean class</jc> - * <ja>@Pojo</ja>(swap=BSwap.<jk>class</jk>) - * <jk>public class</jk> B { - * <jk>public</jk> String <jf>f1</jf>; - * } - * - * <jc>// Our POJO swap to force the bean to be serialized as a String</jc> - * <jk>public class</jk> BSwap <jk>extends</jk> PojoSwap<B,String> { - * <jk>public</jk> String swap(BeanSession s, B o) <jk>throws</jk> SerializeException { - * <jk>return</jk> o.f1; - * } - * <jk>public</jk> B unswap(BeanSession s, String f) <jk>throws</jk> ParseException { { - * B b1 = <jk>new</jk> B(); - * b1.<jf>f1</jf> = f; - * <jk>return</jk> b1; - * } - * } - * - * <jk>public void</jk> test() <jk>throws</jk> Exception { - * WriterSerializer s = JsonSerializer.<jsf>DEFAULT</jsf>; - * B b = <jk>new</jk> B(); - * b.<jf>f1</jf> = <js>"bar"</js>; - * String json = s.serialize(b); - * <jsm>assertEquals</jsm>(<js>"\"bar\""</js>, json); - * - * ReaderParser p = JsonParser.<jsf>DEFAULT</jsf>; - * b = p.parse(json, B.<jk>class</jk>); - * <jsm>assertEquals</jsm>(<js>"bar"</js>, b.<jf>f1</jf>); - * } - * </p> - * - * <p> - * Note that using this annotation is functionally equivalent to adding swaps to the serializers and parsers: - * <p class='bcode'> - * WriterSerializer s = <jk>new</jk> JsonSerializerBuilder().pojoSwaps(BSwap.<jk>class</jk>).build(); - * ReaderParser p = <jk>new</jk> JsonParserBuilder().pojoSwaps(BSwap.<jk>class</jk>).build(); - * </p> - */ - Class<?> swap() default Null.class; -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swap.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swap.java new file mode 100644 index 0000000..1daa3e9 --- /dev/null +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swap.java @@ -0,0 +1,31 @@ +// *************************************************************************************************************************** +// * 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.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +@Documented +@Target({TYPE,ANNOTATION_TYPE}) +@Retention(RUNTIME) +@Inherited +public @interface Swap { + + Class<?> value() default Null.class; + + String template() default ""; + + String[] mediaTypes() default {}; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swaps.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swaps.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swaps.java new file mode 100644 index 0000000..4795ce8 --- /dev/null +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Swaps.java @@ -0,0 +1,27 @@ +// *************************************************************************************************************************** +// * 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.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +@Documented +@Target({TYPE,ANNOTATION_TYPE}) +@Retention(RUNTIME) +@Inherited +public @interface Swaps { + + Swap[] value() default {}; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java index 376843a..975cae4 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java @@ -83,8 +83,8 @@ public final class HtmlParserSession extends XmlParserSession { if (eType == null) eType = (ClassMeta<T>)object(); - PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(); - ClassMeta<?> sType = eType.getSerializedClassMeta(); + PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap(this); + ClassMeta<?> sType = transform == null ? eType : transform.getSwapClassMeta(this); setCurrentClass(sType); int event = r.getEventType(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java index 27f020a..847b40d 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java @@ -68,7 +68,7 @@ public class HtmlSchemaDocSerializerSession extends HtmlDocSerializerSession { aType = push(attrName, eType, null); - sType = eType.getSerializedClassMeta(); + sType = eType.getSerializedClassMeta(this); String type = null; if (sType.isEnum() || sType.isCharSequence() || sType.isChar()) @@ -86,7 +86,7 @@ public class HtmlSchemaDocSerializerSession extends HtmlDocSerializerSession { out.put("type", type); out.put("class", eType.toString()); - PojoSwap t = eType.getPojoSwap(); + PojoSwap t = eType.getPojoSwap(this); if (t != null) out.put("transform", t); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java index 8cbbb83..3f1f1fd 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java @@ -263,15 +263,17 @@ public class HtmlSerializerSession extends XmlSerializerSession { aType = ((Delegate)o).getClassMeta(); } - sType = aType.getSerializedClassMeta(); + sType = aType; + String typeName = null; if (isAddBeanTypeProperties() && ! eType.equals(aType)) typeName = aType.getDictionaryName(); // 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. @@ -564,10 +566,10 @@ public class HtmlSerializerSession extends XmlSerializerSession { for (Object o : c) { ClassMeta<?> cm = getClassMetaForObject(o); - if (cm != null && cm.getPojoSwap() != null) { - PojoSwap f = cm.getPojoSwap(); - o = f.swap(this, o); - cm = cm.getSerializedClassMeta(); + if (cm != null && cm.getPojoSwap(this) != null) { + PojoSwap swap = cm.getPojoSwap(this); + o = swap.swap(this, o); + cm = swap.getSwapClassMeta(this); } out.oTag(i+1, "tr"); @@ -705,11 +707,13 @@ public class HtmlSerializerSession extends XmlSerializerSession { if (o1 == null) return null; ClassMeta<?> cm = getClassMetaForObject(o1); - if (cm.getPojoSwap() != null) { - PojoSwap f = cm.getPojoSwap(); - o1 = f.swap(this, o1); - cm = cm.getSerializedClassMeta(); + + PojoSwap swap = cm.getPojoSwap(this); + if (swap != null) { + o1 = swap.swap(this, o1); + cm = swap.getSwapClassMeta(this); } + if (cm == null || ! cm.isMapOrBean()) return null; if (cm.getInnerClass().isAnnotationPresent(HtmlLink.class)) @@ -767,10 +771,11 @@ public class HtmlSerializerSession extends XmlSerializerSession { if (o == null) continue; cm = getClassMetaForObject(o); - if (cm != null && cm.getPojoSwap() != null) { - PojoSwap f = cm.getPojoSwap(); - o = f.swap(this, o); - cm = cm.getSerializedClassMeta(); + + PojoSwap ps = cm == null ? null : cm.getPojoSwap(this); + if (ps != null) { + o = ps.swap(this, o); + cm = ps.getSwapClassMeta(this); } if (prevC.contains(cm)) continue; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java index 4ea7bec..5b5c64f 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java @@ -219,7 +219,8 @@ public final class Accept { for (int i = 0; i < mediaTypes.length; i++) { MediaType mt = mediaTypes[i]; - int matchQuant2 = mt.match(mr.getMediaType()); + int matchQuant2 = mr.getMediaType().match(mt, false); + if (matchQuant2 > matchQuant) { matchIndex = i; matchQuant = matchQuant2; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/495c648d/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentType.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentType.java index 05a4f3e..5bcc4ed 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentType.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentType.java @@ -95,7 +95,7 @@ public class ContentType extends MediaType { for (int i = 0; i < mediaTypes.length; i++) { MediaType mt = mediaTypes[i]; - int matchQuant2 = mt.match(this); + int matchQuant2 = mt.match(this, true); if (matchQuant2 > matchQuant) { matchQuant = matchQuant2; matchIndex = i;
