private static bool NextIteration(IServiceModel serviceModel, IEnumerator <string> urlPathSegmentsEnumerator, ICollection <IHypermediaPath> documentSelfPath) { // Parse for the next relationship CLR resource type represented as // either a to-many resource collection, to-many resource, or to-one resource // in the URL path. var previousResourceTypePath = documentSelfPath.Last(x => x.HasClrResourceType()); var previousClrResourceType = previousResourceTypePath.GetClrResourceType(); var previousResourceType = serviceModel.GetResourceType(previousClrResourceType); var relationship = default(IRelationshipInfo); var nonResourcePathSegments = default(List <string>); var pathSegmentToRelationshipDictionary = default(IDictionary <string, IRelationshipInfo>); while (urlPathSegmentsEnumerator.MoveNext()) { var currentUrlPathSegment = urlPathSegmentsEnumerator.Current; pathSegmentToRelationshipDictionary = pathSegmentToRelationshipDictionary ?? previousResourceType .RelationshipsInfo .Collection .ToDictionary(x => x.ApiRelPathSegment, StringComparer.OrdinalIgnoreCase); // Iterate over URL path segments until the current URL path segment // represents a relationship path segment. if (pathSegmentToRelationshipDictionary.TryGetValue(currentUrlPathSegment, out relationship)) { // Done iterating. break; } // Keep iterating. nonResourcePathSegments = nonResourcePathSegments ?? new List <string>(); nonResourcePathSegments.Add(currentUrlPathSegment); } // Add any non-resource path segments if needed. var nonResourcePathSegmentsFound = nonResourcePathSegments != null; if (nonResourcePathSegmentsFound) { var nonResourceTypePath = new NonResourceHypermediaPath(nonResourcePathSegments); documentSelfPath.Add(nonResourceTypePath); } // If no relationship path segments found, then done. var noRelationshipPathSegments = relationship == null; if (noRelationshipPathSegments) { return(false); } // Iterate one more URL path segment for a possible resource identifier. var clrResourceType = relationship.ToClrType; var apiRelationshipRelPathSegment = urlPathSegmentsEnumerator.Current; var apiRelationshipCardinality = relationship.ToCardinality; bool continueIterating; switch (apiRelationshipCardinality) { case RelationshipCardinality.ToOne: { continueIterating = true; var toOneResourcePath = new ToOneResourceHypermediaPath(clrResourceType, apiRelationshipRelPathSegment); documentSelfPath.Add(toOneResourcePath); } break; case RelationshipCardinality.ToMany: { var moreUrlPathSegments = urlPathSegmentsEnumerator.MoveNext(); continueIterating = moreUrlPathSegments; if (!moreUrlPathSegments) { var toManyResourceCollectionPath = new ToManyResourceCollectionHypermediaPath(clrResourceType, apiRelationshipRelPathSegment); documentSelfPath.Add(toManyResourceCollectionPath); } else { var apiId = urlPathSegmentsEnumerator.Current; var toManyResourcePath = new ToManyResourceHypermediaPath(clrResourceType, apiRelationshipRelPathSegment, apiId); documentSelfPath.Add(toManyResourcePath); } } break; default: { var detail = InfrastructureErrorStrings.InternalErrorExceptionDetailUnknownEnumerationValue .FormatWith(typeof(RelationshipCardinality).Name, apiRelationshipCardinality); throw new InternalErrorException(detail); } } return(continueIterating); }
private static bool InitialIteration(IServiceModel serviceModel, IEnumerator <string> urlPathSegmentsEnumerator, ICollection <IHypermediaPath> documentSelfPath) { // Parse for the initial CLR resource type represented as either // a resource or resource collection in the raw URL path. var resourceType = default(IResourceType); var clrResourceType = default(Type); var nonResourcePathSegments = default(List <string>); var pathSegmentToResourceTypeDictionary = default(IDictionary <string, IResourceType>); // Parse for initial resource or resource collection path objects. while (urlPathSegmentsEnumerator.MoveNext()) { var currentUrlPathSegment = urlPathSegmentsEnumerator.Current; pathSegmentToResourceTypeDictionary = pathSegmentToResourceTypeDictionary ?? serviceModel .ResourceTypes .ToDictionary(x => x.HypermediaInfo.ApiCollectionPathSegment, StringComparer.OrdinalIgnoreCase); // Iterate over URL path segments until the current URL path segment // represents a CLR resource collection path segment. if (pathSegmentToResourceTypeDictionary.TryGetValue(currentUrlPathSegment, out resourceType)) { // Done iterating. clrResourceType = resourceType.ClrType; break; } // Keep iterating. nonResourcePathSegments = nonResourcePathSegments ?? new List <string>(); nonResourcePathSegments.Add(currentUrlPathSegment); } // Add any non-resource path segments, if needed. var nonResourcePathSegmentsFound = nonResourcePathSegments != null; if (nonResourcePathSegmentsFound) { var nonResourceTypePath = new NonResourceHypermediaPath(nonResourcePathSegments); documentSelfPath.Add(nonResourceTypePath); } // If no CLR related resource path segments found, then done. var noClrResourcePathSegments = clrResourceType == null; if (noClrResourcePathSegments) { return(false); } // Take into account singleton resources. if (resourceType.IsSingleton()) { var apiSingletonPathSegment = urlPathSegmentsEnumerator.Current; var apiSingletonPath = new SingletonHypermediaPath(clrResourceType, apiSingletonPathSegment); documentSelfPath.Add(apiSingletonPath); return(true); } // Iterate one more URL path segment for a possible resource identifier. var apiCollectionPathSegment = urlPathSegmentsEnumerator.Current; var moreUrlPathSegments = urlPathSegmentsEnumerator.MoveNext(); if (!moreUrlPathSegments) { var resourceCollectionPath = new ResourceCollectionHypermediaPath(clrResourceType, apiCollectionPathSegment); documentSelfPath.Add(resourceCollectionPath); } else { var apiId = urlPathSegmentsEnumerator.Current; var resourcePath = new ResourceHypermediaPath(clrResourceType, apiCollectionPathSegment, apiId); documentSelfPath.Add(resourcePath); } return(moreUrlPathSegments); }