/// <summary>Add a dynamic token value to the context.</summary>
        /// <param name="tokenValue">The token to add.</param>
        public void Add(DynamicTokenValue tokenValue)
        {
            // validate
            if (this.ParentContext.Contains(tokenValue.Name, enforceContext: false))
            {
                throw new InvalidOperationException($"Can't register a '{tokenValue}' token because there's a global token with that name.");
            }
            if (this.LocalContext.Contains(tokenValue.Name, enforceContext: false))
            {
                throw new InvalidOperationException($"Can't register a '{tokenValue.Name}' dynamic token because there's a config token with that name.");
            }

            // get (or create) token
            if (!this.DynamicContext.Tokens.TryGetValue(tokenValue.Name, out DynamicToken token))
            {
                this.DynamicContext.Save(token = new DynamicToken(tokenValue.Name, this.Scope));
            }

            // add token value
            token.AddTokensUsed(tokenValue.GetTokensUsed());
            token.AddAllowedValues(tokenValue.Value);
            this.DynamicTokenValues.Add(tokenValue);

            // track tokens which should trigger an update to this token
            Queue <string>   tokenQueue = new Queue <string>(tokenValue.GetTokensUsed());
            InvariantHashSet visited    = new InvariantHashSet();

            while (tokenQueue.Any())
            {
                // get token name
                string tokenName = tokenQueue.Dequeue();
                if (!visited.Add(tokenName))
                {
                    continue;
                }

                // if the current token uses other tokens, they may affect the being added too
                IToken curToken = this.GetToken(tokenName, enforceContext: false);
                foreach (string name in curToken.GetTokensUsed())
                {
                    tokenQueue.Enqueue(name);
                }
                if (curToken is DynamicToken curDynamicToken)
                {
                    foreach (string name in curDynamicToken.GetPossibleTokensUsed())
                    {
                        tokenQueue.Enqueue(name);
                    }
                }

                // add dynamic value as a dependency of the current token
                if (!this.TokenDependents.TryGetValue(curToken.Name, out InvariantHashSet used))
                {
                    this.TokenDependents.Add(curToken.Name, used = new InvariantHashSet());
                }
                used.Add(tokenValue.Name);
            }
        }
Exemple #2
0
        /// <summary>Add a dynamic token value to the context.</summary>
        /// <param name="name">The token name.</param>
        /// <param name="rawValue">The token value to set.</param>
        /// <param name="conditions">The conditions that must match to set this value.</param>
        public void AddDynamicToken(string name, IManagedTokenString rawValue, IEnumerable <Condition> conditions)
        {
            // validate
            if (this.ParentContext.Contains(name, enforceContext: false))
            {
                throw new InvalidOperationException($"Can't register a '{name}' token because there's a global token with that name.");
            }
            if (this.LocalContext.Contains(name, enforceContext: false))
            {
                throw new InvalidOperationException($"Can't register a '{name}' dynamic token because there's a config token with that name.");
            }

            // get (or create) token
            if (!this.DynamicTokens.TryGetValue(name, out ManagedManualToken managed))
            {
                managed = new ManagedManualToken(name, this.Scope);
                this.DynamicTokens[name] = managed;
                this.DynamicContext.Save(managed.Token);
            }

            // create token value handler
            var tokenValue = new DynamicTokenValue(managed, rawValue, conditions);

            string[] tokensUsed = tokenValue.GetTokensUsed().ToArray();

            // save value info
            managed.ValueProvider.AddTokensUsed(tokensUsed);
            managed.ValueProvider.AddAllowedValues(rawValue);
            this.DynamicTokenValues.Add(tokenValue);

            // track tokens which should trigger an update to this token
            Queue <string>   tokenQueue = new Queue <string>(tokensUsed);
            InvariantHashSet visited    = new InvariantHashSet();

            while (tokenQueue.Any())
            {
                // get token name
                string usedTokenName = tokenQueue.Dequeue();
                if (!visited.Add(usedTokenName))
                {
                    continue;
                }

                // if the used token uses other tokens, they may affect the one being added too
                IToken usedToken = this.GetToken(usedTokenName, enforceContext: false);
                foreach (string nextTokenName in usedToken.GetTokensUsed())
                {
                    tokenQueue.Enqueue(nextTokenName);
                }

                // add new token as a dependent of the used token
                if (!this.TokenDependents.TryGetValue(usedToken.Name, out InvariantHashSet used))
                {
                    this.TokenDependents.Add(usedToken.Name, used = new InvariantHashSet());
                }
                used.Add(name);
            }

            // track new token
            this.HasNewTokens = true;
        }