001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core.codec; 018 019import java.util.List; 020import java.util.Map; 021 022import org.reactivestreams.Publisher; 023import reactor.core.publisher.Flux; 024import reactor.core.publisher.Mono; 025import reactor.core.publisher.MonoProcessor; 026 027import org.springframework.core.ResolvableType; 028import org.springframework.core.io.buffer.DataBuffer; 029import org.springframework.lang.Nullable; 030import org.springframework.util.Assert; 031import org.springframework.util.MimeType; 032 033/** 034 * Strategy for decoding a {@link DataBuffer} input stream into an output stream 035 * of elements of type {@code <T>}. 036 * 037 * @author Sebastien Deleuze 038 * @author Rossen Stoyanchev 039 * @since 5.0 040 * @param <T> the type of elements in the output stream 041 */ 042public interface Decoder<T> { 043 044 /** 045 * Whether the decoder supports the given target element type and the MIME 046 * type of the source stream. 047 * @param elementType the target element type for the output stream 048 * @param mimeType the mime type associated with the stream to decode 049 * (can be {@code null} if not specified) 050 * @return {@code true} if supported, {@code false} otherwise 051 */ 052 boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType); 053 054 /** 055 * Decode a {@link DataBuffer} input stream into a Flux of {@code T}. 056 * @param inputStream the {@code DataBuffer} input stream to decode 057 * @param elementType the expected type of elements in the output stream; 058 * this type must have been previously passed to the {@link #canDecode} 059 * method and it must have returned {@code true}. 060 * @param mimeType the MIME type associated with the input stream (optional) 061 * @param hints additional information about how to do encode 062 * @return the output stream with decoded elements 063 */ 064 Flux<T> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType, 065 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints); 066 067 /** 068 * Decode a {@link DataBuffer} input stream into a Mono of {@code T}. 069 * @param inputStream the {@code DataBuffer} input stream to decode 070 * @param elementType the expected type of elements in the output stream; 071 * this type must have been previously passed to the {@link #canDecode} 072 * method and it must have returned {@code true}. 073 * @param mimeType the MIME type associated with the input stream (optional) 074 * @param hints additional information about how to do encode 075 * @return the output stream with the decoded element 076 */ 077 Mono<T> decodeToMono(Publisher<DataBuffer> inputStream, ResolvableType elementType, 078 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints); 079 080 /** 081 * Decode a data buffer to an Object of type T. This is useful for scenarios, 082 * that distinct messages (or events) are decoded and handled individually, 083 * in fully aggregated form. 084 * @param buffer the {@code DataBuffer} to decode 085 * @param targetType the expected output type 086 * @param mimeType the MIME type associated with the data 087 * @param hints additional information about how to do encode 088 * @return the decoded value, possibly {@code null} 089 * @since 5.2 090 */ 091 @Nullable 092 default T decode(DataBuffer buffer, ResolvableType targetType, 093 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) throws DecodingException { 094 095 MonoProcessor<T> processor = MonoProcessor.create(); 096 decodeToMono(Mono.just(buffer), targetType, mimeType, hints).subscribeWith(processor); 097 098 Assert.state(processor.isTerminated(), "DataBuffer decoding should have completed."); 099 Throwable ex = processor.getError(); 100 if (ex != null) { 101 throw (ex instanceof CodecException ? (CodecException) ex : 102 new DecodingException("Failed to decode: " + ex.getMessage(), ex)); 103 } 104 return processor.peek(); 105 } 106 107 /** 108 * Return the list of MIME types this decoder supports. 109 */ 110 List<MimeType> getDecodableMimeTypes(); 111 112}