private static Tuple <ICollection <IHypermediaPath>, ResourcePathMode> CreateResourcePathParts(Type clrResourceType, IResourceType resourceType, ICollection <IHypermediaPath> resourceBasePath, IRelationshipInfo resourcePreviousRelationship) { Contract.Requires(clrResourceType != null); Contract.Requires(resourceType != null); ResourcePathMode resourcePathMode; if (resourcePreviousRelationship == null) { var apiCollectionPathSegment = resourceType.HypermediaInfo.ApiCollectionPathSegment; var hypermediaPath = default(IHypermediaPath); if (!resourceType.IsSingleton()) { hypermediaPath = new ResourceCollectionHypermediaPath(clrResourceType, apiCollectionPathSegment); resourcePathMode = ResourcePathMode.IncludeApiId; } else { hypermediaPath = new SingletonHypermediaPath(clrResourceType, apiCollectionPathSegment); resourcePathMode = ResourcePathMode.IgnoreApiId; } resourceBasePath.Add(hypermediaPath); } else { var previousRelationshipCardinality = resourcePreviousRelationship.ToCardinality; var apiRelationshipRelPathSegment = resourcePreviousRelationship.ApiRelPathSegment; switch (previousRelationshipCardinality) { case RelationshipCardinality.ToOne: { var toOneResourceHypermediaPath = new ToOneResourceHypermediaPath(clrResourceType, apiRelationshipRelPathSegment); resourceBasePath.Add(toOneResourceHypermediaPath); resourcePathMode = ResourcePathMode.IgnoreApiId; } break; case RelationshipCardinality.ToMany: { var toManyResourceHypermediaPath = new ToManyResourceCollectionHypermediaPath(clrResourceType, apiRelationshipRelPathSegment); resourceBasePath.Add(toManyResourceHypermediaPath); resourcePathMode = ResourcePathMode.IncludeApiId; } break; default: { var detail = InfrastructureErrorStrings.InternalErrorExceptionDetailUnknownEnumerationValue .FormatWith(typeof(RelationshipCardinality).Name, previousRelationshipCardinality); throw new InternalErrorException(detail); } } } var resourcePathParts = new Tuple <ICollection <IHypermediaPath>, ResourcePathMode>(resourceBasePath, resourcePathMode); return(resourcePathParts); }
// PRIVATE METHODS ////////////////////////////////////////////////// #region Methods private static Link CreateStandardDocumentLink(IHypermediaContext hypermediaContext, IDocumentPathContext documentPathContext, ILinkContext linkContext) { Contract.Requires(hypermediaContext != null); Contract.Requires(documentPathContext != null); Contract.Requires(linkContext != null); var apiRel = linkContext.Rel; var apiLinkMeta = linkContext.Meta; switch (apiRel) { case Keywords.Up: { var apiDocumentSelfPath = documentPathContext.DocumentSelfPath .SafeToList(); var apiDocumentSelfPathCount = apiDocumentSelfPath.Count; var apiDocumentUpPath = new List <IHypermediaPath>(apiDocumentSelfPathCount); for (var i = 0; i < apiDocumentSelfPathCount; ++i) { var hypermediaPath = apiDocumentSelfPath[i]; var lastHypermediaPath = i == apiDocumentSelfPathCount - 1; if (lastHypermediaPath) { var hypermediaPathType = hypermediaPath.HypermediaPathType; switch (hypermediaPathType) { // Don't add the last hypermedia path. case HypermediaPathType.ResourceCollectionPath: case HypermediaPathType.ToOneResourcePath: case HypermediaPathType.ToManyResourceCollectionPath: case HypermediaPathType.NonResourcePath: case HypermediaPathType.SingletonPath: continue; case HypermediaPathType.ResourcePath: { // Turn last resource path into a resource collection path. var resourceHypermediaPath = (ResourceHypermediaPath)hypermediaPath; var clrResourceType = resourceHypermediaPath.ClrResourceType; var apiCollectionPathSegment = resourceHypermediaPath.ApiCollectionPathSegment; var resourceCollectionHypermediaPath = new ResourceCollectionHypermediaPath(clrResourceType, apiCollectionPathSegment); hypermediaPath = resourceCollectionHypermediaPath; } break; case HypermediaPathType.ToManyResourcePath: { // Turn last resource path into a to-many resource collection path. var toManyResourceHypermediaPath = (ToManyResourceHypermediaPath)hypermediaPath; var clrResourceType = toManyResourceHypermediaPath.ClrResourceType; var apiRelationshipPathSegment = toManyResourceHypermediaPath.ApiRelationshipPathSegment; var toManyResourceCollectionHypermediaPath = new ToManyResourceCollectionHypermediaPath(clrResourceType, apiRelationshipPathSegment); hypermediaPath = toManyResourceCollectionHypermediaPath; } break; default: throw new ArgumentOutOfRangeException(); } } apiDocumentUpPath.Add(hypermediaPath); } if (apiDocumentUpPath.Any() == false) { return(null); } var apiDocumentUpPathContext = new DocumentPathContext(apiDocumentUpPath); var clrPrimaryResourceType = apiDocumentUpPathContext.ClrResourceTypes.Any() ? apiDocumentUpPathContext.GetPrimaryClrResourceType() : documentPathContext.GetPrimaryClrResourceType(); var urlBuilderConfiguration = hypermediaContext.GetUrlBuilderConfiguration(clrPrimaryResourceType); var apiHRef = UrlBuilder.Create(urlBuilderConfiguration) .Path(apiDocumentUpPath) .Build(); var apiDocumentLink = new Link { HRef = apiHRef, Meta = apiLinkMeta }; return(apiDocumentLink); } case Keywords.Self: { // Get the resource type that generated this document. var clrSelfResourceType = documentPathContext.GetPrimaryClrResourceType(); var apiDocumentSelfPath = documentPathContext.DocumentSelfPath.SafeToReadOnlyCollection(); var apiDocumentSelfPathClrTypesOnly = apiDocumentSelfPath.Where(x => x.HasClrResourceType()) .ToList(); var apiDocumentSelfPathClrTypesOnlyCount = apiDocumentSelfPathClrTypesOnly.Count; if (apiDocumentSelfPathClrTypesOnlyCount > 1) { var lastHypermediaPath = apiDocumentSelfPathClrTypesOnly[apiDocumentSelfPathClrTypesOnlyCount - 1]; var lastHypermediaPathType = lastHypermediaPath.HypermediaPathType; switch (lastHypermediaPathType) { case HypermediaPathType.ToOneResourcePath: case HypermediaPathType.ToManyResourceCollectionPath: { var nextToLastHypermediaPath = apiDocumentSelfPathClrTypesOnly[apiDocumentSelfPathClrTypesOnlyCount - 2]; clrSelfResourceType = nextToLastHypermediaPath.GetClrResourceType(); break; } } } var urlBuilderConfiguration = hypermediaContext.GetUrlBuilderConfiguration(clrSelfResourceType); var query = documentPathContext.DocumentSelfQuery; var apiHRef = UrlBuilder.Create(urlBuilderConfiguration) .Path(apiDocumentSelfPath) .Query(query) .Build(); var apiDocumentLink = new Link { HRef = apiHRef, Meta = apiLinkMeta }; return(apiDocumentLink); } } return(null); }