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.sse; 018 019 020import java.io.*; 021import java.util.*; 022 023import org.apache.juneau.marshall.*; 024import org.apache.juneau.marshall.parser.*; 025import org.apache.juneau.marshall.stream.*; 026import static org.apache.juneau.commons.utils.Shorts.*; 027 028/** 029 * Session object that lives for the duration of a single use of {@link SseParser}. 030 * 031 * <h5 class='section'>Notes:</h5><ul> 032 * <li class='warn'>This class is not thread safe and is typically discarded after one use. 033 * </ul> 034 * 035 * <h5 class='section'>See Also:</h5><ul> 036 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Sse">SSE</a> 037 * </ul> 038 */ 039@SuppressWarnings({ 040 "java:S110", // Inheritance depth acceptable for session hierarchy 041 "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants 042 "resource", // Closeable resources are owned by the caller's parser session; Eclipse JDT @Owning warning is by design. 043 "unchecked" // Type erasure: SseEvent/List<SseEvent> returned via Object cast 044}) 045public class SseParserSession extends ReaderParserSession implements RecordReadable { 046 047 /** 048 * Builder class. 049 */ 050 public static class Builder extends ReaderParserSession.Builder<Builder> { 051 052 /** 053 * Constructor. 054 * 055 * @param ctx The context creating this session. Cannot be <jk>null</jk>. 056 */ 057 protected Builder(SseParser ctx) { 058 super(reqnn("ctx", ctx)); 059 } 060 061 @Override 062 public SseParserSession build() { 063 return new SseParserSession(this); 064 } 065 } 066 067 /** 068 * Creates a new builder for this object. 069 * 070 * @param ctx The context creating this session. Cannot be <jk>null</jk>. 071 * @return A new builder. 072 */ 073 public static Builder create(SseParser ctx) { 074 return new Builder(reqnn("ctx", ctx)); 075 } 076 077 /** 078 * Constructor. 079 * 080 * @param builder The builder for this object. 081 */ 082 protected SseParserSession(Builder builder) { 083 super(builder); 084 } 085 086 @Override /* RecordReadable */ 087 public RecordReader readRecords(Object input) throws IOException { 088 return RecordAdapter.arrayReader(this, input); 089 } 090 091 @Override /* RecordReadable */ 092 public boolean isRecordStreaming() { 093 return false; 094 } 095 096 @Override /* Overridden from ParserSession */ 097 @SuppressWarnings({ 098 "java:S2095" // Reader is owned by ParserPipe and closed via SseEventReader in try-with-resources. 099 }) 100 protected <T> T doRead(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException { 101 var r = pipe.getReader(); 102 if (r == null) 103 return null; 104 List<SseEvent> events; 105 try (var r2 = new SseEventReader(r)) { 106 events = r2.toList(); 107 } 108 if (type == null || type.isObject() || type.isCollectionOrArray()) { 109 if (type != null && type.isArray()) 110 return (T) events.toArray(new SseEvent[0]); 111 return (T) events; 112 } 113 if (SseEvent.class.equals(type.inner())) { 114 return events.isEmpty() ? null : (T) events.get(0); 115 } 116 if (List.class.isAssignableFrom(type.inner())) 117 return (T) events; 118 throw new ParseException(this, "SseParser cannot produce target type '%s'.", type); 119 } 120}