/// <summary>
        /// Query rules.
        ///
        /// If RuleSet is null, then returns null.
        /// </summary>
        /// <param name="filterCriteria"></param>
        /// <returns></returns>
        /// <exception cref="Exception">Wrapped error</exception>
        public IPluralRulesEnumerable Query(PluralRuleInfo filterCriteria)
        {
            if (filterCriteria.RuleSet == null)
            {
                return(null);
            }

            ResultLine line = GetRules(filterCriteria.RuleSet);

            if (line.Error != null)
            {
                throw new Exception(line.Error.Message, line.Error);
            }
            if (line.Rules == null)
            {
                return(null);
            }

            if (line.Rules is IPluralRulesQueryable queryable)
            {
                // Set RuleSet to null
                return(queryable.Query(filterCriteria.ChangeRuleSet(null)));
            }
            return(null);
        }
Example #2
0
        /// <summary>
        /// </summary>
        /// <param name="filterCriteria"></param>
        /// <returns></returns>
        public virtual IPluralRulesEnumerable Query(PluralRuleInfo filterCriteria)
        {
            if (filterCriteria.Equals(PluralRuleInfo.Empty))
            {
                return(this);
            }

            int c = 0;

            foreach (var rule in this)
            {
                if (filterCriteria.FilterMatch(rule.Info))
                {
                    c++;
                }
            }
            IPluralRule[] result = new IPluralRule[c];

            int i = 0;

            foreach (var rule in this)
            {
                if (filterCriteria.FilterMatch(rule.Info))
                {
                    result[i++] = rule;
                }
            }

            return(new PluralRulesArray(result));
        }
Example #3
0
 /// <summary>
 /// Evaluate <paramref name="number"/> against all rules in the scope stating from the last added.
 /// </summary>
 /// <param name="subset">RuleSet, Culture and Category must have non-null value. "" is valid. Case must be null and optional must be -1.</param>
 /// <param name="number">(optional) numeric and text representation of numberic value</param>
 /// <returns>Matching cases, first ones are optional, the last one is always mandatory (and only mandatory). Or null if evaluate failed.</returns>
 public                     IPluralRule[] Evaluate(PluralRuleInfo subset, IPluralNumber number)
 {
     for (int i = stack.Count - 1; i >= 0; i--)
     {
         if (stack[i] is IPluralRulesEvaluatable eval)
         {
             IPluralRule[] result = eval.Evaluate(subset, number);
             if (result != null)
             {
                 return(result);
             }
         }
     }
     // Could not evaluate.
     return(null);
 }
 /// <summary>
 /// Try to resolve ruleset and evaluate number.
 /// </summary>
 /// <param name="subset"></param>
 /// <param name="number"></param>
 /// <returns></returns>
 /// <exception cref="Exception">On wrapped error</exception>
 public IPluralRule[] Evaluate(PluralRuleInfo subset, IPluralNumber number)
 {
     if (subset.RuleSet != null)
     {
         ResultLine line = GetRules(subset.RuleSet);
         if (line.Error != null)
         {
             throw new Exception(line.Error.Message, line.Error);
         }
         if (line.Rules is IPluralRulesEvaluatable eval)
         {
             // Set RuleSet to null
             return(eval.Evaluate(subset.ChangeRuleSet(null), number));
         }
     }
     return(null);
 }
 /// <summary>
 /// If this info is a filter criteria, then tests whether <paramref name="info"/> matches the criteria.
 /// If any of the local fields is null, then that value is not compared.
 ///
 /// </summary>
 /// <param name="info"></param>
 /// <returns></returns>
 public bool FilterMatch(PluralRuleInfo info)
 {
     if (RuleSet != null && RuleSet != info.RuleSet)
     {
         return(false);
     }
     if (Category != null && Category != info.Category)
     {
         return(false);
     }
     if (Culture != null && Culture != info.Culture)
     {
         return(false);
     }
     if (Case != null && Case != info.Case)
     {
         return(false);
     }
     if (Optional != -1 && Optional != info.Optional)
     {
         return(false);
     }
     return(true);
 }
 /// <summary>
 /// Create rule that compares to zero value.
 /// </summary>
 /// <param name="info"></param>
 public One(PluralRuleInfo info) : base(info)
 {
 }
 /// <summary>
 /// Create rule that compares to zero value.
 /// </summary>
 /// <param name="info"></param>
 public Zero(PluralRuleInfo info) : base(info)
 {
 }
 /// <summary>
 /// Create rule that evaluates with <paramref name="ruleExpression"/>.
 /// </summary>
 /// <param name="info"></param>
 /// <param name="infoExpression">info expression</param>
 /// <param name="ruleExpression"></param>
 /// <param name="samplesExpression"></param>
 public Expression(PluralRuleInfo info, IPluralRuleInfosExpression infoExpression, IExpression ruleExpression, params ISamplesExpression[] samplesExpression) : base(info)
 {
     this.Infos   = infoExpression;
     this.Rule    = ruleExpression;
     this.Samples = samplesExpression ?? NO_SAMPLES;
 }
 /// <summary>
 /// Create rule.
 /// </summary>
 /// <param name="info">info</param>
 public PluralRule(PluralRuleInfo info)
 {
     this.Info = info;
 }
 /// <summary>
 /// Create rule that always evaluates to true.
 /// </summary>
 /// <param name="info"></param>
 /// <param name="infosExp"></param>
 /// <param name="ruleExp"></param>
 /// <param name="samplesExps"></param>
 public TrueWithExpression(PluralRuleInfo info, IPluralRuleInfosExpression infosExp, IExpression ruleExp, params ISamplesExpression[] samplesExps) : base(info)
 {
     this.Infos   = infosExp;
     this.Rule    = ruleExp;
     this.Samples = samplesExps;
 }
 /// <summary>
 /// Create rule that always evaluates to true.
 /// </summary>
 /// <param name="info"></param>
 public True(PluralRuleInfo info) : base(info)
 {
 }
 /// <summary>
 /// Create rule
 /// </summary>
 /// <param name="info"></param>
 public Empty(PluralRuleInfo info) : base(info)
 {
 }
