Completed
Push — master ( 94633f...bbac12 )
by Kunal
03:51
created

addFilesToBuilder(Builder,Map)   A

Complexity

Conditions 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
rs 9.2
cc 4
1
package com.base.Http.Clients;
2
3
import com.base.Exceptions.BaseHttpException;
4
import com.base.Http.Request.Request;
5
import com.base.Http.Response.Response;
6
import okhttp3.*;
7
8
import java.io.File;
9
import java.io.IOException;
0 ignored issues
show
Unused Code introduced by
Remove this unused import 'java.io.IOException'.
Loading history...
10
import java.nio.file.Files;
11
import java.util.HashMap;
12
import java.util.Iterator;
13
import java.util.Map;
14
15
public class OkHttpClient implements HttpClientInterface {
16
17
    /**
18
     * Implementation of {@link HttpClientInterface}
19
     *
20
     * @param request  {@link Request}
21
     * @param response {@link Response}
22
     * @return Response
23
     * @throws BaseHttpException
24
     */
25
    @Override
26
    public Response send(Request request, Response response) throws BaseHttpException {
27
28
        // Send the Request and Fetch the Response
29
        try {
30
            // Request Builder
31
            okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder()
32
                    .url(request.getUrl());
33
34
            // Prepare the headers
35
            this.prepareHeaders(request, requestBuilder);
36
37
            // Request Body
38
            RequestBody requestBody = null;
39
40
            // The Request has Body
41
            if (this.requestHasBody(request)) {
42
                // Prepare the Body
43
                requestBody = this.buildRequestBody(request);
44
            }
45
46
            // Add body to the request
47
            requestBuilder.method(request.getMethod(), requestBody);
48
49
            // Build the Request
50
            okhttp3.Request okHttpRequest = requestBuilder.build();
51
52
53
            // Create the Client
54
            okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
55
            okhttp3.Response okHttpResponse = client.newCall(okHttpRequest).execute();
56
57
            String body = okHttpResponse.body().string();
58
            Map<String, String> responseHeaders = this.getResponseHeaders(okHttpResponse);
59
60
            if (response == null) {
61
                response = new Response(request);
62
            }
63
64
            response.setBody(body)
65
                    .setHeaders(responseHeaders)
66
                    .setStatusCode(okHttpResponse.code());
67
68
            return response;
69
        } catch (Exception e) {
70
            throw new BaseHttpException(500, e.getMessage(), response);
71
        }
72
    }
73
74
    /**
75
     * This method accepts the {@link Request} if the request's method is patch, post or put then it will true or else false.
76
     *
77
     * @param request {@link Request}
78
     * @return true or false on the basis of which type of request come.
79
     */
80
    private boolean requestHasBody(Request request) {
81
        return request.getMethod().equalsIgnoreCase(Request.METHOD_PATCH) ||
82
                request.getMethod().equalsIgnoreCase(Request.METHOD_POST) ||
83
                request.getMethod().equalsIgnoreCase(Request.METHOD_PUT);
84
    }
85
86
    /**
87
     * It will Return the {@link com.base.Http.Request.RequestBody} on the basis of {@link Request}
88
     *
89
     * @param request {@link Request}
90
     * @return ResponseBody {@link ResponseBody}
91
     * @throws Exception
92
     */
93
    private RequestBody buildRequestBody(Request request) throws Exception {
94
        // Request is multipart
95
        if (this.requestIsMultipart(request)) {
96
            // Build Request Body
97
            MultipartBody.Builder bodyBuilder = this.getMultiPartBuilder();
98
            this.addParamsToBuilder(bodyBuilder, request.getParameters());
99
            this.addFilesToBuilder(bodyBuilder, request.getFiles());
100
            return bodyBuilder.build();
101
        }
102
103
        // Simple Request
104
        FormBody.Builder formBodyBuilder = new FormBody.Builder();
105
        this.addParamsToBuilder(formBodyBuilder, request.getParameters());
106
        return formBodyBuilder.build();
107
    }
108
109
    /**
110
     * Accept the {@link Request} and return true if {@link Request} is Multipart or else not.
111
     *
112
     * @param request {@link Request}
113
     * @return java.lang.Boolean
114
     */
115
    private boolean requestIsMultipart(Request request) {
116
        return (request.getMethod().equalsIgnoreCase(Request.METHOD_POST)) &&
117
                (!request.getParameters().isEmpty() || !request.getFiles().isEmpty());
118
    }
119
120
    /**
121
     * Get Response Headers.
122
     *
123
     * @param okHttpResponse
124
     * @return
125
     */
126
    private Map<String, String> getResponseHeaders(okhttp3.Response okHttpResponse) {
127
        Map<String, String> headers = new HashMap<>();
128
        Headers okHttpHeaders = okHttpResponse.headers();
129
        Iterator<String> iterator = okHttpHeaders.names().iterator();
130
131
        while (iterator.hasNext()) {
132
            String key = iterator.next();
133
            String value = headers.get(key);
134
135
            headers.put(key, value);
136
        }
137
138
        return headers;
139
    }
140
141
    /**
142
     * Prepare Request Headers.
143
     *
144
     * @param request
145
     * @param requestBuilder
146
     */
147
    private void prepareHeaders(Request request, okhttp3.Request.Builder requestBuilder) {
148
        Map<String, String> headers = request.getHeaders();
149
150
        for (String headerKey : headers.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
151
            String headerValue = headers.get(headerKey);
152
            requestBuilder.addHeader(headerKey, headerValue);
153
        }
154
    }
155
156
    /**
157
     * Get {@link MultipartBody.Builder}
158
     *
159
     * @return MultipartBody.Builder
160
     * @throws Exception
161
     */
162
    private MultipartBody.Builder getMultiPartBuilder() throws Exception {
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
163
        return new MultipartBody.Builder()
164
                .setType(MultipartBody.FORM);
165
    }
166
167
    /**
168
     * It wll add parameters to the Builder
169
     *
170
     * @param builder
171
     * @param parameters Map of
172
     */
173
    private void addParamsToBuilder(FormBody.Builder builder, Map<String, String> parameters) {
174
        for (String key : parameters.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
175
            String value = parameters.get(key);
176
            // If key is `user_ids*1`, its part of a value (user_ids[]) array. Else, it's a single value.
177
            String keyName = key.contains("*") ? key.substring(0, key.indexOf('*')).concat("[]") : key;
178
179
            builder.add(keyName, value);
180
        }
181
    }
182
183
184
    private void addParamsToBuilder(MultipartBody.Builder builder, Map<String, String> parameters) {
185
        for (String key : parameters.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
186
            String value = parameters.get(key);
187
            // If key is `user_ids*1`, its part of a value (user_ids[]) array. Else, it's a single value.
188
            String keyName = key.contains("*") ? key.substring(0, key.indexOf('*')).concat("[]") : key;
189
190
            builder.addFormDataPart(keyName, value);
191
        }
192
    }
193
194
    private void addFilesToBuilder(MultipartBody.Builder builder, Map<String, File> files) throws Exception {
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
195
        for (String key : files.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
196
            File file = files.get(key);
197
198
            // If key is `allFiles*1`, its part of a file (allFiles[]) array. Else, it's a single file.
199
            String fileName = key.contains("*") ? key.substring(0, key.indexOf('*')).concat("[]") : key;
200
201
            if (file.exists()) {
202
                MediaType fileType = MediaType.parse("application/octet-stream");
203
                builder.addFormDataPart(fileName, file.getName(), RequestBody.create(fileType, file));
204
            }
205
        }
206
    }
207
}
208