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.serializer;
18  
19  import static org.apache.juneau.commons.utils.AssertionUtils.*;
20  import static org.apache.juneau.commons.utils.Utils.*;
21  
22  import java.io.*;
23  import java.lang.reflect.*;
24  import java.nio.charset.*;
25  import java.util.*;
26  import java.util.function.*;
27  
28  import org.apache.juneau.*;
29  import org.apache.juneau.commons.collections.FluentMap;
30  import org.apache.juneau.httppart.*;
31  import org.apache.juneau.svl.*;
32  
33  /**
34   * Subclass of {@link SerializerSession} for character-based serializers.
35   *
36   * <h5 class='topic'>Description</h5>
37   *
38   * This class is typically the parent class of all character-based serializers.
39   * <br>It has 1 abstract method to implement...
40   * <ul class='spaced-list'>
41   * 	<li>
42   * 		{@link #doSerialize(SerializerPipe, Object)}
43   * </ul>
44   *
45   * <h5 class='section'>Notes:</h5><ul>
46   * 	<li class='warn'>This class is not thread safe and is typically discarded after one use.
47   * </ul>
48   *
49   * <h5 class='section'>See Also:</h5><ul>
50   * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
51   * </ul>
52   */
53  public class WriterSerializerSession extends SerializerSession {
54  	/**
55  	 * Builder class.
56  	 */
57  	public static class Builder extends SerializerSession.Builder {
58  
59  		private boolean useWhitespace;
60  		private Charset fileCharset;
61  		private Charset streamCharset;
62  		private WriterSerializer ctx;
63  
64  		/**
65  		 * Constructor
66  		 *
67  		 * @param ctx The context creating this session.
68  		 * 	<br>Cannot be <jk>null</jk>.
69  		 */
70  		protected Builder(WriterSerializer ctx) {
71  			super(assertArgNotNull("ctx", ctx));
72  			this.ctx = ctx;
73  			fileCharset = ctx.getFileCharset();
74  			streamCharset = ctx.getStreamCharset();
75  			useWhitespace = ctx.useWhitespace;
76  		}
77  
78  		@Override /* Overridden from Builder */
79  		public <T> Builder apply(Class<T> type, Consumer<T> apply) {
80  			super.apply(type, apply);
81  			return this;
82  		}
83  
84  		@Override
85  		public WriterSerializerSession build() {
86  			return new WriterSerializerSession(this);
87  		}
88  
89  		@Override /* Overridden from Builder */
90  		public Builder debug(Boolean value) {
91  			super.debug(value);
92  			return this;
93  		}
94  
95  		/**
96  		 * File charset.
97  		 *
98  		 * <p>
99  		 * The character set to use for writing Files to the file system.
100 		 *
101 		 * <p>
102 		 * Used when passing in files to {@link Serializer#serialize(Object, Object)}.
103 		 *
104 		 * <p>
105 		 * If not specified, defaults to the JVM system default charset.
106 		 *
107 		 * @param value
108 		 * 	The new property value.
109 		 * 	<br>Can be <jk>null</jk> (value will not be set, defaults to JVM system default charset).
110 		 * @return This object.
111 		 */
112 		public Builder fileCharset(Charset value) {
113 			if (nn(value))
114 				fileCharset = value;
115 			return this;
116 		}
117 
118 		@Override /* Overridden from Builder */
119 		public Builder javaMethod(Method value) {
120 			super.javaMethod(value);
121 			return this;
122 		}
123 
124 		@Override /* Overridden from Builder */
125 		public Builder locale(Locale value) {
126 			super.locale(value);
127 			return this;
128 		}
129 
130 		@Override /* Overridden from Builder */
131 		public Builder mediaType(MediaType value) {
132 			super.mediaType(value);
133 			return this;
134 		}
135 
136 		@Override /* Overridden from Builder */
137 		public Builder mediaTypeDefault(MediaType value) {
138 			super.mediaTypeDefault(value);
139 			return this;
140 		}
141 
142 		@Override /* Overridden from Builder */
143 		public Builder properties(Map<String,Object> value) {
144 			super.properties(value);
145 			return this;
146 		}
147 
148 		@Override /* Overridden from Builder */
149 		public Builder property(String key, Object value) {
150 			super.property(key, value);
151 			return this;
152 		}
153 
154 		@Override /* Overridden from Builder */
155 		public Builder resolver(VarResolverSession value) {
156 			super.resolver(value);
157 			return this;
158 		}
159 
160 		@Override /* Overridden from Builder */
161 		public Builder schema(HttpPartSchema value) {
162 			super.schema(value);
163 			return this;
164 		}
165 
166 		@Override /* Overridden from Builder */
167 		public Builder schemaDefault(HttpPartSchema value) {
168 			super.schemaDefault(value);
169 			return this;
170 		}
171 
172 		/**
173 		 * Output stream charset.
174 		 *
175 		 * <p>
176 		 * The character set to use when writing to OutputStreams.
177 		 *
178 		 * <p>
179 		 * Used when passing in output streams and byte arrays to {@link WriterSerializer#serialize(Object, Object)}.
180 		 *
181 		 * <p>
182 		 * If not specified, defaults to UTF-8.
183 		 *
184 		 * @param value
185 		 * 	The new property value.
186 		 * 	<br>Can be <jk>null</jk> (value will not be set, defaults to UTF-8).
187 		 * @return This object.
188 		 */
189 		public Builder streamCharset(Charset value) {
190 			if (nn(value))
191 				streamCharset = value;
192 			return this;
193 		}
194 
195 		@Override /* Overridden from Builder */
196 		public Builder timeZone(TimeZone value) {
197 			super.timeZone(value);
198 			return this;
199 		}
200 
201 		@Override /* Overridden from Builder */
202 		public Builder timeZoneDefault(TimeZone value) {
203 			super.timeZoneDefault(value);
204 			return this;
205 		}
206 
207 		@Override /* Overridden from Builder */
208 		public Builder unmodifiable() {
209 			super.unmodifiable();
210 			return this;
211 		}
212 
213 		@Override /* Overridden from Builder */
214 		public Builder uriContext(UriContext value) {
215 			super.uriContext(value);
216 			return this;
217 		}
218 
219 		/**
220 		 * Use whitespace.
221 		 *
222 		 * <p>
223 		 * If true, whitespace is added to the output to improve readability.
224 		 *
225 		 * @param value
226 		 * 	The new property value.
227 		 * 	<br>Can be <jk>null</jk> (value will not be set, existing value from context will be kept).
228 		 * @return This object.
229 		 */
230 		public Builder useWhitespace(Boolean value) {
231 			if (nn(value))
232 				useWhitespace = value;
233 			return this;
234 		}
235 	}
236 
237 	/**
238 	 * Creates a new builder for this object.
239 	 *
240 	 * @param ctx The context creating this session.
241 	 * 	<br>Cannot be <jk>null</jk>.
242 	 * @return A new builder.
243 	 */
244 	public static Builder create(WriterSerializer ctx) {
245 		return new Builder(assertArgNotNull("ctx", ctx));
246 	}
247 
248 	private final WriterSerializer ctx;
249 	private final boolean useWhitespace;
250 	private final Charset fileCharset;
251 	private final Charset streamCharset;
252 
253 	/**
254 	 * Constructor.
255 	 *
256 	 * @param builder The builder for this object.
257 	 */
258 	protected WriterSerializerSession(Builder builder) {
259 		super(builder);
260 		ctx = builder.ctx;
261 		fileCharset = builder.fileCharset;
262 		streamCharset = builder.streamCharset;
263 		useWhitespace = builder.useWhitespace;
264 	}
265 
266 	/**
267 	 * Returns the file charset defined on this session.
268 	 *
269 	 * @return the file charset defined on this session.
270 	 */
271 	public Charset getFileCharset() { return fileCharset; }
272 
273 	/**
274 	 * Returns the stream charset defined on this session.
275 	 *
276 	 * @return the stream charset defined on this session.
277 	 */
278 	public Charset getStreamCharset() { return streamCharset; }
279 
280 	@Override /* Overridden from SerializerSession */
281 	public final boolean isWriterSerializer() { return true; }
282 
283 	/**
284 	 * Convenience method for serializing an object to a <c>String</c>.
285 	 *
286 	 * @param o The object to serialize.
287 	 * @return The output serialized to a string.
288 	 * @throws SerializeException If a problem occurred trying to convert the output.
289 	 */
290 	@Override /* Overridden from SerializerSession */
291 	public final String serialize(Object o) throws SerializeException {
292 		var w = new StringWriter();
293 		try {
294 			serialize(o, w);
295 		} catch (IOException e) {
296 			throw new SerializeException(e); // Shouldn't happen.
297 		}
298 		return w.toString();
299 	}
300 
301 	@Override /* Overridden from SerializerSession */
302 	public final String serializeToString(Object o) throws SerializeException {
303 		return serialize(o);
304 	}
305 
306 	@Override /* Overridden from SerializerSession */
307 	protected SerializerPipe createPipe(Object output) {
308 		return new SerializerPipe(output, streamCharset, fileCharset);
309 	}
310 
311 	/**
312 	 * Maximum indentation.
313 	 *
314 	 * @see WriterSerializer.Builder#maxIndent(int)
315 	 * @return
316 	 * 	The maximum indentation level in the serialized document.
317 	 */
318 	protected final int getMaxIndent() { return ctx.getMaxIndent(); }
319 
320 	/**
321 	 * Quote character.
322 	 *
323 	 * @see WriterSerializer.Builder#quoteChar(char)
324 	 * @return
325 	 * 	The character used for quoting attributes and values.
326 	 */
327 	protected char getQuoteChar() { return ctx.getQuoteChar(); }
328 
329 	/**
330 	 * Use whitespace.
331 	 *
332 	 * @see WriterSerializer.Builder#useWhitespace()
333 	 * @return
334 	 * 	The character used for quoting attributes and values.
335 	 */
336 	protected final boolean isUseWhitespace() { return useWhitespace; }
337 
338 	@Override /* Overridden from SerializerSession */
339 	protected FluentMap<String,Object> properties() {
340 		return super.properties()
341 			.a("fileCharset", fileCharset)
342 			.a("streamCharset", streamCharset)
343 			.a("useWhitespace", useWhitespace);
344 	}
345 }