Skip to content

Commit

Permalink
Merge pull request #159 from RikkiGibson/ConcreteRestResponse
Browse files Browse the repository at this point in the history
Use concrete RestResponse in generator
  • Loading branch information
RikkiGibson authored Mar 2, 2018
2 parents 7e62008 + 2696cec commit 0df911b
Show file tree
Hide file tree
Showing 528 changed files with 18,987 additions and 8,329 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>1.8</source>
<target>1.8</target>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
<compilerArgument>-Xlint:unchecked</compilerArgument>
Expand Down
176 changes: 114 additions & 62 deletions src/JavaCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ public override Task Generate(AutoRestCodeModel codeModel)
javaFiles.Add(GetMethodGroupClientJavaFile(methodGroupClient, javaSettings));
}

foreach (ResponseModel rm in service.ResponseModels)
{
javaFiles.Add(GetResponseJavaFile(rm, javaSettings));
}

foreach (ServiceModel model in service.Models)
{
javaFiles.Add(GetModelJavaFile(model, javaSettings));
Expand Down Expand Up @@ -691,11 +696,27 @@ private static Service ParseService(AutoRestCodeModel codeModel, JavaSettings se
IEnumerable<ServiceModel> models = autoRestModelTypes
.Select((AutoRestCompositeType autoRestCompositeType) => ParseModel(autoRestCompositeType, settings, serviceModels))
.ToArray();

IEnumerable<ResponseModel> responseModels = codeModel.Methods
.Where(m => m.ReturnType.Headers != null)
.Select(m => ParseResponse(m, settings))
.ToList();

#endregion

ServiceManager manager = ParseManager(serviceClientName, codeModel, settings);

return new Service(serviceClientName, serviceClientDescription, enumTypes, exceptions, xmlSequenceWrappers, models, manager, serviceClient);
return new Service(serviceClientName, serviceClientDescription, enumTypes, exceptions, xmlSequenceWrappers, responseModels, models, manager, serviceClient);
}

private static ResponseModel ParseResponse(AutoRestMethod method, JavaSettings settings)
{
string name = method.MethodGroup.Name.ToPascalCase() + method.Name.ToPascalCase() + "Response";
string package = settings.Package + "." + settings.ModelsSubpackage;
string description = $"Contains all response data for the {method.Name} operation.";
IType headersType = ParseType(method.ReturnType.Headers, method.Extensions, settings).AsNullable();
IType bodyType = ParseType(method.ReturnType.Body, method.Extensions, settings).AsNullable();
return new ResponseModel(name, package, description, headersType, bodyType);
}

private static ServiceClient ParseServiceClient(AutoRestCodeModel codeModel, JavaSettings settings)
Expand Down Expand Up @@ -1061,19 +1082,25 @@ private static RestAPIMethod ParseRestAPIMethod(AutoRestMethod autoRestMethod, J
}
else
{
IType restResponseHeadersType = ConvertToClientType(ParseType(autoRestRestAPIMethodReturnType.Headers, settings));

IType restResponseBodyType;
if (settings.IsAzureOrFluent && responseBodyWireListType != null && (autorestRestAPIMethodReturnTypeIsPaged || restAPIMethodSimulateMethodAsPagingOperation))
IType singleValueType;
if (autoRestRestAPIMethodReturnType.Headers != null)
{
string className = autoRestMethod.MethodGroup.Name.ToPascalCase() + autoRestMethod.Name.ToPascalCase() + "Response";
singleValueType = new ClassType(settings.Package + "." + settings.ModelsSubpackage, className);
}
else if (responseBodyType.Equals(GenericType.FlowableByteBuffer))
{
singleValueType = ClassType.StreamResponse;
}
else if (responseBodyType.Equals(PrimitiveType.Void))
{
restResponseBodyType = responseBodyWireListType;
singleValueType = ClassType.VoidResponse;
}
else
{
restResponseBodyType = responseBodyType;
singleValueType = GenericType.BodyResponse(responseBodyType);
}

restAPIMethodReturnType = GenericType.Single(GenericType.RestResponse(restResponseHeadersType, responseBodyType));
restAPIMethodReturnType = GenericType.Single(singleValueType);
}

List<RestAPIParameter> restAPIMethodParameters = new List<RestAPIParameter>();
Expand Down Expand Up @@ -2401,6 +2428,79 @@ private static bool ShouldParseModelType(AutoRestCompositeType modelType, JavaSe
return shouldParseModelType;
}

public static JavaFile GetResponseJavaFile(ResponseModel response, JavaSettings settings)
{
JavaFile javaFile = GetJavaFileWithHeaderAndPackage(response.Package, settings, response.Name);
ISet<string> imports = new HashSet<string> { "java.util.Map" };
IType restResponseType = GenericType.RestResponse(response.HeadersType, response.BodyType);
restResponseType.AddImportsTo(imports, includeImplementationImports: true);

bool isStreamResponse = response.BodyType.Equals(GenericType.FlowableByteBuffer);
if (isStreamResponse)
{
imports.Add("java.io.Closeable");
imports.Add("io.reactivex.internal.functions.Functions");
}

javaFile.Import(imports);

string classSignature = isStreamResponse
? $"{response.Name} extends {restResponseType} implements Closeable"
: $"{response.Name} extends {restResponseType}";

javaFile.JavadocComment(javadoc =>
{
javadoc.Description(response.Description);
});

javaFile.PublicFinalClass(classSignature, classBlock =>
{
classBlock.JavadocComment(javadoc =>
{
javadoc.Description($"Creates an instance of {response.Name}.");
javadoc.Param("statusCode", "the status code of the HTTP response");
javadoc.Param("headers", "the deserialized headers of the HTTP response");
javadoc.Param("rawHeaders", "the raw headers of the HTTP response");
javadoc.Param("body", isStreamResponse ? "the body content stream" : "the deserialized body of the HTTP response");
});
classBlock.PublicConstructor(
$"{response.Name}(int statusCode, {response.HeadersType} headers, Map<String, String> rawHeaders, {response.BodyType} body)",
ctorBlock => ctorBlock.Line("super(statusCode, headers, rawHeaders, body);"));
if (!response.HeadersType.Equals(ClassType.Void))
{
classBlock.JavadocComment(javadoc => javadoc.Return("the deserialized response headers"));
classBlock.Annotation("Override");
classBlock.PublicMethod($"{response.HeadersType} headers()", methodBlock => methodBlock.Return("super.headers()"));
}
if (!response.BodyType.Equals(ClassType.Void))
{
if (response.BodyType.Equals(GenericType.FlowableByteBuffer))
{
classBlock.JavadocComment(javadoc => javadoc.Return("the response content stream"));
}
else
{
classBlock.JavadocComment(javadoc => javadoc.Return("the deserialized response body"));
}
classBlock.Annotation("Override");
classBlock.PublicMethod($"{response.BodyType} body()", methodBlock => methodBlock.Return("super.body()"));
}
if (isStreamResponse)
{
classBlock.JavadocComment(javadoc => javadoc.Description("Disposes of the connection associated with this stream response."));
classBlock.Annotation("Override");
classBlock.PublicMethod("void close()",
methodBlock => methodBlock.Line("body().subscribe(Functions.emptyConsumer(), Functions.<Throwable>emptyConsumer()).dispose();"));
}
});
return javaFile;
}

public static JavaFile GetModelJavaFile(ServiceModel model, JavaSettings settings)
{
JavaFile javaFile = GetJavaFileWithHeaderAndPackage(model.Package, settings, model.Name);
Expand Down Expand Up @@ -3497,10 +3597,6 @@ restAPIMethodReturnBodyClientType is ListType restAPIMethodReturnBodyClientListT
pageType = restAPIMethodReturnBodyClientType.AsNullable();
}

GenericType restResponseType = GenericType.RestResponse(
headersType: ConvertToClientType(ParseType(autoRestRestAPIMethodReturnType.Headers, settings)),
bodyType: deserializedResponseBodyType);

Parameter serviceCallbackParameter = new Parameter(
description: "the async ServiceCallback to handle successful and failed responses.",
isFinal: false,
Expand Down Expand Up @@ -4193,16 +4289,7 @@ restAPIMethodReturnBodyClientType is ListType restAPIMethodReturnBodyClientListT
string restAPIMethodArgumentList = GetRestAPIMethodArgumentList(autoRestMethodOrderedRetrofitParameters, settings);
function.Line($"return service.{restAPIMethod.Name}({restAPIMethodArgumentList}).map(new {GenericType.Function(restResponseType, pageType)}() {{");
function.Indent(() =>
{
function.Annotation("Override");
function.Block($"public {pageType} apply({restResponseType} response)", subFunction =>
{
subFunction.Return("response.body()");
});
});
function.Line("});");
function.Return($"service.{restAPIMethod.Name}({restAPIMethodArgumentList}).map(res -> res.body())");
});
break;