Example #13
0
 /// <summary>
 /// Evaluate cases
 /// </summary>
 /// <param name="subset">filter</param>
 /// <param name="number"></param>
 /// <returns>matching cases. First ones are optional, last one is non-optional. Or null if none matched.</returns>
 public IPluralRule[] Evaluate(PluralRuleInfo subset, IPluralNumber number)
 => Query(subset) is IPluralRulesEvaluatable eval?eval.Evaluate(subset, number) : null;
Example #14
0
        /// <summary>
        /// Filter rules by <paramref name="filterCriteria"/>.
        /// </summary>
        /// <param name="filterCriteria"></param>
        /// <returns><see cref="PluralRulesCasesEvaluatable"/> or <see cref="PluralRulesArray"/>, or null if content is empty</returns>
        public IPluralRulesEnumerable Query(PluralRuleInfo filterCriteria)
        {
            // Try get
            IPluralRulesEnumerable result = null;

            lock (m_lock) if (queries.TryGetValue(filterCriteria, out result))
                {
                    return(result);
                }

            // Query
            if (ruleSource is IPluralRulesQueryable queryable)
            {
                result = queryable.Query(filterCriteria);
                // Wrap into PluralRulesEvaluatable
                if (result != null && filterCriteria.Category != null && filterCriteria.Culture != null && filterCriteria.Case == null && filterCriteria.Optional == -1)
                {
                    result = new PluralRulesCasesEvaluatable(result);
                }
            }
            else if (ruleSource is IEnumerable <IPluralRule> enumr)
            {
                // Filter rules
                StructList8 <IPluralRule> list     = new StructList8 <IPluralRule>();
                StructList8 <string>      rulesets = new StructList8 <string>();
                foreach (IPluralRule rule in enumr)
                {
                    // Filter by criteria
                    if (!filterCriteria.FilterMatch(rule.Info))
                    {
                        continue;
                    }
                    // Gather a list of rulesets
                    if (rule.Info.RuleSet != null && !rulesets.Contains(rule.Info.RuleSet))
                    {
                        rulesets.Add(rule.Info.RuleSet);
                    }
                    // Add to list
                    list.Add(rule);
                }
                // No result
                if (list.Count == 0)
                {
                    result = null;
                }
                // Instantiate PluralRulesEvaluatable
                else if (rulesets.Count <= 1 && filterCriteria.Category != null && filterCriteria.Culture != null && filterCriteria.Case == null && filterCriteria.Optional == -1)
                {
                    result = new PluralRulesCasesEvaluatable(list.ToArray());
                }
                // Instantiate PluralRules.
                else
                {
                    result = new PluralRulesArray(list.ToArray());
                }
            }
            // Could not read source
            else
            {
                result = null;
            }
            // Write to cache, if is still new
            lock (m_lock) if (!queries.ContainsKey(filterCriteria))
                {
                    queries[filterCriteria] = result;
                }

            // Return result
            return(result);
        }
