Skip to content

Commit dc5b343

Browse files
authored
Merge pull request #20 from sashirestela/19-remove-code-related-to-bodypart
Remove Code Related to BodyPart
2 parents 1f1f638 + aa10d0c commit dc5b343

File tree

10 files changed

+54
-72
lines changed

10 files changed

+54
-72
lines changed

README.md

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ var cleverClient = CleverClient.builder()
152152

153153
### Supported Response Types
154154

155-
The reponse types are determined from the method responses. We don't need any annotation for that. We have five response types: [Stream](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html) of objects, [List](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html) of objects, Generic of object, Single object, and Plain Text, and all of them can be asynchronous or synchronous. For async responses you have to use the Java class [CompletableFuture](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html).
155+
The reponse types are determined from the method responses. We don't need any annotation for that. We have five response types: [Stream](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html) of objects, [List](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html) of objects, Generic of object, Single object, [Binary](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html) object, and Plain Text, and all of them can be asynchronous or synchronous. For async responses you have to use the Java class [CompletableFuture](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html).
156156

157157
| Method Response | Sync/Async | Response Type |
158158
|-------------------------------------|------------|-----------------------------------------|
@@ -164,6 +164,8 @@ The reponse types are determined from the method responses. We don't need any an
164164
| Generic\<Object> | Sync | Custom Generic Class of Object |
165165
| CompletableFuture\<Object> | Async | Single Object |
166166
| Object | Sync | Single Object |
167+
| CompletableFuture\<InputStream> | Async | Binary Object |
168+
| InputStream | Sync | Binary Object |
167169
| CompletableFuture\<String> | Async | Plain Text |
168170
| String | Sync | Plain Text |
169171

@@ -172,29 +174,29 @@ The reponse types are determined from the method responses. We don't need any an
172174
You can create interface default methods to execute special requirements such as pre/post processing before/after calling annotated regular methods. For example in the following interface definition, we have two regular methods with POST annotation which are called from another two default methods. In those defaults methods we are making some pre processing (in this case, modifying the request object) before calling the annotated methods:
173175

174176
```java
175-
@Resource("/v1/completions")
177+
@Resource("/v1/chat/completions")
176178
interface Completions {
177179

178-
default CompletableFuture<CompletionResponse> create(CompletionRequest completionRequest) {
179-
completionRequest.setStream(false);
180-
return notUseCreate(completionRequest);
181-
}
180+
@POST
181+
Stream<ChatResponse> __createSyncStream(@Body ChatRequest chatRequest);
182182

183-
@POST
184-
CompletableFuture<CompletionResponse> notUseCreate(@Body CompletionRequest completionRequest);
183+
default Stream<ChatResponse> createSyncStream(ChatRequest chatRequest) {
184+
var request = chatRequest.withStream(true);
185+
return __createSyncStream(request);
186+
}
185187

186-
default CompletableFuture<Stream<CompletionResponse>> createStream(CompletionRequest completionRequest) {
187-
completionRequest.setStream(true);
188-
return notUseCreateStream(completionRequest);
189-
}
188+
@POST
189+
CompletableFuture<Stream<ChatResponse>> __createAsyncStream(@Body ChatRequest chatRequest);
190190

191-
@POST
192-
CompletableFuture<Stream<CompletionResponse>> notUseCreateStream(@Body CompletionRequest completionRequest);
191+
default CompletableFuture<Stream<ChatResponse>> createAsyncStream(ChatRequest chatRequest) {
192+
var request = chatRequest.withStream(true);
193+
return __createAsyncStream(request);
194+
}
193195

194196
}
195197
```
196198

197-
Note that we have named the annotated methods with the prefix "notUse" (notUseCreate, notUseCreateStream) just to indicate that we should not call them directly but should call the default ones (create, createStream).
199+
Note that we have named the annotated methods with the suffix "__" just to indicate that we should not call them directly but should call the default ones (those without the suffix).
198200

199201
## ✳ Examples
200202

