Ejemplo n.º 1
0
        /// <summary>Normalise and parse the given condition values.</summary>
        /// <param name="raw">The raw condition values to normalise.</param>
        /// <param name="tokenContext">The tokens available for this content pack.</param>
        /// <param name="formatVersion">The format version specified by the content pack.</param>
        /// <param name="latestFormatVersion">The latest format version.</param>
        /// <param name="minumumTokenVersions">The minimum format versions for newer condition types.</param>
        /// <param name="conditions">The normalised conditions.</param>
        /// <param name="error">An error message indicating why normalisation failed.</param>
        private bool TryParseConditions(InvariantDictionary <string> raw, IContext tokenContext, ISemanticVersion formatVersion, ISemanticVersion latestFormatVersion, InvariantDictionary <ISemanticVersion> minumumTokenVersions, out ConditionDictionary conditions, out string error)
        {
            conditions = new ConditionDictionary();

            // no conditions
            if (raw == null || !raw.Any())
            {
                error = null;
                return(true);
            }

            // parse conditions
            foreach (KeyValuePair <string, string> pair in raw)
            {
                // parse condition key
                if (!TokenName.TryParse(pair.Key, out TokenName name))
                {
                    error      = $"'{pair.Key}' isn't a valid token name";
                    conditions = null;
                    return(false);
                }

                // get token
                IToken token = tokenContext.GetToken(name, enforceContext: false);
                if (token == null)
                {
                    error      = $"'{pair.Key}' isn't a valid condition; must be one of {string.Join(", ", tokenContext.GetTokens(enforceContext: false).Select(p => p.Name).OrderBy(p => p))}";
                    conditions = null;
                    return(false);
                }

                // validate subkeys
                if (!token.CanHaveSubkeys)
                {
                    if (name.HasSubkey())
                    {
                        error      = $"{name.Key} conditions don't allow subkeys (:)";
                        conditions = null;
                        return(false);
                    }
                }
                else if (token.RequiresSubkeys)
                {
                    if (!name.HasSubkey())
                    {
                        error      = $"{name.Key} conditions must specify a token subkey (see readme for usage)";
                        conditions = null;
                        return(false);
                    }
                }

                // check compatibility
                if (minumumTokenVersions.TryGetValue(name.Key, out ISemanticVersion minVersion) && minVersion.IsNewerThan(formatVersion))
                {
                    error      = $"{name} isn't available with format version {formatVersion} (change the {nameof(ContentConfig.Format)} field to {latestFormatVersion} to use newer features)";
                    conditions = null;
                    return(false);
                }

                // parse values
                InvariantHashSet values = this.ParseCommaDelimitedField(pair.Value);
                if (!values.Any())
                {
                    error      = $"{name} can't be empty";
                    conditions = null;
                    return(false);
                }

                // restrict to allowed values
                InvariantHashSet rawValidValues = token.GetAllowedValues(name);
                if (rawValidValues?.Any() == true)
                {
                    InvariantHashSet validValues = new InvariantHashSet(rawValidValues);
                    {
                        string[] invalidValues = values.ExceptIgnoreCase(validValues).ToArray();
                        if (invalidValues.Any())
                        {
                            error      = $"invalid {name} values ({string.Join(", ", invalidValues)}); expected one of {string.Join(", ", validValues)}";
                            conditions = null;
                            return(false);
                        }
                    }
                }

                // perform custom validation
                if (!token.TryCustomValidation(values, out string customError))
                {
                    error      = $"invalid {name} values: {customError}";
                    conditions = null;
                    return(false);
                }

                // create condition
                conditions[name] = new Condition(name, values);
            }

            // return parsed conditions
            error = null;
            return(true);
        }