Skip to content

Commit

Permalink
Merge pull request #504 from microsoftgraph/dev
Browse files Browse the repository at this point in the history
 api release for java v3
  • Loading branch information
baywet authored Mar 16, 2021
2 parents 6b82f8e + 9b6a682 commit 5532973
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 34 deletions.
23 changes: 23 additions & 0 deletions CodeSnippetsReflection.Test/CSharpGeneratorShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,29 @@ public void GeneratesSnippetsWithMultilineStringEscaped()
Assert.Contains(stream, result);
}

[Fact]
//This test asserts that Enums are displayed Correctly in Csharp Snippets
public void GeneratesSnippetsWithEnumsCorrectlyDisplayed()
{
//Arrange
LanguageExpressions expressions = new CSharpExpressions();
var url = "https://graph.microsoft.com/beta/reports/authenticationMethods/usersRegisteredByMethod(includedUserTypes='all',includedUserRoles='all')";

var requestPayload = new HttpRequestMessage(HttpMethod.Get, url);
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrlBeta, _edmModelBeta.Value);
//Act by generating the code snippet
var result = new CSharpGenerator(_edmModelBeta.Value).GenerateCodeSnippet(snippetModel, expressions);


//Assert the snippet generated is as expected
var expected = "GraphServiceClient graphClient = new GraphServiceClient( authProvider );\r\n\r\n" +
"var userRegistrationMethodSummary = await graphClient.Reports.AuthenticationMethods\r\n" +
"\t.UsersRegisteredByMethod(IncludedUserTypes.All,IncludedUserRoles.All)\r\n" +
"\t.Request()\r\n" +
"\t.GetAsync();";
Assert.Equal(expected, result);
}

[Fact]
// This tests asserts that a type beginning with "@" character is also added to the AdditionalData bag
public void GeneratesSnippetsWithTypesStartingWithTheAtSymbol()
Expand Down
62 changes: 57 additions & 5 deletions CodeSnippetsReflection.Test/JavaGeneratorShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class JavaGeneratorShould
{
private const string ServiceRootUrl = "https://graph.microsoft.com/v1.0";
private readonly IEdmModel _edmModel = CsdlReader.Parse(XmlReader.Create(CommonGeneratorShould.CleanV1Metadata));
private const string AuthProviderPrefix = "IGraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( authProvider ).buildClient();\r\n\r\n";
private const string AuthProviderPrefix = "GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( authProvider ).buildClient();\r\n\r\n";

[Fact]
public void MapCorrectTypeForGuidReturnType()
Expand Down Expand Up @@ -116,7 +116,7 @@ public void MapCorrectTypeForDateTimeProperties()
//Act by generating the code snippet
var result = new JavaGenerator(_edmModel).GenerateCodeSnippet(snippetModel, expressions);

Assert.Contains(" CalendarSerializer.deserialize(\"datetime-value\")", result);
Assert.Contains(" OffsetDateTimeSerializer.deserialize(\"datetime-value\")", result);
}
[Fact]
public void MapCorrectTypeForDoubleProperties()
Expand Down Expand Up @@ -495,7 +495,7 @@ public void GeneratesSnippetsWithQueryOptions()
"requestOptions.add(new QueryOption(\"startDateTime\", \"2017-01-01T19:00:00.0000000\"));\r\n" + //Query Options present
"requestOptions.add(new QueryOption(\"endDateTime\", \"2017-01-07T19:00:00.0000000\"));\r\n" + //Query Options present
"\r\n" +
"IEventCollectionPage calendarView = graphClient.me().calendar().calendarView()\r\n" +
"EventCollectionPage calendarView = graphClient.me().calendar().calendarView()\r\n" +
"\t.buildRequest( requestOptions )\r\n" +
"\t.get();";

Expand Down Expand Up @@ -667,7 +667,10 @@ public void GeneratesSnippetsForOdataActionsWithParameters()

//Assert code snippet string matches expectation
const string expectedSnippet = "WorkbookRange workbookRange = graphClient.me().drive().items(\"{id}\").workbook().worksheets(\"{id|name}\")\r\n" +
"\t.range(\"A1:B2\")\r\n" +//parameter has double quotes
"\t.range(WorkbookWorksheetRangeParameterSet\r\n" +
"\t\t.newBuilder()\r\n" +
"\t\t.withAddress(\"A1:B2\")\r\n" +
"\t\t.build())\r\n" +//parameter has double quotes
"\t.buildRequest()\r\n" +
"\t.get();";

Expand Down Expand Up @@ -701,7 +704,11 @@ public void GeneratesSnippetsWithOptionalParametersInCorrectOrder()
"Boolean hasHeaders = true;\r\n" +
"\r\n" +
"graphClient.me().drive().items(\"{id}\").workbook().tables()\r\n" +
"\t.add(address,hasHeaders)\r\n" +
"\t.add(WorkbookTableAddParameterSet\r\n" +
"\t\t.newBuilder()\r\n" +
"\t\t.withAddress(address)\r\n" +
"\t\t.withHasHeaders(hasHeaders)\r\n" +
"\t\t.build())\r\n" +
"\t.buildRequest()\r\n" +
"\t.post();";