Expand Down Expand Up @@ -4254,16 +4341,7 @@ restAPIMethodReturnBodyClientType is ListType restAPIMethodReturnBodyClientListT
ApplyParameterTransformations(function, clientMethod, settings);
ConvertClientTypesToWireTypes(function, autoRestMethodRetrofitParameters, methodClientReference, settings);
string restAPIMethodArgumentList = GetRestAPIMethodArgumentList(autoRestMethodOrderedRetrofitParameters, settings);
function.Line($"return service.{clientMethod.RestAPIMethod.Name}({restAPIMethodArgumentList}).map(new {GenericType.Function(restResponseType, pageType)}() {{");
function.Indent(() =>
{
function.Annotation("Override");
function.Block($"public {pageType} apply({restResponseType} response)", subFunction =>
{
subFunction.Return("response.body()");
});
});
function.Line("}).toObservable();");
function.Return($"service.{clientMethod.RestAPIMethod.Name}({restAPIMethodArgumentList}).map(res -> res.body()).toObservable()");
});
break;

Expand Down Expand Up @@ -4464,34 +4542,11 @@ restAPIMethodReturnBodyClientType is ListType restAPIMethodReturnBodyClientListT
{
if (restAPIMethodReturnBodyClientType != PrimitiveType.Void)
{
function.Line($".flatMapMaybe(new {GenericType.Function(restResponseType, clientMethod.ReturnValue.Type)}() {{");
function.Indent(() =>
{
function.Block($"public {clientMethod.ReturnValue.Type} apply({restResponseType} restResponse)", subFunction =>
{
subFunction.If("restResponse.body() == null", ifBlock =>
{
ifBlock.Return("Maybe.empty()");
})
.Else(elseBlock =>
{
elseBlock.Return("Maybe.just(restResponse.body())");
});
});
});
function.Line("});");
function.Line($".flatMapMaybe(res -> res.body() == null ? Maybe.empty() : Maybe.just(res.body()));");
}
else if (isFluentDelete)
{
function.Line($".flatMapMaybe(new {GenericType.Function(restResponseType, clientMethod.ReturnValue.Type)}() {{");
function.Indent(() =>
{
function.Block($"public {clientMethod.ReturnValue.Type} apply({restResponseType} restResponse)", subFunction =>
{
subFunction.Return("Maybe.empty()");
});
});
function.Line("});");
function.Line($".flatMapMaybe(res -> Maybe.empty());");
}
else
{
Expand Down Expand Up @@ -4869,14 +4924,11 @@ restAPIMethodReturnBodyClientType is ListType restAPIMethodReturnBodyClientListT
restAPIMethod: restAPIMethod,
expressionsToValidate: expressionsToValidate));

