Skip to content

Commit 0ccadf8

Browse files
committed
Iterate on GetImplicitNavigationPropertyUrlSegment
1 parent c0fa08d commit 0ccadf8

File tree

1 file changed

+59
-35
lines changed

1 file changed

+59
-35
lines changed

Templates/CSharp/Base/CollectionRequest.Base.template.tt

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<# // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. #>
22
<#@ template debug="true" hostspecific="true" language="C#" #>
33
<#@ include file="Request.Base.template.tt"#>
4+
5+
46
<#+
57

6-
using System.Linq.Enumerable;
8+
// using System.Linq.Enumerable;
79

810
// -------------------------------------------------------------
911
// Methods for standard entity collection classes
@@ -133,46 +135,47 @@ public string GetPostAsyncMethod(OdcmProperty odcmProperty, string requestBody =
133135
return string.Empty;
134136
}
135137

136-
public string GetPostAsyncMethodForReferencesRequest(OdcmProperty odcmProperty)
138+
public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, OdcmProperty odcmProperty)
137139
{
138-
var sanitizedPropertyName = odcmProperty.Projection.Type.Name.GetSanitizedPropertyName(odcmProperty.Name);
139-
var propertyType = this.GetPropertyTypeName(odcmProperty);
140+
// (1) Check that there are NavigationPropertyBindings. If there aren't any, then we know this segment of
141+
// the canonical path to the reference.
142+
if (singleton.NavigationPropertyBindings.Count == 0)
143+
{
144+
return "/" + odcmProperty.Name;
145+
}
140146

141-
var templateWriterHost = (CustomT4Host)Host;
142-
var templateWriter = (CodeWriterCSharp)templateWriterHost.CodeWriter;
147+
// (2) Get all of the keys that contain our target path name. The keys come from the Path attribute on a
148+
// NavigationPropertyBinding. So if our target property (OdcmProperty.Name) is named 'schools', then we need to only consider
149+
// NavigationPropertyBinding paths that end with 'schools'. The NavigationPropertyBindings are found in the Singleton that
150+
// defines the EntitySet that contains this property. The NavigationPropertyBindings provide generation hints for how to
151+
// reference non-contained entities that are defined within the same Singleton (this statement is conjecture). This generation
152+
// hints is used to specify a reference URL for $ref call.
143153

144-
var serviceNavigationProperty = odcmProperty.GetServiceCollectionNavigationPropertyForPropertyType();
145-
if (serviceNavigationProperty == null)
146-
return string.Empty;
147-
148-
//Append the singleton's navigation type to the @odata.id if relevant
149-
var implicitNavigationProperty = string.Empty;
150-
if (serviceNavigationProperty.GetType() == typeof(OdcmSingleton))
151-
{
152-
var singleton = (OdcmSingleton)serviceNavigationProperty;
154+
// TODO DELETE: in this case, "teachers". This should be the end part of the BindingPath.
153155

154-
// (1) Get all of the keys (Binding Paths) that contain our target path name, in this case, "teachers". This should be the end part of the BindingPath.
155156
IEnumerable<string> keys = singleton.NavigationPropertyBindings.Where(kvp => kvp.Key.EndsWith(odcmProperty.Name)).Select(kvp => kvp.Key);
156-
// TODO: if keys.Count == 0, we need to short circuit this.
157-
158-
/*
159-
// Check that we actually matched a key. If we have NavigationPropertyBindings and we didn't find a potential match, then we have an error
160-
if (singleton.NavigationPropertyBindings.Count != 0 && keys.Count() == 0) // I don't think this is good.
161-
{
162-
throw new Exception("Expected that a prospect key match is found. No key was found.");
163-
}
164-
*/
165-
166-
// (2) We need to query the paths in {keys} against the entity (odcmProperty.Class) that contains this navigation property (odcmProperty).
157+
/*
158+
<Singleton Name="education" Type="microsoft.graph.educationRoot">
159+
<NavigationPropertyBinding Path="classes/teachers" Target="users" />
160+
<NavigationPropertyBinding Path="classes/members" Target="users" />
161+
<NavigationPropertyBinding Path="classes/schools" Target="schools" />
162+
<NavigationPropertyBinding Path="schools/classes" Target="classes" />
163+
<NavigationPropertyBinding Path="schools/users" Target="users" />
164+
<NavigationPropertyBinding Path="users/schools" Target="schools" />
165+
<NavigationPropertyBinding Path="users/classes" Target="classes" />
166+
</Singleton>
167+
*/
168+
169+
// We need to support long NavPropBindings. That is, we need to support multi-segment NavigationPropertyBinding paths
170+
// (3) We need to query the paths in {keys} against the entity (odcmProperty.Class) that contains this navigation property (odcmProperty).
167171
// We need to determine the unique binding path from the singleton through the entity on to this navigation property, query the keys
168172
// for it, and then get the target. There could be 1 or more hops that we need to account for.
169173

170174
// odcmProperty.Name; // --> "teachers"
171175

172-
var navPropClassToFind = odcmProperty.Class.Name; // -- > "educationClass";
176+
var navPropClassToFind = odcmProperty.Class.Name; // -- > "educationClass"; This is the EntityType that contains the navigation property
173177
string firstBindingPathSegment = ""; // We are incorrectly assuming to segment.
174-
175-
178+
176179
foreach (OdcmProperty prop in (singleton.Type as OdcmEntityClass).Properties)
177180
{
178181
if (prop.Type.Name == navPropClassToFind)
@@ -192,14 +195,35 @@ public string GetPostAsyncMethodForReferencesRequest(OdcmProperty odcmProperty)
192195
if (singleton.NavigationPropertyBindings.TryGetValue(bindingPath, out bindingTarget))
193196
{
194197
// We found the target
195-
implicitNavigationProperty = "/" + bindingTarget;
198+
return "/" + bindingTarget;
196199
}
197200
else
198-
implicitNavigationProperty = "/" + odcmProperty.Name;
199-
200-
201-
}
201+
return "/" + odcmProperty.Name;
202+
}
203+
204+
public string GetPostAsyncMethodForReferencesRequest(OdcmProperty odcmProperty)
205+
{
206+
var sanitizedPropertyName = odcmProperty.Projection.Type.Name.GetSanitizedPropertyName(odcmProperty.Name);
207+
var propertyType = this.GetPropertyTypeName(odcmProperty);
208+
209+
var templateWriterHost = (CustomT4Host)Host;
210+
var templateWriter = (CodeWriterCSharp)templateWriterHost.CodeWriter;
211+
212+
var serviceNavigationProperty = odcmProperty.GetServiceCollectionNavigationPropertyForPropertyType();
213+
if (serviceNavigationProperty == null)
214+
return string.Empty;
215+
216+
var implicitNavigationProperty = string.Empty;
202217

218+
// If the odcmProperty is a part of Singleton, then we need to determine whether there is a
219+
// NavigationPropertyBinding generation hint. If there is, then we need to use it for
220+
// creating the URL of a reference entity in a POST body.
221+
if (serviceNavigationProperty.GetType() == typeof(OdcmSingleton))
222+
{
223+
var singleton = (OdcmSingleton)serviceNavigationProperty;
224+
225+
implicitNavigationProperty = GetImplicitNavigationPropertyUrlSegment(singleton, odcmProperty);
226+
}
203227

204228
var stringBuilder = new StringBuilder();
205229

0 commit comments

Comments
 (0)