1package com.bumptech.glide;
2
3import android.content.Context;
4
5import com.bumptech.glide.load.engine.DiskCacheStrategy;
6import com.bumptech.glide.load.model.ModelLoader;
7import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
8import com.bumptech.glide.load.resource.transcode.UnitTranscoder;
9import com.bumptech.glide.manager.Lifecycle;
10import com.bumptech.glide.manager.RequestTracker;
11import com.bumptech.glide.provider.DataLoadProvider;
12import com.bumptech.glide.provider.FixedLoadProvider;
13import com.bumptech.glide.provider.LoadProvider;
14import com.bumptech.glide.request.FutureTarget;
15import com.bumptech.glide.request.target.Target;
16
17import java.io.File;
18
19/**
20 * A class for handling requests to load a generic resource type or transcode the generic resource type into another
21 * generic resource type.
22 *
23 * <p>
24 *     Warning - It is <em>not</em> safe to use this builder after calling <code>into()</code>, it may be pooled and
25 *     reused.
26 * </p>
27 *
28 * @param  The type of the model used to retrieve data.
29 * @param  The type of data retrieved.
30 * @param  The type of resource to be decoded from the the data.
31 */
32public class GenericTranscodeRequest<ModelType, DataType, ResourceType>
33        extends GenericRequestBuilder<ModelType, DataType, ResourceType, ResourceType> implements DownloadOptions {
34    private final ModelLoader<ModelType, DataType> modelLoader;
35    private final Class<DataType> dataClass;
36    private final Class<ResourceType> resourceClass;
37    private final RequestManager.OptionsApplier optionsApplier;
38
39    private static <A, T, Z, R> LoadProvider<A, T, Z, R> build(Glide glide, ModelLoader<A, T> modelLoader,
40            Class<T> dataClass, Class<Z> resourceClass, ResourceTranscoder<Z, R> transcoder) {
41        DataLoadProvider<T, Z> dataLoadProvider = glide.buildDataProvider(dataClass, resourceClass);
42        return new FixedLoadProvider<A, T, Z, R>(modelLoader, transcoder, dataLoadProvider);
43    }
44
45    GenericTranscodeRequest(
46            Class<ResourceType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other,
47            ModelLoader<ModelType, DataType> modelLoader, Class<DataType> dataClass, Class<ResourceType> resourceClass,
48            RequestManager.OptionsApplier optionsApplier) {
49        super(build(other.glide, modelLoader, dataClass, resourceClass, UnitTranscoder.<ResourceType>get()),
50                transcodeClass, other);
51        this.modelLoader = modelLoader;
52        this.dataClass = dataClass;
53        this.resourceClass = resourceClass;
54        this.optionsApplier = optionsApplier;
55    }
56
57    GenericTranscodeRequest(Context context, Glide glide, Class<ModelType> modelClass,
58            ModelLoader<ModelType, DataType> modelLoader, Class<DataType> dataClass, Class<ResourceType> resourceClass,
59            RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
60        super(context, modelClass, build(glide, modelLoader, dataClass, resourceClass,
61                        UnitTranscoder.<ResourceType>get()), resourceClass, glide, requestTracker, lifecycle);
62        this.modelLoader = modelLoader;
63        this.dataClass = dataClass;
64        this.resourceClass = resourceClass;
65        this.optionsApplier = optionsApplier;
66    }
67
68    /**
69     * Adds a transcoder to this request to transcode from the resource type to the given transcode type.
70     *
71     * @param transcoder The transcoder to use.
72     * @param transcodeClass The class of the resource type that will be transcoded to.
73     * @param  The type of the resource that will be transcoded to.
74     * @return A new request builder to set options for the transcoded load.
75     */
76    public <TranscodeType> GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> transcode(
77            ResourceTranscoder<ResourceType, TranscodeType> transcoder, Class<TranscodeType> transcodeClass) {
78        LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider = build(glide, modelLoader,
79                dataClass, resourceClass, transcoder);
80
81        return optionsApplier.apply(new GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType>(
82                loadProvider, transcodeClass, this));
83    }
84
85    /**
86     * {@inheritDoc}
87     */
88    public <Y extends Target<File>> Y downloadOnly(Y target) {
89        return getDownloadOnlyRequest().into(target);
90    }
91
92    /**
93     * {@inheritDoc}
94     */
95    public FutureTarget<File> downloadOnly(int width, int height) {
96        return getDownloadOnlyRequest().into(width, height);
97    }
98
99    private GenericRequestBuilder<ModelType, DataType, File, File> getDownloadOnlyRequest() {
100        ResourceTranscoder<File, File> transcoder = UnitTranscoder.get();
101        DataLoadProvider<DataType, File> dataLoadProvider = glide.buildDataProvider(dataClass, File.class);
102        FixedLoadProvider<ModelType, DataType, File, File> fixedLoadProvider =
103                new FixedLoadProvider<ModelType, DataType, File, File>(modelLoader, transcoder, dataLoadProvider);
104        return optionsApplier.apply(new GenericRequestBuilder<ModelType, DataType, File, File>(fixedLoadProvider,
105                File.class, this))
106                .priority(Priority.LOW)
107                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
108                .skipMemoryCache(true);
109    }
110}
111