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.marshall.parser; 018 019 020import java.io.*; 021import java.nio.charset.*; 022 023import org.apache.juneau.commons.collections.*; 024import static org.apache.juneau.commons.utils.Shorts.*; 025 026/** 027 * Subclass of parser session objects for character-based parsers. 028 * 029 * <h5 class='section'>Notes:</h5><ul> 030 * <li class='warn'>This class is not thread safe and is typically discarded after one use. 031 * </ul> 032 * 033 * <h5 class='section'>See Also:</h5><ul> 034 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a> 035 * </ul> 036 */ 037@SuppressWarnings({ 038 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 039}) 040public class ReaderParserSession extends ParserSession { 041 042 /** 043 * Builder class. 044 */ 045 @SuppressWarnings({ 046 "java:S119" // 'SELF' (CRTP self-type) is intentional and clearer than a single-letter name. 047 }) 048 public abstract static class Builder<SELF extends Builder<SELF>> extends ParserSession.Builder<SELF> { 049 050 private Charset streamCharset; 051 private final ReaderParser ctx; 052 053 /** 054 * Constructor 055 * 056 * @param ctx The context creating this session. 057 * <br>Cannot be <jk>null</jk>. 058 */ 059 protected Builder(ReaderParser ctx) { 060 super(reqnn("ctx", ctx)); 061 this.ctx = ctx; 062 streamCharset = ctx.getStreamCharset(); 063 } 064 065 @Override 066 public ReaderParserSession build() { 067 return new ReaderParserSession(this); 068 } 069 070 @Override /* Overridden from Builder */ 071 public SELF property(String key, Object value) { 072 if (key == null) { 073 super.property(key, value); 074 return self(); 075 } 076 switch (key) { 077 case "streamCharset", "ReaderParserSession.streamCharset": 078 return streamCharset(cvt(value, Charset.class)); 079 default: 080 super.property(key, value); 081 return self(); 082 } 083 } 084 085 /** 086 * Input stream charset. 087 * 088 * <p> 089 * The character set to use for converting InputStreams and byte arrays to readers. 090 * 091 * <p> 092 * Used when passing in input streams and byte arrays to {@link Parser#read(Object, Class)}. 093 * 094 * <p> 095 * If not specified, defaults to UTF-8. 096 * 097 * @param value 098 * The new property value. 099 * <br>Can be <jk>null</jk> (defaults to UTF-8). 100 * @return This object. 101 */ 102 public SELF streamCharset(Charset value) { 103 streamCharset = value; 104 return self(); 105 } 106 107 } 108 109 /** 110 * Concrete default builder leaf for the non-subclassed {@code create()} path (CRTP terminal). 111 */ 112 public static final class DefaultBuilder extends Builder<DefaultBuilder> { 113 114 DefaultBuilder(ReaderParser ctx) { 115 super(ctx); 116 } 117 } 118 119 /** 120 * Creates a new builder for this object. 121 * 122 * @param ctx The context creating this session. 123 * <br>Cannot be <jk>null</jk>. 124 * @return A new builder. 125 */ 126 @SuppressWarnings({ 127 "java:S1452" // Builder<?> wildcard return intentional; callers use it to construct session instances polymorphically 128 }) 129 public static Builder<?> create(ReaderParser ctx) { 130 return new DefaultBuilder(reqnn("ctx", ctx)); 131 } 132 133 private final ReaderParser ctx; 134 private final Charset streamCharset; 135 136 /** 137 * Constructor. 138 * 139 * @param builder The builder for this object. 140 * <br>Cannot be <jk>null</jk>. 141 */ 142 protected ReaderParserSession(Builder<?> builder) { 143 super(builder); 144 ctx = builder.ctx; 145 streamCharset = builder.streamCharset; 146 } 147 148 /** 149 * Wraps the specified input object into a {@link ParserPipe} object so that it can be easily converted into 150 * a stream or reader. 151 * 152 * @param input 153 * The input. 154 * <br>This can be any of the following types: 155 * <ul> 156 * <li><jk>null</jk> 157 * <li>{@link Reader} 158 * <li>{@link CharSequence} 159 * <li>{@link InputStream} containing UTF-8 encoded text (or whatever the encoding specified by 160 * {@link ReaderParser.Builder#streamCharset(Charset)}). 161 * <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or whatever the encoding specified by 162 * {@link ReaderParser.Builder#streamCharset(Charset)}). 163 * </ul> 164 * @return 165 * A new {@link ParserPipe} wrapper around the specified input object. 166 */ 167 @SuppressWarnings({ 168 "resource" // Resource management handled by ParserPipe 169 }) 170 @Override /* Overridden from ParserSesson */ 171 public final ParserPipe createPipe(Object input) { 172 return setPipe(new ParserPipe(input, isDebug(), true, ctx.isAutoCloseStreams(), ctx.isUnbuffered(), streamCharset)); 173 } 174 175 /** 176 * Returns the stream charset defined on this session. 177 * 178 * @return the stream charset defined on this session. 179 */ 180 public Charset getStreamCharset() { return streamCharset; } 181 182 @Override /* Overridden from ParserSession */ 183 public final boolean isReaderParser() { return true; } 184 185 @Override /* Overridden from ParserSession */ 186 protected FluentMap<String,Object> properties() { 187 return super.properties() 188 .a("streamCharset", streamCharset); 189 } 190}