Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

## [0.10.0] - 2023-11-22

### Changed

- Added Spotless as an automatic formatting tool for the entire codebase
- Changed some internal implementations of JsonParse for performance and readability reasons
- [breaking] Removed the usage of reflection for enum deserialization and reordered `RequestAdapter` arguments order

## [0.9.2] - 2023-11-16

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.microsoft.kiota.serialization.Parsable;
import com.microsoft.kiota.serialization.ParsableFactory;
import com.microsoft.kiota.serialization.SerializationWriterFactory;
import com.microsoft.kiota.serialization.ValuedEnumParser;
import com.microsoft.kiota.store.BackingStoreFactory;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
Expand All @@ -26,43 +27,41 @@ public interface RequestAdapter {
/**
* Executes the HTTP request specified by the given RequestInformation and returns the deserialized response model.
* @param requestInfo the request info to execute.
* @param factory the factory to create the parsable object from the type discriminator.
* @param errorMappings the error factories mapping to use in case of a failed request.
* @param factory the factory to create the parsable object from the type discriminator.
* @param <ModelType> the type of the response model to deserialize the response into.
* @return the deserialized response model.
*/
@SuppressWarnings("LambdaLast")
@Nullable <ModelType extends Parsable> ModelType send(
@Nonnull final RequestInformation requestInfo,
@Nonnull final ParsableFactory<ModelType> factory,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings);
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ParsableFactory<ModelType> factory);

/**
* Executes the HTTP request specified by the given RequestInformation and returns the deserialized response model collection.
* @param requestInfo the request info to execute.
* @param factory the factory to create the parsable object from the type discriminator.
* @param errorMappings the error factories mapping to use in case of a failed request.
* @param factory the factory to create the parsable object from the type discriminator.
* @param <ModelType> the type of the response model to deserialize the response into.
* @return the deserialized response model collection.
*/
@SuppressWarnings("LambdaLast")
@Nullable <ModelType extends Parsable> List<ModelType> sendCollection(
@Nonnull final RequestInformation requestInfo,
@Nonnull final ParsableFactory<ModelType> factory,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings);
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ParsableFactory<ModelType> factory);

/**
* Executes the HTTP request specified by the given RequestInformation and returns the deserialized primitive response model.
* @param requestInfo the request info to execute.
* @param targetClass the class of the response model to deserialize the response into.
* @param errorMappings the error factories mapping to use in case of a failed request.
* @param targetClass the class of the response model to deserialize the response into.
* @param <ModelType> the type of the response model to deserialize the response into.
* @return the deserialized primitive response model.
*/
@Nullable <ModelType> ModelType sendPrimitive(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings);
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final Class<ModelType> targetClass);

/**
* Executes the HTTP request specified by the given RequestInformation and returns the deserialized primitive collection response model.
Expand All @@ -74,34 +73,34 @@ public interface RequestAdapter {
*/
@Nullable <ModelType> List<ModelType> sendPrimitiveCollection(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings);
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final Class<ModelType> targetClass);

/**
* Executes the HTTP request specified by the given RequestInformation and returns the deserialized enum value.
* @param requestInfo the request info to execute.
* @param targetClass the class of the response model to deserialize the response into.
* @param errorMappings the error factories mapping to use in case of a failed request.
* @param enumParser a parser from string to enum instances.
* @param <ModelType> the type of the response model to deserialize the response into.
* @return the deserialized primitive response model.
*/
@Nullable <ModelType extends Enum<ModelType>> ModelType sendEnum(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings);
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ValuedEnumParser<ModelType> enumParser);

/**
* Executes the HTTP request specified by the given RequestInformation and returns the deserialized enum collection value.
* @param requestInfo the request info to execute.
* @param targetClass the class of the response model to deserialize the response into.
* @param errorMappings the error factories mapping to use in case of a failed request.
* @param enumParser a parser from string to enum instances.
* @param <ModelType> the type of the response model to deserialize the response into.
* @return the deserialized primitive response model.
*/
@Nullable <ModelType extends Enum<ModelType>> List<ModelType> sendEnumCollection(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings);
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ValuedEnumParser<ModelType> enumParser);

/**
* Sets The base url for every request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,18 @@ public interface ParseNode {
/**
* Gets the Enum value of the node.
* @return the Enum value of the node.
* @param targetEnum the class of the enum.
* @param enumParser the parser for Enums
* @param <T> the type of the enum.
*/
@Nullable <T extends Enum<T>> T getEnumValue(@Nonnull final Class<T> targetEnum);
@Nullable <T extends Enum<T>> T getEnumValue(@Nonnull final ValuedEnumParser<T> enumParser);