GenericType singleRestResponseReturnType = GenericType.Single(GenericType.RestResponse(
headersType: ConvertToClientType(ParseType(autoRestRestAPIMethodReturnType.Headers, settings)),
bodyType: deserializedResponseBodyType));
clientMethods.Add(new ClientMethod(
description: restAPIMethod.Description,
returnValue: new ReturnValue(
description: $"a Single which performs the network request upon subscription.",
type: singleRestResponseReturnType),
type: ConvertToClientType(restAPIMethod.ReturnType)),
name: GetSimpleAsyncRestResponseMethodName(restAPIMethod),
parameters: parameters,
onlyRequiredParameters: onlyRequiredParameters,
Expand Down
2 changes: 2 additions & 0 deletions src/Model/ClassType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class ClassType : IType
public static readonly ClassType URL = new ClassType("java.net", "URL");
public static readonly ClassType NonNull = new ClassType("io.reactivex.annotations", "NonNull");
public static readonly ClassType OperationDescription = new ClassType("com.microsoft.rest.v2", "OperationDescription");
public static readonly ClassType VoidResponse = new ClassType("com.microsoft.rest.v2", "VoidResponse");
public static readonly ClassType StreamResponse = new ClassType("com.microsoft.rest.v2", "StreamResponse");

public ClassType(string package, string name, IEnumerable<string> implementationImports = null, IDictionary<string,string> extensions = null, bool isInnerModelType = false, Func<string,string> defaultValueExpressionConverter = null)
{
Expand Down
1 change: 1 addition & 0 deletions src/Model/GenericType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class GenericType : IType
public static GenericType Page(IType elementType) => new GenericType("com.microsoft.azure.v2", "Page", elementType);
public static GenericType PagedList(IType elementType) => new GenericType("com.microsoft.azure.v2", "PagedList", elementType);
public static GenericType RestResponse(IType headersType, IType bodyType) => new GenericType("com.microsoft.rest.v2", "RestResponse", headersType, bodyType);
public static GenericType BodyResponse(IType bodyType) => new GenericType("com.microsoft.rest.v2", "BodyResponse", bodyType);
public static GenericType Single(IType typeArgument) => new GenericType("io.reactivex", "Single", typeArgument);
public static GenericType Function(IType inputType, IType outputType) => new GenericType("io.reactivex.functions", "Function", inputType, outputType);

Expand Down
23 changes: 23 additions & 0 deletions src/Model/ResponseModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace AutoRest.Java.Model
{
public sealed class ResponseModel
{
public string Name { get; }
public string Package { get; }
public string Description { get; }
public IType HeadersType { get; }
public IType BodyType { get; }

public ResponseModel(string name, string package, string description, IType headersType, IType bodyType)
{
Name = name;
Package = package;
Description = description;
HeadersType = headersType;
BodyType = bodyType;
}
}
}
17 changes: 16 additions & 1 deletion src/Model/Service.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,23 @@ public class Service
/// <param name="models"></param>
/// <param name="manager"></param>
/// <param name="serviceClient"></param>
public Service(string clientName, string clientDescription, IEnumerable<EnumType> enums, IEnumerable<ServiceException> exceptions, IEnumerable<XmlSequenceWrapper> xmlSequenceWrappers, IEnumerable<ServiceModel> models, ServiceManager manager, ServiceClient serviceClient)
public Service(
string clientName,
string clientDescription,
IEnumerable<EnumType> enums,
IEnumerable<ServiceException> exceptions,
IEnumerable<XmlSequenceWrapper> xmlSequenceWrappers,
IEnumerable<ResponseModel> responseModels,
IEnumerable<ServiceModel> models,
ServiceManager manager,
ServiceClient serviceClient)
{
ClientName = clientName;
ClientDescription = clientDescription;
Enums = enums;
Exceptions = exceptions;
XmlSequenceWrappers = xmlSequenceWrappers;
ResponseModels = responseModels;
Models = models;
Manager = manager;
ServiceClient = serviceClient;
Expand Down Expand Up @@ -58,6 +68,11 @@ public Service(string clientName, string clientDescription, IEnumerable<EnumType
/// </summary>
public IEnumerable<XmlSequenceWrapper> XmlSequenceWrappers { get; }

/// <summary>
/// Get the response models which contain the response status code, headers and body for each service method.
/// </summary>
public IEnumerable<ResponseModel> ResponseModels { get; }

/// <summary>
/// Get the model types that are used by this service.
/// </summary>
Expand Down
Loading

0 comments on commit 0df911b

Please sign in to comment.