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);
        }
Пример #2
0
        // 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);
        }