private void Expand(RelationshipOrientedGraphNode node)
        {
            IEnumerable <EntityToken> nativeParentEntityTokens = SecurityAncestorFacade.GetParents(node.EntityToken);

            if (nativeParentEntityTokens != null)
            {
                nativeParentEntityTokens.ForEach(f => AddEntityToken(node, f));
            }


            IEnumerable <EntityToken> auxiliaryParentEntityTokens = AuxiliarySecurityAncestorFacade.GetParents(node.EntityToken);

            if (auxiliaryParentEntityTokens != null)
            {
                auxiliaryParentEntityTokens.ForEach(f => AddEntityToken(node, f));
            }


            IEnumerable <EntityToken> hookingParentEntityTokens = HookingFacade.GetHookies(node.EntityToken);

            if (hookingParentEntityTokens != null)
            {
                hookingParentEntityTokens.ForEach(f => AddEntityToken(node, f));
            }
        }
        private void ExpandNextLevel(string userName)
        {
            int levelNumber = _levels.Count - 1;

            if (levelNumber > 1000)
            {
                throw new InvalidOperationException($"The entity token '{_levels[0][0].EntityToken}' has more than 1000 levels of parents, this might be an infinite loop");
            }

            _moreLevelsToExpend = false;

            List <RelationshipGraphNode> nodes = _levels[levelNumber];

            if (nodes.Count > 1000)
            {
                throw new InvalidOperationException($"The entity token '{_levels[0][0].EntityToken}' has more than 1000 nodes at the level {levelNumber}, this might be an infinite loop");
            }


            foreach (RelationshipGraphNode node in nodes)
            {
                if (_searchOption == RelationshipGraphSearchOption.Native || _searchOption == RelationshipGraphSearchOption.Both)
                {
                    IEnumerable <EntityToken> parentEntityTokens;
                    if (!EntityTokenCacheFacade.GetCachedNativeParents(node.EntityToken, out parentEntityTokens, userName))
                    {
                        parentEntityTokens = SecurityAncestorFacade.GetParents(node.EntityToken)?.Evaluate();

                        EntityTokenCacheFacade.AddNativeCache(node.EntityToken, parentEntityTokens);
                    }

                    if (parentEntityTokens != null)
                    {
                        AddNewParentEntityTokens(node, parentEntityTokens, RelationshipGraphNodeType.Entity, levelNumber);
                    }
                }

                if (_searchOption == RelationshipGraphSearchOption.Hooked || _searchOption == RelationshipGraphSearchOption.Both)
                {
                    IEnumerable <EntityToken> parentEntityTokens;

                    if (!EntityTokenCacheFacade.GetCachedHookingParents(node.EntityToken, out parentEntityTokens, userName))
                    {
                        IEnumerable <EntityToken> auxiliaryParentEntityTokens = AuxiliarySecurityAncestorFacade.GetParents(node.EntityToken);
                        IEnumerable <EntityToken> hookingParentEntityTokens   = HookingFacade.GetHookies(node.EntityToken);

                        parentEntityTokens = auxiliaryParentEntityTokens.ConcatOrDefault(hookingParentEntityTokens)?.Evaluate();

                        EntityTokenCacheFacade.AddHookingCache(node.EntityToken, parentEntityTokens);
                    }

                    if (parentEntityTokens != null)
                    {
                        AddNewParentEntityTokens(node, parentEntityTokens, RelationshipGraphNodeType.Hooking, levelNumber);
                    }
                }
            }
        }
        /// <exclude />
        public string GetResult()
        {
            EntityTokenHtmlPrettyfierHelper helper = new EntityTokenHtmlPrettyfierHelper();

            helper.StartTable();
            helper.AddHeading("<b>Basic Information</b>");
            OnWriteEntityTokenType(this.EntityToken, helper);
            OnWriteType(this.EntityToken, helper);
            OnWriteSource(this.EntityToken, helper);
            OnWriteId(this.EntityToken, helper);

            var extraInfo = EntityToken.OnGetExtraPrettyHtml();

            if (!extraInfo.IsNullOrEmpty())
            {
                helper.AddFullRow(new[] { "<b>Extra</b>", extraInfo });
            }

            helper.AddHeading("<b>Custom Properties</b>");
            foreach (var kvp in _customProperties)
            {
                PropertyInfo propertyInfo = this.EntityToken.GetType().GetPropertiesRecursively().Single(f => f.Name == kvp.Key);
                kvp.Value(kvp.Key, propertyInfo.GetValue(this.EntityToken, null), helper);
            }


            helper.AddHeading("<b>Piggybag</b>");
            foreach (var kvp in this.PiggyBag)
            {
                OnPiggyBagEntry(kvp.Key, kvp.Value, helper);
            }

            helper.AddHeading("<b>SecurityAncestorProvider</b>");
            SecurityAncestorProviderAttribute attribute = this.EntityToken.GetType().GetCustomAttributesRecursively <SecurityAncestorProviderAttribute>().SingleOrDefault();

            OnWriteSecurityAncestorProvider(attribute, helper);


            helper.AddHeading("<b>AuxiliarySecurityAncestorProviders</b>");
            foreach (IAuxiliarySecurityAncestorProvider auxiliarySecurityAncestorProvider in AuxiliarySecurityAncestorFacade.GetAuxiliaryAncestorProviders(this.EntityToken.GetType()))
            {
                OnWriteAuxiliarySecurityAncestorProvider(auxiliarySecurityAncestorProvider, helper);
            }

            helper.EndTable();

            return(helper.GetResult());
        }