/**
* Gets the EnumSet value of the node.
* @return the EnumSet value of the node.
* @param targetEnum the class of the enum.
* @param enumParser the parser for Enums
* @param <T> the type of the enum.
*/
@Nullable <T extends Enum<T>> EnumSet<T> getEnumSetValue(@Nonnull final Class<T> targetEnum);
@Nullable <T extends Enum<T>> EnumSet<T> getEnumSetValue(@Nonnull final ValuedEnumParser<T> enumParser);

/**
* Gets the collection of primitive values of the node.
Expand All @@ -144,9 +144,10 @@ public interface ParseNode {
* Gets the collection of Enum values of the node.
* @return the collection of Enum values of the node.
* @param <T> the type of the enum.
* @param targetEnum the class of the enum
* @param enumParser the parser for Enums
*/
@Nullable <T extends Enum<T>> List<T> getCollectionOfEnumValues(@Nonnull final Class<T> targetEnum);
@Nullable <T extends Enum<T>> List<T> getCollectionOfEnumValues(
@Nonnull final ValuedEnumParser<T> enumParser);

/**
* Gets the model object value of the node.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.microsoft.kiota.serialization;

import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;

/** The interface for a valued enum parser. */
@FunctionalInterface
public interface ValuedEnumParser<T extends Enum> {
/**
* Gets an enum from it's string value.
* @param value the string value of the enum.
* @return the enum value derived from the string.
*/
@Nullable T forValue(@Nonnull String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.microsoft.kiota.serialization.ParseNodeFactoryRegistry;
import com.microsoft.kiota.serialization.SerializationWriterFactory;
import com.microsoft.kiota.serialization.SerializationWriterFactoryRegistry;
import com.microsoft.kiota.serialization.ValuedEnumParser;
import com.microsoft.kiota.store.BackingStoreFactory;
import com.microsoft.kiota.store.BackingStoreFactorySingleton;
import io.opentelemetry.api.GlobalOpenTelemetry;
Expand Down Expand Up @@ -172,13 +173,13 @@ public void enableBackingStore(@Nullable final BackingStoreFactory backingStoreF
}

private static final String nullRequestInfoParameter = "parameter requestInfo cannot be null";
private static final String nullTargetClassParameter = "parameter targetClass cannot be null";
private static final String nullEnumParserParameter = "parameter enumParser cannot be null";
private static final String nullFactoryParameter = "parameter factory cannot be null";

@Nullable public <ModelType extends Parsable> List<ModelType> sendCollection(
@Nonnull final RequestInformation requestInfo,
@Nonnull final ParsableFactory<ModelType> factory,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings) {
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ParsableFactory<ModelType> factory) {
Objects.requireNonNull(requestInfo, nullRequestInfoParameter);
Objects.requireNonNull(factory, nullFactoryParameter);

Expand Down Expand Up @@ -258,8 +259,8 @@ private Span startSpan(

@Nullable public <ModelType extends Parsable> ModelType send(
@Nonnull final RequestInformation requestInfo,
@Nonnull final ParsableFactory<ModelType> factory,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings) {
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ParsableFactory<ModelType> factory) {
Objects.requireNonNull(requestInfo, nullRequestInfoParameter);
Objects.requireNonNull(factory, nullFactoryParameter);

Expand Down Expand Up @@ -321,10 +322,10 @@ private void closeResponse(boolean closeResponse, Response response) {

@Nullable public <ModelType> ModelType sendPrimitive(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings) {
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final Class<ModelType> targetClass) {
Objects.requireNonNull(requestInfo, nullRequestInfoParameter);
Objects.requireNonNull(targetClass, nullTargetClassParameter);
Objects.requireNonNull(targetClass, "parameter targetClass cannot be null");
final Span span = startSpan(requestInfo, "sendPrimitiveAsync");
try (final Scope scope = span.makeCurrent()) {
Response response = this.getHttpResponseMessage(requestInfo, span, span, null);
Expand Down Expand Up @@ -415,10 +416,10 @@ private void closeResponse(boolean closeResponse, Response response) {

@Nullable public <ModelType extends Enum<ModelType>> ModelType sendEnum(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings) {
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ValuedEnumParser<ModelType> enumParser) {
Objects.requireNonNull(requestInfo, nullRequestInfoParameter);
Objects.requireNonNull(targetClass, nullTargetClassParameter);
Objects.requireNonNull(enumParser, nullEnumParserParameter);
final Span span = startSpan(requestInfo, "sendEnumAsync");
try (final Scope scope = span.makeCurrent()) {
Response response = this.getHttpResponseMessage(requestInfo, span, span, null);
Expand All @@ -441,7 +442,7 @@ private void closeResponse(boolean closeResponse, Response response) {
.setParent(Context.current().with(span))
.startSpan();
try (final Scope deserializationScope = deserializationSpan.makeCurrent()) {
final Object result = rootNode.getEnumValue(targetClass);
final Object result = rootNode.getEnumValue(enumParser::forValue);
setResponseType(result, span);
return (ModelType) result;
} finally {
Expand All @@ -461,10 +462,10 @@ private void closeResponse(boolean closeResponse, Response response) {

@Nullable public <ModelType extends Enum<ModelType>> List<ModelType> sendEnumCollection(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings) {
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final ValuedEnumParser<ModelType> enumParser) {
Objects.requireNonNull(requestInfo, nullRequestInfoParameter);
Objects.requireNonNull(targetClass, nullTargetClassParameter);
Objects.requireNonNull(enumParser, nullEnumParserParameter);
final Span span = startSpan(requestInfo, "sendEnumCollectionAsync");
try (final Scope scope = span.makeCurrent()) {
Response response = this.getHttpResponseMessage(requestInfo, span, span, null);
Expand All @@ -487,7 +488,8 @@ private void closeResponse(boolean closeResponse, Response response) {
.setParent(Context.current().with(span))
.startSpan();
try (final Scope deserializationScope = deserializationSpan.makeCurrent()) {
final Object result = rootNode.getCollectionOfEnumValues(targetClass);
final Object result =
rootNode.getCollectionOfEnumValues(enumParser::forValue);
setResponseType(result, span);
return (List<ModelType>) result;
} finally {
Expand All @@ -507,8 +509,8 @@ private void closeResponse(boolean closeResponse, Response response) {

@Nullable public <ModelType> List<ModelType> sendPrimitiveCollection(
@Nonnull final RequestInformation requestInfo,
@Nonnull final Class<ModelType> targetClass,
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings) {
@Nullable final HashMap<String, ParsableFactory<? extends Parsable>> errorMappings,
@Nonnull final Class<ModelType> targetClass) {
Objects.requireNonNull(requestInfo, nullRequestInfoParameter);

final Span span = startSpan(requestInfo, "sendPrimitiveCollectionAsync");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void SendStreamReturnsUsableStream(int statusCode) throws Exception {
};
InputStream response = null;
try {
response = requestAdapter.sendPrimitive(requestInformation, InputStream.class, null);
response = requestAdapter.sendPrimitive(requestInformation, null, InputStream.class);
assertNotNull(response);
assertEquals(text, new String(response.readAllBytes(), StandardCharsets.UTF_8));
} finally {
Expand Down Expand Up @@ -131,7 +131,7 @@ public void SendStreamReturnsNullOnNoContent(int statusCode) throws Exception {
}
};
final var response =
requestAdapter.sendPrimitive(requestInformation, InputStream.class, null);
requestAdapter.sendPrimitive(requestInformation, null, InputStream.class);
assertNull(response);
}

Expand Down Expand Up @@ -161,7 +161,7 @@ public void SendReturnsNullOnNoContent(int statusCode) throws Exception {
};
final var mockEntity = mock(Parsable.class);
when(mockEntity.getFieldDeserializers()).thenReturn(new HashMap<>());
final var response = requestAdapter.send(requestInformation, (node) -> mockEntity, null);
final var response = requestAdapter.send(requestInformation, null, (node) -> mockEntity);
assertNull(response);
}

Expand Down Expand Up @@ -200,7 +200,7 @@ public void SendReturnsObjectOnContent(int statusCode) throws Exception {
when(mockFactory.getValidContentType()).thenReturn("application/json");
final var requestAdapter =
new OkHttpRequestAdapter(authenticationProviderMock, mockFactory, null, client);
final var response = requestAdapter.send(requestInformation, (node) -> mockEntity, null);
final var response = requestAdapter.send(requestInformation, null, (node) -> mockEntity);
assertNotNull(response);
}

Expand Down Expand Up @@ -242,7 +242,7 @@ public void throwsAPIException() throws Exception {
final var exception =
assertThrows(
ApiException.class,
() -> requestAdapter.send(requestInformation, (node) -> mockEntity, null));
() -> requestAdapter.send(requestInformation, null, (node) -> mockEntity));
assertNotNull(exception);
assertEquals(404, exception.getResponseStatusCode());
assertTrue(exception.getResponseHeaders().containsKey("request-id"));
Expand Down
Loading