001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.serializer; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.io.*; 023import java.lang.reflect.*; 024import java.nio.charset.*; 025import java.util.*; 026import java.util.function.*; 027 028import org.apache.juneau.*; 029import org.apache.juneau.commons.collections.FluentMap; 030import org.apache.juneau.httppart.*; 031import org.apache.juneau.svl.*; 032 033/** 034 * Subclass of {@link SerializerSession} for character-based serializers. 035 * 036 * <h5 class='topic'>Description</h5> 037 * 038 * This class is typically the parent class of all character-based serializers. 039 * <br>It has 1 abstract method to implement... 040 * <ul class='spaced-list'> 041 * <li> 042 * {@link #doSerialize(SerializerPipe, Object)} 043 * </ul> 044 * 045 * <h5 class='section'>Notes:</h5><ul> 046 * <li class='warn'>This class is not thread safe and is typically discarded after one use. 047 * </ul> 048 * 049 * <h5 class='section'>See Also:</h5><ul> 050 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a> 051 * </ul> 052 */ 053public class WriterSerializerSession extends SerializerSession { 054 /** 055 * Builder class. 056 */ 057 public static class Builder extends SerializerSession.Builder { 058 059 private boolean useWhitespace; 060 private Charset fileCharset; 061 private Charset streamCharset; 062 private WriterSerializer ctx; 063 064 /** 065 * Constructor 066 * 067 * @param ctx The context creating this session. 068 * <br>Cannot be <jk>null</jk>. 069 */ 070 protected Builder(WriterSerializer ctx) { 071 super(assertArgNotNull("ctx", ctx)); 072 this.ctx = ctx; 073 fileCharset = ctx.getFileCharset(); 074 streamCharset = ctx.getStreamCharset(); 075 useWhitespace = ctx.useWhitespace; 076 } 077 078 @Override /* Overridden from Builder */ 079 public <T> Builder apply(Class<T> type, Consumer<T> apply) { 080 super.apply(type, apply); 081 return this; 082 } 083 084 @Override 085 public WriterSerializerSession build() { 086 return new WriterSerializerSession(this); 087 } 088 089 @Override /* Overridden from Builder */ 090 public Builder debug(Boolean value) { 091 super.debug(value); 092 return this; 093 } 094 095 /** 096 * File charset. 097 * 098 * <p> 099 * 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}