Expand Down Expand Up @@ -1077,5 +1084,50 @@ public void GenerateProfilePicture()
var result = new JavaGenerator(_edmModel).GenerateCodeSnippet(snippetModel, expressions);
Assert.Contains("byte[]", result);
}
[Fact]
public void NotIncludeParenthesisInIdentifiers()
{
LanguageExpressions expressions = new JavaExpressions();
const string jsonObject = "{" +
"\"value\":" +
"[" +
"{" +
"\"id\": \"contoso.sharepoint.com,da60e844-ba1d-49bc-b4d4-d5e36bae9019,712a596e-90a1-49e3-9b48-bfa80bee8740\"" +
"}," +
"{" +
"\"id\": \"contoso.sharepoint.com,da60e844-ba1d-49bc-b4d4-d5e36bae9019,0271110f-634f-4300-a841-3a8a2e851851\"" +
"}" +
"] " +
"}";

var requestPayload =
new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/users/{user-id}/followedSites/add")
{
Content = new StringContent(jsonObject)
};
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, _edmModel);
var result = new JavaGenerator(_edmModel).GenerateCodeSnippet(snippetModel, expressions);
Assert.DoesNotContain("Site(Add", result);// in case it's a collection we need to trim the ) at the end of the type name
}
[Fact]
public void UseTheRightTypePrefixForParameterSets() {
LanguageExpressions expressions = new JavaExpressions();
const string jsonObject = "{" +
"\"EmailAddresses\": [" +
"\"[email protected]\", " +
"\"[email protected]\"" +
"]," +
"\"MailTipsOptions\": \"automaticReplies, mailboxFullStatus\"" +
"}";

var requestPayload =
new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/me/getMailTips")
{
Content = new StringContent(jsonObject)
};
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, _edmModel);
var result = new JavaGenerator(_edmModel).GenerateCodeSnippet(snippetModel, expressions);
Assert.Contains("UserGetMailTipsParameterSet", result);
}
}
}
5 changes: 3 additions & 2 deletions CodeSnippetsReflection/LanguageGenerators/CSharpGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ private string CSharpGenerateResourcesPath(SnippetModel snippetModel)
break;
//handle functions/actions and any parameters present into collections
case OperationSegment operationSegment:
var paramList = CommonGenerator.GetParameterListFromOperationSegment(operationSegment, snippetModel);
var paramList = CommonGenerator.GetParameterListFromOperationSegment(
operationSegment, snippetModel, returnEnumTypeIfEnum:true);
var parameters = string.Join(",", paramList.Select(x =>
{
if (x.Contains("'"))
Expand All @@ -261,7 +262,7 @@ private string CSharpGenerateResourcesPath(SnippetModel snippetModel)
// do we have other special types that show up in URLs?
var split = x.Split("'");
var enumType = CommonGenerator.UppercaseFirstLetter(split[0].Split(".").Last()); // TimeZoneStandard
var enumValue = split[1];
var enumValue = CommonGenerator.UppercaseFirstLetter(split[1]);
return $"{enumType}.{enumValue}";
}
else
Expand Down
84 changes: 65 additions & 19 deletions CodeSnippetsReflection/LanguageGenerators/CommonGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static string GenerateQuerySection(SnippetModel snippetModel, LanguageExp
foreach (var (key, value) in snippetModel.RequestHeaders)
{
//no need to generate source for the host header
if (key.ToLower().Equals("host",StringComparison.Ordinal))
if (key.ToLower().Equals("host", StringComparison.Ordinal))
continue;
//append the header to the snippet
var valueString = value.First()
Expand Down Expand Up @@ -159,7 +159,7 @@ public IEdmType GetEdmTypeFromIdentifier(ODataPathSegment oDataPathSegment, ICol
case OperationSegment operationSegment:
foreach (var parameters in operationSegment.Operations.First().Parameters)
{
if (!parameters.Name.Equals(path.FirstOrDefault(),StringComparison.OrdinalIgnoreCase))
if (!parameters.Name.Equals(path.FirstOrDefault(), StringComparison.OrdinalIgnoreCase))
continue;

(type, isNavigationProperty) = SearchForEdmType(parameters.Type.Definition, path);
Expand Down Expand Up @@ -214,7 +214,7 @@ public IEdmType GetEdmTypeFromIdentifier(ODataPathSegment oDataPathSegment, ICol
{
foreach (var property in structuredType.DeclaredProperties)
{
if (property.Name.Equals(searchIdentifier,StringComparison.OrdinalIgnoreCase))
if (property.Name.Equals(searchIdentifier, StringComparison.OrdinalIgnoreCase))
{
elementDefinition = GetEdmElementType(property.Type.Definition);

Expand Down Expand Up @@ -275,7 +275,7 @@ private static IEdmType GetEdmElementType(IEdmType edmType)
/// <param name="variableName">variable name to check for uniqueness</param>
/// <param name="languageExpressions">Language expressions that holds list of reserved words for filtering</param>
/// <returns>Modified variable name that is not a keyword</returns>
public static string EnsureVariableNameIsNotReserved(string variableName , LanguageExpressions languageExpressions)
public static string EnsureVariableNameIsNotReserved(string variableName, LanguageExpressions languageExpressions)
{
if (languageExpressions.ReservedNames.Contains(variableName))
{
Expand Down Expand Up @@ -316,7 +316,43 @@ public static string LowerCaseFirstLetter(string s)
a[0] = char.ToLower(a[0]);
return new string(a);
}
/// <summary>
/// This is a language agnostic function that looks at a operationSegment and returns a list of parameters with their names and values needed by the operation.
/// If the method is a post, the parameters are sought for in the request body. Otherwise they are sort for in the request url
/// </summary>
/// <param name="operationSegment">OData OperationSegment representing a Function or action</param>
/// <param name="snippetModel">Snippet Model to obtain useful data from</param>
/// <param name="collectionSuffix">Suffix to be added to elements that are proved to be members collections</param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, string>> GetParameterListFromOperationSegmentWithNames(OperationSegment operationSegment, SnippetModel snippetModel, bool returnEnumTypeIfEnum, string collectionSuffix = "")
{
var parametersProvided = new List<string>();
if (!string.IsNullOrEmpty(snippetModel.RequestBody)
&& JsonConvert.DeserializeObject(snippetModel.RequestBody) is JObject testObj)
{
foreach (var (key, _) in testObj)
{
parametersProvided.Add(key);
}
}


if (snippetModel.Method == HttpMethod.Post)
{
//use the order from the metadata
var parameters = operationSegment
.Operations
.First()
.Parameters
.Skip(1) // the first parameter is always the binding one
.ToList();
return AddValidParameterItemsFromIEdmOperationParameterList(new List<string>(), parameters, parametersProvided, collectionSuffix)
.Select((x, idx) => new KeyValuePair<string, string>(parameters[idx].Name, x));
}
else
return operationSegment.Parameters.Select(x => new KeyValuePair<string, string>(x.Name, GetParameterValueFromOperationUrlSegement(x, returnEnumTypeIfEnum)));

}
/// <summary>
/// This is a language agnostic function that looks at a operationSegment and returns a list of parameters needed by the operation.
/// If the method is a post, the parameters are sought for in the request body. Otherwise they are sort for in the request url
Expand All @@ -326,7 +362,9 @@ public static string LowerCaseFirstLetter(string s)
/// <param name="collectionSuffix">Suffix to be added to elements that are proved to be members collections</param>
/// <param name="isOrderedByOptionalParameters">Flag to show whether the parameters are ordered by the the metadata or optionality of params</param>
/// <returns></returns>
public static IEnumerable<string> GetParameterListFromOperationSegment(OperationSegment operationSegment, SnippetModel snippetModel, string collectionSuffix = "", bool isOrderedByOptionalParameters = true)
public static IEnumerable<string> GetParameterListFromOperationSegment(
OperationSegment operationSegment, SnippetModel snippetModel, string collectionSuffix = "",
bool isOrderedByOptionalParameters = true, bool returnEnumTypeIfEnum = false)
{
var paramList = new List<string>();

Expand Down Expand Up @@ -364,25 +402,33 @@ public static IEnumerable<string> GetParameterListFromOperationSegment(Operation
//read parameters from url since this is an odata function
foreach (var parameter in operationSegment.Parameters)
{
switch (parameter.Value)
{
case ConvertNode convertNode:
{
if (convertNode.Source is ConstantNode constantNode)
{
paramList.Add($"\"{constantNode.Value}\"");
}
break;
}
case ConstantNode constantNode:
paramList.Add(constantNode.LiteralText);
break;
}
var value = GetParameterValueFromOperationUrlSegement(parameter, returnEnumTypeIfEnum);
if (!string.IsNullOrEmpty(value))
paramList.Add(value);
}
}

return paramList;
}
/// <summary>
/// Gets the value of an operation from the URL segments when available
/// </summary>
/// <param name="parameter">Parameter to look for</param>
/// <returns>Value provided by the HTTP snippet</returns>
private static string GetParameterValueFromOperationUrlSegement(OperationSegmentParameter parameter, bool returnEnumTypeIfEnum)
{
switch (parameter.Value)
{
case ConvertNode convertNode when convertNode.Source is ConstantNode cNode:
return $"\"{cNode.Value}\"";
case ConstantNode constantNode when constantNode.TypeReference.Definition.TypeKind == EdmTypeKind.Enum && returnEnumTypeIfEnum:
return $"{parameter.Name}{constantNode.LiteralText}";
case ConstantNode constantNode:
return constantNode.LiteralText;
default:
return null;
}
}

/// <summary>
/// Helper function to add parameters from list of operationSegment parameters. This is validated from a list of parameters given
Expand Down
Loading

0 comments on commit 5532973

Please sign in to comment.