/// <summary>
            /// Creates a new <see cref="ResourceIdScope"/>
            /// </summary>
            /// <param name="pathSegments">The scope path segments</param>
            /// <param name="output">The scope output</param>
            public static bool TryParse(IEnumerable <string> pathSegments, out ResourceIdScope output)
            {
                output = null;

                var segmentLength = pathSegments.Count();

                if (segmentLength < 3 || segmentLength % 2 != 1)
                {
                    return(false);
                }

                output = ResourceIdScope.Create(
                    pathSegments.First(),
                    pathSegments.Skip(1).Where((_, i) => i % 2 == 0),
                    pathSegments.Skip(1).Where((_, i) => i % 2 == 1));
                return(true);
            }
        /// <summary>
        /// Parses resource scopes from a list of path segments
        /// </summary>
        /// <param name="pathSegments">The scope path segments</param>
        /// <param name="startIndex">The scope start index</param>
        /// <param name="routingScope">The scope</param>
        /// <param name="parentScopes">The parent scopes</param>
        protected static bool TryParseResourceScopes(IReadOnlyList <string> pathSegments, int startIndex, out ResourceIdScope routingScope, out IEnumerable <ResourceIdScope> parentScopes)
        {
            routingScope = null;
            parentScopes = null;

            var segmentLength = pathSegments.Count - startIndex;

            if (segmentLength < 2 || segmentLength % 2 != 0)
            {
                return(false);
            }

            var providerIndices = Enumerable.Range(startIndex, segmentLength).Where(i => i % 2 == 0 && StringComparer.OrdinalIgnoreCase.Equals(pathSegments[i], "providers"));

            if (!providerIndices.Any())
            {
                return(false);
            }

            var allScopes = providerIndices.Zip(
                providerIndices.Skip(1).Concat(new[] { pathSegments.Count }),
                (start, end) =>
            {
                var scopeSegments = pathSegments.Skip(start + 1).Take(end - start - 1);
                ResourceIdScope scope;
                if (!ResourceIdScope.TryParse(scopeSegments, out scope))
                {
                    return(null);
                }

                return(scope);
            });

            if (allScopes.Any(scope => scope == null))
            {
                return(false);
            }

            routingScope = allScopes.Last();
            parentScopes = allScopes.Take(allScopes.Count() - 1);
            return(true);
        }
 /// <summary>
 /// Enumerates the parent resource Ids
 /// </summary>
 /// <param name="orderByDepthAscending">Order by depth ascending?</param>
 public IEnumerable <ResourceIdScope> GetParents(bool orderByDepthAscending)
 {
     if (orderByDepthAscending)
     {
         for (var i = 1; i < this.TypeHierarchy.Count; i++)
         {
             yield return(ResourceIdScope.Create(
                              providerNamespace: this.ProviderNamespace,
                              typeHierarchy: this.TypeHierarchy.Take(i),
                              nameHierarchy: this.NameHierarchy.Take(i)));
         }
     }
     else
     {
         for (var i = this.TypeHierarchy.Count - 1; i > 0; i--)
         {
             yield return(ResourceIdScope.Create(
                              providerNamespace: this.ProviderNamespace,
                              typeHierarchy: this.TypeHierarchy.Take(i),
                              nameHierarchy: this.NameHierarchy.Take(i)));
         }
     }
 }
 /// <summary>
 /// Formats a subscription-level resource Id
 /// </summary>
 /// <param name="subscriptionId">The subscription Id</param>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 private static string FormatResourceId(string subscriptionId, ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes)
 => $"/subscriptions/{subscriptionId}/providers/{ResourceId.FormatUnqualifiedId(routingScope, parentScopes)}";
 /// <summary>
 /// Initializes a new instance of the <see cref="SubscriptionLevelResourceId"/> class
 /// </summary>
 /// <param name="subscriptionId">The subscription Id</param>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 private SubscriptionLevelResourceId(string subscriptionId, ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes)
     : base(routingScope, parentScopes, SubscriptionLevelResourceId.FormatResourceId(subscriptionId, routingScope, parentScopes))
 {
     this.SubscriptionId = subscriptionId;
 }
 /// <summary>
 /// Formats the unqualified id string
 /// </summary>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 protected static string FormatUnqualifiedId(ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes)
 => parentScopes.Select(s => s.FormatUnqualifiedId()).Concat(new[] { routingScope.FormatUnqualifiedId() }).ConcatStrings("/providers/");
 /// <summary>
 /// Initializes a new instance of the <see cref="ResourceId"/> class
 /// </summary>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 /// <param name="fullyQualifiedId">The fully-qualified resource Id</param>
 protected ResourceId(ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes, string fullyQualifiedId)
 {
     this.RoutingScope     = routingScope;
     this.ParentScopes     = parentScopes;
     this.FullyQualifiedId = fullyQualifiedId;
 }
 /// <summary>
 /// Generates a child resource Id
 /// </summary>
 /// <param name="nestedType">The last segment of the child resource type</param>
 /// <param name="nestedName">The last segment of the child resource name</param>
 public ResourceIdScope GetChild(string nestedType, string nestedName)
 => ResourceIdScope.Create(
     providerNamespace: this.ProviderNamespace,
     typeHierarchy: this.TypeHierarchy.Concat(new[] { nestedType }),
     nameHierarchy: this.NameHierarchy.Concat(new[] { nestedName }));
 /// <summary>
 /// Formats a tenant-level resource Id
 /// </summary>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 private static string FormatResourceId(ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes)
 => $"/providers/{ResourceId.FormatUnqualifiedId(routingScope, parentScopes)}";
 /// <summary>
 /// Initializes a new instance of the <see cref="TenantLevelResourceId"/> class
 /// </summary>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 private TenantLevelResourceId(ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes)
     : base(routingScope, parentScopes, TenantLevelResourceId.FormatResourceId(routingScope, parentScopes))
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ResourceGroupLevelResourceId"/> class
 /// </summary>
 /// <param name="subscriptionId">The subscription Id</param>
 /// <param name="resourceGroup">The resource group</param>
 /// <param name="routingScope">The routing scope</param>
 /// <param name="parentScopes">The parent scopes</param>
 private ResourceGroupLevelResourceId(string subscriptionId, string resourceGroup, ResourceIdScope routingScope, IEnumerable <ResourceIdScope> parentScopes)
     : base(routingScope, parentScopes, ResourceGroupLevelResourceId.FormatResourceId(subscriptionId, resourceGroup, routingScope, parentScopes))
 {
     this.SubscriptionId = subscriptionId;
     this.ResourceGroup  = resourceGroup;
 }
 /// <summary>
 /// Creates a new <see cref="TenantLevelResourceId"/>
 /// </summary>
 /// <param name="subscriptionId">The subscription Id</param>
 /// <param name="resourceGroup">The resource group</param>
 /// <param name="providerNamespace">The provider namespace</param>
 /// <param name="typeHierarchy">The type hierarchy</param>
 /// <param name="nameHierarchy">The name hierarchy</param>
 public static ResourceGroupLevelResourceId Create(string subscriptionId, string resourceGroup, string providerNamespace, IEnumerable <string> typeHierarchy, IEnumerable <string> nameHierarchy)
 => new ResourceGroupLevelResourceId(subscriptionId, resourceGroup, ResourceIdScope.Create(providerNamespace, typeHierarchy, nameHierarchy), Enumerable.Empty <ResourceIdScope>());