View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.a.rttests;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.util.*;
23  
24  import org.apache.juneau.*;
25  import org.apache.juneau.annotation.*;
26  import org.apache.juneau.html.*;
27  import org.apache.juneau.json.*;
28  import org.apache.juneau.msgpack.*;
29  import org.apache.juneau.uon.*;
30  import org.apache.juneau.urlencoding.*;
31  import org.apache.juneau.xml.*;
32  import org.junit.jupiter.params.*;
33  import org.junit.jupiter.params.provider.*;
34  
35  /**
36   * Tests designed to serialize and parse objects to make sure we end up
37   * with the same objects for all serializers and parsers.
38   */
39  class RoundTripAddClassAttrs_Test extends TestBase {
40  
41  	private static RoundTrip_Tester[] TESTERS = {
42  		tester(1, "JsonSerializer.DEFAULT/JsonParser.DEFAULT")
43  			.serializer(JsonSerializer.create().addBeanTypes().addRootType())
44  			.parser(JsonParser.create().disableInterfaceProxies())
45  			.build(),
46  		tester(2, "JsonSerializer.DEFAULT_SIMPLE/JsonParser.DEFAULT")
47  			.serializer(JsonSerializer.create().json5().addBeanTypes().addRootType())
48  			.parser(JsonParser.create().disableInterfaceProxies())
49  			.build(),
50  		tester(3, "JsonSerializer.DEFAULT_SQ/JsonParser.DEFAULT")
51  			.serializer(JsonSerializer.create().json5().addBeanTypes().addRootType())
52  			.parser(JsonParser.create().disableInterfaceProxies())
53  			.build(),
54  		tester(4, "XmlSerializer.DEFAULT/XmlParser.DEFAULT")
55  			.serializer(XmlSerializer.create().addBeanTypes().addRootType())
56  			.parser(XmlParser.create().disableInterfaceProxies())
57  			.validateXmlWhitespace()
58  			.validateXml()
59  			.build(),
60  		tester(5, "HtmlSerializer.DEFAULT/HtmlParser.DEFAULT")
61  			.serializer(HtmlSerializer.create().addBeanTypes().addRootType())
62  			.parser(HtmlParser.create().disableInterfaceProxies())
63  			.validateXmlWhitespace()
64  			.build(),
65  		tester(6, "UonSerializer.DEFAULT_ENCODING/UonParser.DEFAULT_DECODING")
66  			.serializer(UonSerializer.create().encoding().addBeanTypes().addRootType())
67  			.parser(UonParser.create().decoding().disableInterfaceProxies())
68  			.build(),
69  		tester(7, "UonSerializer.DEFAULT/UonParser.DEFAULT")
70  			.serializer(UonSerializer.create().addBeanTypes().addRootType())
71  			.parser(UonParser.create().disableInterfaceProxies())
72  			.build(),
73  		tester(8, "UrlEncodingSerializer.DEFAULT/UrlEncodingParser.DEFAULT")
74  			.serializer(UrlEncodingSerializer.create().addBeanTypes().addRootType())
75  			.parser(UrlEncodingParser.create().disableInterfaceProxies())
76  			.build(),
77  		tester(9, "MsgPackSerializer.DEFAULT/MsgPackParser.DEFAULT")
78  			.serializer(MsgPackSerializer.create().addBeanTypes().addRootType())
79  			.parser(MsgPackParser.create().disableInterfaceProxies())
80  			.build()
81  	};
82  
83  	static RoundTrip_Tester[]  testers() {
84  		return TESTERS;
85  	}
86  
87  	protected static RoundTrip_Tester.Builder tester(int index, String label) {
88  		return RoundTrip_Tester.create(index, label).dictionary(A.class, B.class, C.class, D.class, E.class, F.class);
89  	}
90  
91  	//====================================================================================================
92  	// testBean
93  	//====================================================================================================
94  
95  	@ParameterizedTest
96  	@MethodSource("testers")
97  	void a01_bean(RoundTrip_Tester t) throws Exception {
98  		var x = new A("foo");
99  
100 		x = t.roundTrip(x, A.class);
101 		assertEquals("foo", x.getF1());
102 
103 		var xa = t.roundTrip(x, AA.class);
104 		assertEquals("foo", xa.getF1());
105 
106 		var xi = t.roundTrip(x, IA.class);
107 		assertEquals("foo", xi.getF1());
108 
109 		x = t.roundTrip(x, Object.class);
110 		assertEquals("foo", x.getF1());
111 	}
112 
113 	public interface IA {
114 		String getF1();
115 		void setF1(String f1);
116 	}
117 
118 	public abstract static class AA implements IA {}
119 
120 	@Bean(typeName="A")
121 	public static class A extends AA {
122 		private String f1;
123 
124 		@Override /* AA */ public String getF1() { return f1; }
125 		@Override /* AA */ public void setF1(String v) { f1 = v; }
126 
127 		public A() {}
128 		public A(String f1) {
129 			this.f1 = f1;
130 		}
131 	}
132 
133 	//====================================================================================================
134 	// testBeanArray
135 	//====================================================================================================
136 
137 	@ParameterizedTest
138 	@MethodSource("testers")
139 	void a02_beanArray(RoundTrip_Tester t) throws Exception {
140 		var x = a(new A("foo"));
141 
142 		x = t.roundTrip(x, A[].class);
143 		assertEquals("foo", x[0].getF1());
144 
145 		var xa = (AA[])t.roundTrip(x, AA[].class);
146 		assertEquals("foo", xa[0].getF1());
147 
148 		var xi = (IA[])t.roundTrip(x, IA[].class);
149 		assertEquals("foo", xi[0].getF1());
150 	}
151 
152 	//====================================================================================================
153 	// testBeanWithBeanProps
154 	//====================================================================================================
155 
156 	@ParameterizedTest
157 	@MethodSource("testers")
158 	void a03_beanWithBeanProps(RoundTrip_Tester t) throws Exception {
159 		var x = new B("foo");
160 		x = t.roundTrip(x, B.class);
161 		assertBean(x, "f2a{f1},f2b{f1},f2c{f1},f2d{f1}", "{foo},{foo},{foo},{foo}");
162 
163 		x = t.roundTrip(x, Object.class);
164 		assertBean(x, "f2a{f1},f2b{f1},f2c{f1},f2d{f1}", "{foo},{foo},{foo},{foo}");
165 	}
166 
167 	@Bean(typeName="B")
168 	public static class B {
169 		public A f2a;
170 		public AA f2b;
171 		public IA f2c;
172 		public Object f2d;
173 		public B() {}
174 		public B(String f1) {
175 			f2d = f2c = f2b = f2a = new A(f1);
176 		}
177 	}
178 
179 	//====================================================================================================
180 	// testMapsWithTypeParams - Maps with type parameters should not have class attributes on entries.
181 	//====================================================================================================
182 
183 	@ParameterizedTest
184 	@MethodSource("testers")
185 	void a04_mapsWithTypeParams(RoundTrip_Tester t) throws Exception {
186 		var x = new C("foo");
187 		x = t.roundTrip(x, C.class);
188 		assertBean(x, "f3a{foo{f1}},f3b{foo{f1}},f3c{foo{f1}},f3d{foo{f1}}", "{{foo}},{{foo}},{{foo}},{{foo}}");
189 
190 		x = t.roundTrip(x, Object.class);
191 		assertBean(x, "f3a{foo{f1}},f3b{foo{f1}},f3c{foo{f1}},f3d{foo{f1}}", "{{foo}},{{foo}},{{foo}},{{foo}}");
192 	}
193 
194 	@Bean(typeName="C")
195 	public static class C {
196 		public Map<String,A> f3a = new HashMap<>();
197 		public Map<String,A> f3b = new HashMap<>();
198 		public Map<String,A> f3c = new HashMap<>();
199 		public Map<String,A> f3d = new HashMap<>();
200 
201 		public C(){}
202 		public C(String f1) {
203 			var b = new A(f1);
204 			f3a.put("foo", b);
205 			f3b.put("foo", b);
206 			f3c.put("foo", b);
207 			f3d.put("foo", b);
208 		}
209 	}
210 
211 	//====================================================================================================
212 	// testMapsWithoutTypeParams - Maps without type parameters should have class attributes on entries.
213 	//====================================================================================================
214 
215 	@ParameterizedTest
216 	@MethodSource("testers")
217 	void a05_mapsWithoutTypeParams(RoundTrip_Tester t) throws Exception {
218 		var x = new D("foo");
219 		x = t.roundTrip(x, D.class);
220 		assertBean(x, "f4a{0{f1}},f4b{0{f1}},f4c{0{f1}},f4d{0{f1}}", "{{foo}},{{foo}},{{foo}},{{foo}}");
221 
222 		x = t.roundTrip(x, Object.class);
223 		assertBean(x, "f4a{0{f1}},f4b{0{f1}},f4c{0{f1}},f4d{0{f1}}", "{{foo}},{{foo}},{{foo}},{{foo}}");
224 	}
225 
226 	@Bean(typeName="D")
227 	public static class D {
228 		public A[] f4a;
229 		public AA[] f4b;
230 		public IA[] f4c;
231 		public Object[] f4d;
232 
233 		public D(){}
234 		public D(String f1) {
235 			var b = new A(f1);
236 			f4a = new A[]{b};
237 			f4b = new AA[]{b};
238 			f4c = new IA[]{b};
239 			f4d = new Object[]{b};
240 		}
241 	}
242 
243 	//====================================================================================================
244 	// testBeanWithListProps
245 	//====================================================================================================
246 
247 	@ParameterizedTest
248 	@MethodSource("testers")
249 	void a06_beanWithListProps(RoundTrip_Tester t) throws Exception {
250 		var x = new E("foo");
251 		x = t.roundTrip(x, E.class);
252 		assertBean(x, "f5a{0{f1}},f5b{0{f1}},f5c{0{f1}},f5d{0{f1}}", "{{foo}},{{foo}},{{foo}},{{foo}}");
253 
254 		x = t.roundTrip(x, Object.class);
255 		assertBean(x, "f5a{0{f1}},f5b{0{f1}},f5c{0{f1}},f5d{0{f1}}", "{{foo}},{{foo}},{{foo}},{{foo}}");
256 	}
257 
258 	@Bean(typeName="E")
259 	public static class E {
260 		public List<A> f5a = new LinkedList<>();
261 		public List<AA> f5b = new LinkedList<>();
262 		public List<IA> f5c = new LinkedList<>();
263 		public List<Object> f5d = new LinkedList<>();
264 
265 		public E(){}
266 		public E(String f1) {
267 			var b = new A(f1);
268 			f5a.add(b);
269 			f5b.add(b);
270 			f5c.add(b);
271 			f5d.add(b);
272 		}
273 	}
274 
275 	//====================================================================================================
276 	// testBeanWithListOfArraysProps
277 	//====================================================================================================
278 
279 	@ParameterizedTest
280 	@MethodSource("testers")
281 	void a07_beanWithListOfArraysProps(RoundTrip_Tester t) throws Exception {
282 		var x = new F("foo");
283 		x = t.roundTrip(x, F.class);
284 		assertBean(x, "f6a{0{0{f1}}},f6b{0{0{f1}}},f6c{0{0{f1}}},f6d{0{0{f1}}}", "{{{foo}}},{{{foo}}},{{{foo}}},{{{foo}}}");
285 
286 		x = t.roundTrip(x, Object.class);
287 		assertBean(x, "f6a{0{0{f1}}},f6b{0{0{f1}}},f6c{0{0{f1}}},f6d{0{0{f1}}}", "{{{foo}}},{{{foo}}},{{{foo}}},{{{foo}}}");
288 	}
289 
290 	@Bean(typeName="F")
291 	public static class F {
292 		public List<A[]> f6a = new LinkedList<>();
293 		public List<AA[]> f6b = new LinkedList<>();
294 		public List<IA[]> f6c = new LinkedList<>();
295 		public List<Object[]> f6d = new LinkedList<>();
296 
297 		public F(){}
298 		public F(String f1) {
299 			var b = a(new A(f1));
300 			f6a.add(b);
301 			f6b.add(b);
302 			f6c.add(b);
303 			f6d.add(b);
304 		}
305 	}
306 }