Example #15
0
 /// <summary>
 /// Query a collection of rules.
 /// </summary>
 /// <param name="rules"></param>
 /// <param name="filterCriteria">filter criteria</param>
 /// <returns>enumerable of rules, or null if could not run query with the <paramref name="filterCriteria"/></returns>
 public static IPluralRulesEnumerable Query(this IPluralRules rules, PluralRuleInfo filterCriteria)
 => rules is IPluralRulesQueryable queryable?queryable.Query(filterCriteria) : null;
        /// <summary>
        /// Add placeholder and cases that apply to that placeholder.
        /// </summary>
        /// <param name="placeholder"></param>
        /// <param name="placeholderValue"></param>
        /// <param name="pluralRules"></param>
        /// <param name="culture"></param>
        public void AddPlaceholder(IPlaceholder placeholder, IPluralNumber placeholderValue, IPluralRules pluralRules, string culture)
        {
            IExpression e = placeholder?.Expression;

            if (e == null)
            {
                return;
            }

            // Query cases
            PluralRuleInfo query = new PluralRuleInfo(null, placeholder.PluralCategory, culture, null, -1);

            IPluralRule[] cases = pluralRules.Evaluate(query, placeholderValue);
            if (cases == null || cases.Length == 0)
            {
                return;
            }
            int optionalCount = cases.Length == 1 ? 0 : cases.Length - 1;
            int requiredCount = cases.Length > 0 ? 1 : 0;

            // Scan arguments
            StructList4 <int> argIndices = new StructList4 <int>();

            GetArguments(e, ref argIndices);

            // Add and unify cases
            for (int ix = 0; ix < argIndices.Count; ix++)
            {
                int argIx = argIndices[ix];

                // Find if argument already exists
                int prevIx = -1;
                for (int j = 0; j < arguments.Count; j++)
                {
                    if (arguments[j].ArgumentIndex == argIx)
                    {
                        prevIx = j; break;
                    }
                }

                if (prevIx < 0)
                {
                    // Add argument
                    Entry entry = new Entry {
                        Cases = cases, ArgumentIndex = argIx, OptionalCases = optionalCount, RequiredCases = requiredCount
                    };
                    arguments.Add(entry);
                    this.Count  *= (1 + cases.Length);
                    this.count1 *= cases.Length;
                }
                else
                {
                    // Previous entry
                    Entry entry = arguments[prevIx];
                    // Unify entries
                    StructList8 <IPluralRule> optionalCases = new StructList8 <IPluralRule>(IPluralRuleComparer.Default);
                    StructList8 <IPluralRule> requiredCases = new StructList8 <IPluralRule>(IPluralRuleComparer.Default);
                    foreach (var c in entry.Cases)
                    {
                        if (c.Info.Optional == 1)
                        {
                            optionalCases.AddIfNew(c);
                        }
                        else if (c.Info.Optional == 0)
                        {
                            requiredCases.AddIfNew(c);
                        }
                    }
                    foreach (var c in cases)
                    {
                        if (c.Info.Optional == 1)
                        {
                            optionalCases.AddIfNew(c);
                        }
                        else if (c.Info.Optional == 0)
                        {
                            requiredCases.AddIfNew(c);
                        }
                    }
                    StructList8 <IPluralRule> allCases = new StructList8 <IPluralRule>(IPluralRuleComparer.Default);
                    for (int i = 0; i < optionalCases.Count; i++)
                    {
                        allCases.Add(optionalCases[i]);
                    }
                    for (int i = 0; i < requiredCases.Count; i++)
                    {
                        allCases.Add(requiredCases[i]);
                    }

                    // Create new entry
                    Entry newEntry = new Entry {
                        Cases = allCases.ToArray(), ArgumentIndex = argIx, OptionalCases = optionalCases.Count, RequiredCases = requiredCases.Count
                    };

                    // Update
                    arguments[prevIx] = newEntry;

                    this.Count  /= (1 + entry.Cases.Length);
                    this.Count  *= (1 + newEntry.Cases.Length);
                    this.count1 /= entry.Cases.Length;
                    this.count1 *= newEntry.Cases.Length;
                }
            }
        }