@@ -141,11 +141,9 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
141141 To help the future dev in figuring this out, put a break point on the next executable line
142142 with the condition odcmProperty.Name == "teachers". The CSDL in and entities mentioned in these
143143 comments are an example of the use of this scenario.
144-
145144 ****/
146145
147-
148- // (1) Check that there are NavigationPropertyBindings. If there aren't any, then we know this segment of
146+ // (1) Check that there are NavigationPropertyBindings. If there aren't any, then we know this segment is
149147 // the canonical path to the reference.
150148 if (singleton.NavigationPropertyBindings.Count == 0)
151149 {
@@ -158,107 +156,19 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
158156 // defines the EntitySet that contains this property. The NavigationPropertyBindings provide generation hints for how to
159157 // reference non-contained entities that are defined within the same Singleton (this statement is conjecture). This generation
160158 // hints is used to specify a reference URL for $ref call.
161-
162159 // Example: in this case, "teachers". This should be the end part of the BindingPath.
163160
164161 IEnumerable<string> keys = singleton.NavigationPropertyBindings.Where(kvp => kvp.Key.EndsWith(odcmProperty.Name)).Select(kvp => kvp.Key);
165- /*
166- <Singleton Name="education" Type="microsoft.graph.educationRoot">
167- <NavigationPropertyBinding Path="classes/teachers" Target="users" />
168- <NavigationPropertyBinding Path="classes/members" Target="users" />
169- <NavigationPropertyBinding Path="classes/schools" Target="schools" />
170- <NavigationPropertyBinding Path="schools/classes" Target="classes" />
171- <NavigationPropertyBinding Path="schools/users" Target="users" />
172- <NavigationPropertyBinding Path="users/schools" Target="schools" />
173- <NavigationPropertyBinding Path="users/classes" Target="classes" />
174- </Singleton>
175-
176- <EntityType Name="educationRoot" BaseType="microsoft.graph.entity">
177- <NavigationProperty Name="synchronizationProfiles" Type="Collection(microsoft.graph.educationSynchronizationProfile)" ContainsTarget="true" />
178- <NavigationProperty Name="classes" Type="Collection(microsoft.graph.educationClass)" ContainsTarget="true" />
179- <NavigationProperty Name="schools" Type="Collection(microsoft.graph.educationSchool)" ContainsTarget="true" />
180- <NavigationProperty Name="users" Type="Collection(microsoft.graph.educationUser)" ContainsTarget="true" />
181- <NavigationProperty Name="me" Type="microsoft.graph.educationUser" ContainsTarget="true" />
182- </EntityType>
183-
184- <EntityType Name="educationClass" BaseType="microsoft.graph.entity">
185- <Property Name="displayName" Type="Edm.String" Nullable="false" />
186- <NavigationProperty Name="schools" Type="Collection(microsoft.graph.educationSchool)" />
187- <NavigationProperty Name="members" Type="Collection(microsoft.graph.educationUser)" />
188- <NavigationProperty Name="teachers" Type="Collection(microsoft.graph.educationUser)" />
189- <NavigationProperty Name="group" Type="microsoft.graph.group" />
190- <NavigationProperty Name="assignments" Type="Collection(microsoft.graph.educationAssignment)" ContainsTarget="true" />
191- </EntityType>
192- */
193-
194- // We need to support long NavPropBindings. That is, we need to support multi-segment NavigationPropertyBinding paths
195- // (3) We need to query the paths in {keys} against the entity (odcmProperty.Class) that contains this navigation property (odcmProperty).
196- // We need to determine the unique binding path from the singleton through the entity on to this navigation property, query the keys
197- // for it, and then get the target. There could be 1 or more pat segments that we need to account for.
198- // Example: odcmProperty.Class is the entity "educationClass" that has the non-contained navigation property represented by odcmProperty,
199- // which is named 'teachers'. At this point, we know the singleton and all of its NavigationPropertyBindings, we know the singleton's entity type,
200- // which is named 'educationRoot'.
201- // We need to determine whether a NavigationPropertyBinding pth and target is different than the CSDL described path to the reference non-contained entity.
202-
203- // odcmProperty.Name; // --> "teachers"
204-
205- var navPropClassToFind = odcmProperty.Class.Name; // -- > "educationClass"; This is the EntityType that contains the navigation property
206- string firstBindingPathSegment = ""; // We are incorrectly assuming to segment.
207-
208- // Get the path segments.
209- //string[] navPropBindingSegments = keys.First().Split('/');
210-
211- // Example: After hitting the conditional breakpoint, singleton.Type.Name is "educationRoot".
212- // We are going to inspect each navigation property on singleton's type and compare to the segments
213- // in the keys IEnumerable.
214- // The assumption here is that the first segment is a navigation property of the singleton's type
215- // The second assumption is that there are only two segments. We know this is a bad assumption.
216- // The third assumption is that the last segment is the most meaningful.
217- // In short, this only works for a Path that has two segments.
218-
219- foreach (OdcmProperty prop in (singleton.Type as OdcmEntityClass).Properties)
220- {
221- if (prop.Type.Name == navPropClassToFind)
222- {
223- firstBindingPathSegment = prop.Name;
224- break;
225- }
226- }
227-
228- /*
229- What we know.
230-
231- We know the navigation property name and type.
232- We know whih entity contains the navigation property.
233- We know that the navigation property does not contain the entity.
234- We know which singleton is the entity set for the navigation property.
235- We know the singleton's type.
236- We know the NavigationPropertyBindings and which candidates CAN be the one to define the reference path to the entity in the navigation.
237-
238- We don't know the paths to the entity that contains our navigation property. So, the question is, can we know the context in which the
239- navigation property is being accessed at generation time? I don't think we can.
240-
241- The next question is can we code the templates to generate code that is context aware and can create the ref path based on that context.
242- This is a maybe.
243-
244- Our current example works since the scenario only has two levels of entities. What happens when we have three level of entities like
245- /schools/classes/teachers. We know the teachers segments. We don't have context which entities are accessed across the request builders
246- at runtime.
247-
248- We may need to generate a dictionary from the NavPropBindings in to the code files and use those at runtime to discover the context in
249- which a navigtion is called in order to provide the correct reference path.
250-
251- TODO: investigate what it would take to generate code that is context aware of binding path.
252- */
253-
254- string secondBindingPathSegment = odcmProperty.Name;
255-
256- //string bindingPath = firstBindingPathSegment + "/" + keys.First(); // TODO: Need to fix this.
257- string bindingPath = firstBindingPathSegment + "/" + secondBindingPathSegment;
258162
259163 string bindingTarget;
260164
261- if (singleton.NavigationPropertyBindings.TryGetValue(bindingPath, out bindingTarget))
165+ // The first assumption is that CSDL is added with a convention where the last path segment in NavigationPropertyBinding.Path
166+ // is named consistently in a singleton so it doesn't matter what the preceding segments are.
167+ // The second assumption is that if the last path is named consistently, the target will be consistent as well.
168+ // These may turn out to be a weak assumption. We use this assumption since we can't determine a unique path
169+ // for three or more segments since *RequestBuilder and *Request objects are generated per entity+navigation,
170+ // and not [entity+navigation]*n --> across multiple navigations.
171+ if (keys.Count() > 0 && singleton.NavigationPropertyBindings.TryGetValue(keys.First(), out bindingTarget))
262172 {
263173 // We found the target
264174 return "/" + bindingTarget;
0 commit comments