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}