@@ -223,6 +225,8 @@ Some examples have been created in the folder [example](https://github.com/sashi
223225

224226
* ```<className>``` is mandatory and must be one of the values:
225227
* BasicExample
228+
* FileDownloadExample
229+
* MultiServiceExample
226230
* StreamExample (This requires you have an OpenAI account and set the env variable OPENAI_API_TOKEN)
227231

228232
* ```[logOptions]``` are optional and you can you use them to set:

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.github.sashirestela</groupId>
88
<artifactId>cleverclient</artifactId>
9-
<version>0.8.1</version>
9+
<version>0.9.0</version>
1010
<packaging>jar</packaging>
1111

1212
<name>cleverclient</name>

src/example/java/io/github/sashirestela/cleverclient/example/StreamExample.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ public static void main(String[] args) {
3434
.messages(Arrays.asList(
3535
new Message("user", "Write an article about AI, no more than 100 words.")))
3636
.temperature(0.7)
37-
.stream(true)
3837
.build();
3938

4039
showTitle("Example Create Synchronous Stream");

src/example/java/io/github/sashirestela/cleverclient/example/openai/ChatRequest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
import java.util.List;
44

5-
import lombok.AllArgsConstructor;
65
import lombok.Builder;
76
import lombok.Getter;
7+
import lombok.With;
88

9-
@AllArgsConstructor
109
@Getter
1110
@Builder
1211
public class ChatRequest {
1312
private String model;
1413
private List<Message> messages;
1514
private Double temperature;
15+
@With
1616
private Boolean stream;
1717
}

src/example/java/io/github/sashirestela/cleverclient/example/openai/ChatService.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,19 @@
1111
public interface ChatService {
1212

1313
@POST
14-
Stream<ChatResponse> createSyncStream(@Body ChatRequest chatRequest);
14+
Stream<ChatResponse> __createSyncStream(@Body ChatRequest chatRequest);
15+
16+
default Stream<ChatResponse> createSyncStream(ChatRequest chatRequest) {
17+
var request = chatRequest.withStream(true);
18+
return __createSyncStream(request);
19+
}
1520

1621
@POST
17-
CompletableFuture<Stream<ChatResponse>> createAsyncStream(@Body ChatRequest chatRequest);
22+
CompletableFuture<Stream<ChatResponse>> __createAsyncStream(@Body ChatRequest chatRequest);
23+
24+
default CompletableFuture<Stream<ChatResponse>> createAsyncStream(ChatRequest chatRequest) {
25+
var request = chatRequest.withStream(true);
26+
return __createAsyncStream(request);
27+
}
1828

1929
}

src/main/java/io/github/sashirestela/cleverclient/annotation/BodyPart.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/main/java/io/github/sashirestela/cleverclient/http/HttpConnector.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.net.http.HttpRequest;
66
import java.net.http.HttpRequest.BodyPublisher;
77
import java.net.http.HttpRequest.BodyPublishers;
8-
import java.util.List;
98

109
import org.slf4j.Logger;
1110
import org.slf4j.LoggerFactory;
@@ -25,12 +24,12 @@ public class HttpConnector {
2524
private String url;
2625
private String httpMethod;
2726
private ReturnType returnType;
28-
private List<Object> bodyObjects;
27+
private Object bodyObject;
2928
private boolean isMultipart;
3029
private String[] headersArray;
3130

3231
public Object sendRequest() {
33-
var bodyPublisher = createBodyPublisher(bodyObjects, isMultipart);
32+
var bodyPublisher = createBodyPublisher(bodyObject, isMultipart);
3433
var responseClass = returnType.getBaseClass();
3534
HttpRequest httpRequest = null;
3635
if (headersArray.length > 0) {
@@ -53,18 +52,18 @@ public Object sendRequest() {
5352
}
5453
}
5554

56-
private BodyPublisher createBodyPublisher(List<Object> bodyObjects, boolean isMultipart) {
55+
private BodyPublisher createBodyPublisher(Object bodyObject, boolean isMultipart) {
5756
BodyPublisher bodyPublisher = null;
58-
if (bodyObjects.isEmpty()) {
57+
if (bodyObject == null) {
5958
logger.debug("Body Request: (Empty)");
6059
bodyPublisher = BodyPublishers.noBody();
6160
} else if (isMultipart) {
62-
var data = ReflectUtil.getMapFields(bodyObjects);
61+
var data = ReflectUtil.getMapFields(bodyObject);
6362
var requestBytes = HttpMultipart.toByteArrays(data);
6463
logger.debug("Body Request: {}", data);
6564
bodyPublisher = BodyPublishers.ofByteArrays(requestBytes);
6665
} else {
67-
var requestString = JsonUtil.objectsToJson(bodyObjects);
66+
var requestString = JsonUtil.objectToJson(bodyObject);
6867
logger.debug("Body Request: {}", requestString);
6968
bodyPublisher = BodyPublishers.ofString(requestString);
7069
}

src/main/java/io/github/sashirestela/cleverclient/http/HttpProcessor.java

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
import java.util.ArrayList;
66
import java.util.List;
77
import java.util.Optional;
8-
import java.util.stream.Collectors;
9-
import java.util.stream.Stream;
108

11-
import io.github.sashirestela.cleverclient.annotation.BodyPart;
129
import org.slf4j.Logger;
1310
import org.slf4j.LoggerFactory;
1411

@@ -62,16 +59,16 @@ public Object resolve(Method method, Object[] arguments) {
6259
var httpMethod = methodMetadata.getHttpAnnotation().getName();
6360
var returnType = methodMetadata.getReturnType();
6461
var isMultipart = methodMetadata.isMultipart();
65-
var bodyObjects = calculateBodyObjects(methodMetadata, arguments);
62+
var bodyObject = calculateBodyObject(methodMetadata, arguments);
6663
var fullHeaders = new ArrayList<>(this.headers);
67-
fullHeaders.addAll(calculateHeaderContentType(bodyObjects, isMultipart));
64+
fullHeaders.addAll(calculateHeaderContentType(bodyObject, isMultipart));
6865
var fullHeadersArray = fullHeaders.toArray(new String[0]);
6966
var httpConnector = HttpConnector.builder()
7067
.httpClient(httpClient)
7168
.url(url)
7269
.httpMethod(httpMethod)
7370
.returnType(returnType)
74-
.bodyObjects(bodyObjects)
71+
.bodyObject(bodyObject)
7572
.isMultipart(isMultipart)
7673
.headersArray(fullHeadersArray)
7774
.build();
@@ -104,23 +101,19 @@ private void validateMetadata() {
104101
});
105102
}
106103

107-
private List<Object> calculateBodyObjects(Metadata.Method methodMetadata, Object[] arguments) {
108-
final var BODY = Body.class.getSimpleName();
109-
final var BODY_PART = BodyPart.class.getSimpleName();
110-
111-
return Stream.concat(
112-
methodMetadata.getParametersByType().get(BODY).stream()
113-
.limit(1)
114-
.map(param -> arguments[param.getIndex()]),
115-
methodMetadata.getParametersByType().get(BODY_PART).stream()
116-
.map(param -> arguments[param.getIndex()])
117-
.filter(arg -> !CommonUtil.isNullOrEmpty(arg))
118-
).collect(Collectors.toList());
104+
private Object calculateBodyObject(Metadata.Method methodMetadata, Object[] arguments) {
105+
final var BODY = Body.class.getSimpleName();
106+
var indexBody = methodMetadata.getParametersByType().get(BODY)
107+
.stream()
108+
.map(Metadata.Parameter::getIndex)
109+
.findFirst()
110+
.orElse(-1);
111+
return indexBody >= 0 ? arguments[indexBody] : null;
119112
}
120113

121-
private List<String> calculateHeaderContentType(List<Object> bodyObjects, boolean isMultipart) {
114+
private List<String> calculateHeaderContentType(Object bodyObject, boolean isMultipart) {
122115
List<String> headerContentType = new ArrayList<>();
123-
if (!bodyObjects.isEmpty()) {
116+
if (bodyObject != null) {
124117
var contentType = isMultipart
125118
? Constant.TYPE_MULTIPART + Constant.BOUNDARY_TITLE + "\"" + Constant.BOUNDARY_VALUE + "\""
126119
: Constant.TYPE_APP_JSON;

src/main/java/io/github/sashirestela/cleverclient/util/Constant.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private Constant() {
1010
}
1111

1212
public static final List<String> HTTP_METHODS = List.of("GET", "POST", "PUT", "DELETE");
13-
public static final List<String> PARAMETER_TYPES = List.of("Path", "Query", "Body", "BodyPart");
13+
public static final List<String> PARAMETER_TYPES = List.of("Path", "Query", "Body");
1414
public static final List<String> MULTIPART_AS_LIST = List.of("Multipart");
1515

1616
public static final String JSON_EMPTY_CLASS = "{\"type\":\"object\",\"properties\":{}}";

src/main/java/io/github/sashirestela/cleverclient/util/ReflectUtil.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import java.lang.reflect.Method;
88
import java.lang.reflect.Proxy;
99
import java.util.HashMap;
10-
import java.util.List;
1110
import java.util.Map;
1211

1312
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -24,15 +23,6 @@ public static <T> T createProxy(Class<T> interfaceClass, InvocationHandler handl
2423
handler);
2524
}
2625

27-
public static Map<String, Object> getMapFields(List<Object> objects) {
28-
Map<String, Object> structure = new HashMap<>();
29-
for (Object object : objects) {
30-
structure.putAll(getMapFields(object));
31-
}
32-
33-
return structure;
34-
}
35-
3626
public static Map<String, Object> getMapFields(Object object) {
3727
if (object instanceof Map) {
3828
return JsonUtil.objectToMap(object);

0 commit comments

Comments
 (0)