Skip to content

Commit

Permalink
Merge pull request #843 from andreaTP/rem-enum-reflection
Browse files Browse the repository at this point in the history
Remove enum reflection
  • Loading branch information
baywet authored Nov 22, 2023
2 parents cda80a7 + 3813d35 commit 1beb9ae
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 117 deletions.
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

0 comments on commit 1beb9ae

Please sign in to comment.