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.collections.JsonMap.*; 020 021import java.io.*; 022import java.lang.reflect.*; 023import java.nio.charset.*; 024import java.util.*; 025import java.util.function.*; 026 027import org.apache.juneau.*; 028import org.apache.juneau.collections.*; 029import org.apache.juneau.httppart.*; 030import org.apache.juneau.internal.*; 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 //------------------------------------------------------------------------------------------------------------------- 056 // Static 057 //------------------------------------------------------------------------------------------------------------------- 058 059 /** 060 * Creates a new builder for this object. 061 * 062 * @param ctx The context creating this session. 063 * @return A new builder. 064 */ 065 public static Builder create(WriterSerializer ctx) { 066 return new Builder(ctx); 067 } 068 069 //----------------------------------------------------------------------------------------------------------------- 070 // Builder 071 //----------------------------------------------------------------------------------------------------------------- 072 073 /** 074 * Builder class. 075 */ 076 public static class Builder extends SerializerSession.Builder { 077 078 WriterSerializer ctx; 079 boolean useWhitespace; 080 Charset fileCharset, streamCharset; 081 082 /** 083 * Constructor 084 * 085 * @param ctx The context creating this session. 086 */ 087 protected Builder(WriterSerializer ctx) { 088 super(ctx); 089 this.ctx = ctx; 090 useWhitespace = ctx.useWhitespace; 091 fileCharset = ctx.fileCharset; 092 streamCharset = ctx.streamCharset; 093 } 094 095 @Override 096 public WriterSerializerSession build() { 097 return new WriterSerializerSession(this); 098 } 099 100 /** 101 * File charset. 102 * 103 * <p> 104 * The character set to use for writing Files to the file system. 105 * 106 * <p> 107 * Used when passing in files to {@link Serializer#serialize(Object, Object)}. 108 * 109 * <p> 110 * If not specified, defaults to the JVM system default charset. 111 * 112 * @param value 113 * The new property value. 114 * <br>Can be <jk>null</jk>. 115 * @return This object. 116 */ 117 public Builder fileCharset(Charset value) { 118 if (value != null) 119 fileCharset = value; 120 return this; 121 } 122 123 /** 124 * Output stream charset. 125 * 126 * <p> 127 * The character set to use when writing to OutputStreams. 128 * 129 * <p> 130 * Used when passing in output streams and byte arrays to {@link WriterSerializer#serialize(Object, Object)}. 131 * 132 * <p> 133 * If not specified, defaults to UTF-8. 134 * 135 * @param value 136 * The new property value. 137 * <br>Can be <jk>null</jk>. 138 * @return This object. 139 */ 140 public Builder streamCharset(Charset value) { 141 if (value != null) 142 streamCharset = value; 143 return this; 144 } 145 146 /** 147 * Use whitespace. 148 * 149 * <p> 150 * If true, whitespace is added to the output to improve readability. 151 * 152 * @param value 153 * The new property value. 154 * <br>Can be <jk>null</jk>. 155 * @return This object. 156 */ 157 public Builder useWhitespace(Boolean value) { 158 if (value != null) 159 useWhitespace = value; 160 return this; 161 } 162 @Override /* Overridden from Builder */ 163 public <T> Builder apply(Class<T> type, Consumer<T> apply) { 164 super.apply(type, apply); 165 return this; 166 } 167 168 @Override /* Overridden from Builder */ 169 public Builder debug(Boolean value) { 170 super.debug(value); 171 return this; 172 } 173 174 @Override /* Overridden from Builder */ 175 public Builder properties(Map<String,Object> value) { 176 super.properties(value); 177 return this; 178 } 179 180 @Override /* Overridden from Builder */ 181 public Builder property(String key, Object value) { 182 super.property(key, value); 183 return this; 184 } 185 186 @Override /* Overridden from Builder */ 187 public Builder unmodifiable() { 188 super.unmodifiable(); 189 return this; 190 } 191 192 @Override /* Overridden from Builder */ 193 public Builder locale(Locale value) { 194 super.locale(value); 195 return this; 196 } 197 198 @Override /* Overridden from Builder */ 199 public Builder localeDefault(Locale value) { 200 super.localeDefault(value); 201 return this; 202 } 203 204 @Override /* Overridden from Builder */ 205 public Builder mediaType(MediaType value) { 206 super.mediaType(value); 207 return this; 208 } 209 210 @Override /* Overridden from Builder */ 211 public Builder mediaTypeDefault(MediaType value) { 212 super.mediaTypeDefault(value); 213 return this; 214 } 215 216 @Override /* Overridden from Builder */ 217 public Builder timeZone(TimeZone value) { 218 super.timeZone(value); 219 return this; 220 } 221 222 @Override /* Overridden from Builder */ 223 public Builder timeZoneDefault(TimeZone value) { 224 super.timeZoneDefault(value); 225 return this; 226 } 227 228 @Override /* Overridden from Builder */ 229 public Builder javaMethod(Method value) { 230 super.javaMethod(value); 231 return this; 232 } 233 234 @Override /* Overridden from Builder */ 235 public Builder resolver(VarResolverSession value) { 236 super.resolver(value); 237 return this; 238 } 239 240 @Override /* Overridden from Builder */ 241 public Builder schema(HttpPartSchema value) { 242 super.schema(value); 243 return this; 244 } 245 246 @Override /* Overridden from Builder */ 247 public Builder schemaDefault(HttpPartSchema value) { 248 super.schemaDefault(value); 249 return this; 250 } 251 252 @Override /* Overridden from Builder */ 253 public Builder uriContext(UriContext value) { 254 super.uriContext(value); 255 return this; 256 } 257 } 258 259 //----------------------------------------------------------------------------------------------------------------- 260 // Instance 261 //----------------------------------------------------------------------------------------------------------------- 262 263 private final WriterSerializer ctx; 264 private final boolean useWhitespace; 265 private final Charset streamCharset, fileCharset; 266 267 /** 268 * Constructor. 269 * 270 * @param builder The builder for this object. 271 */ 272 protected WriterSerializerSession(Builder builder) { 273 super(builder); 274 ctx = builder.ctx; 275 streamCharset = builder.streamCharset; 276 fileCharset = builder.fileCharset; 277 useWhitespace = builder.useWhitespace; 278 } 279 280 @Override /* SerializerSession */ 281 public final boolean isWriterSerializer() { 282 return true; 283 } 284 285 @Override /* SerializerSession */ 286 protected SerializerPipe createPipe(Object output) { 287 return new SerializerPipe(output, streamCharset, fileCharset); 288 } 289 290 /** 291 * Convenience method for serializing an object to a <c>String</c>. 292 * 293 * @param o The object to serialize. 294 * @return The output serialized to a string. 295 * @throws SerializeException If a problem occurred trying to convert the output. 296 */ 297 @Override /* SerializerSession */ 298 public final String serialize(Object o) throws SerializeException { 299 StringWriter w = new StringWriter(); 300 try { 301 serialize(o, w); 302 } catch (IOException e) { 303 throw new SerializeException(e); // Shouldn't happen. 304 } 305 return w.toString(); 306 } 307 308 @Override /* SerializerSession */ 309 public final String serializeToString(Object o) throws SerializeException { 310 return serialize(o); 311 } 312 313 //----------------------------------------------------------------------------------------------------------------- 314 // Properties 315 //----------------------------------------------------------------------------------------------------------------- 316 317 /** 318 * Maximum indentation. 319 * 320 * @see WriterSerializer.Builder#maxIndent(int) 321 * @return 322 * The maximum indentation level in the serialized document. 323 */ 324 protected final int getMaxIndent() { 325 return ctx.getMaxIndent(); 326 } 327 328 /** 329 * Quote character. 330 * 331 * @see WriterSerializer.Builder#quoteChar(char) 332 * @return 333 * The character used for quoting attributes and values. 334 */ 335 protected char getQuoteChar() { 336 return ctx.getQuoteChar(); 337 } 338 339 /** 340 * Use whitespace. 341 * 342 * @see WriterSerializer.Builder#useWhitespace() 343 * @return 344 * The character used for quoting attributes and values. 345 */ 346 protected final boolean isUseWhitespace() { 347 return useWhitespace; 348 } 349 350 /** 351 * Returns the file charset defined on this session. 352 * 353 * @return the file charset defined on this session. 354 */ 355 public Charset getFileCharset() { 356 return fileCharset; 357 } 358 359 /** 360 * Returns the stream charset defined on this session. 361 * 362 * @return the stream charset defined on this session. 363 */ 364 public Charset getStreamCharset() { 365 return streamCharset; 366 } 367 368 //----------------------------------------------------------------------------------------------------------------- 369 // Other methods 370 //----------------------------------------------------------------------------------------------------------------- 371 372 @Override /* ContextSession */ 373 protected JsonMap properties() { 374 return filteredMap("fileCharset", fileCharset, "streamCharset", streamCharset, "useWhitespace", useWhitespace); 375 } 376}