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