/// <summary>
        /// Creates a line factory that is specialized for handling <see cref="ILineArgument"/> of specific implementing <paramref name="argumentType"/>.
        /// </summary>
        /// <param name="argumentType">Argument class that implements <see cref="ILineArgument"/> once or more than once</param>
        /// <returns>Factory that forwards calls for the specific <paramref name="argumentType"/> or null</returns>
        /// <exception cref="LineException">If adapter construction fails</exception>
        public ILineFactoryByArgument Build(Type argumentType)
        {
            try
            {
                StructList8 <ILineFactoryByArgument> factories = new StructList8 <ILineFactoryByArgument>();

                Type[] intfs = argumentType.GetInterfaces();
                foreach (Type intf in intfs)
                {
                    if (!intf.IsGenericType)
                    {
                        continue;
                    }
                    Type intfGeneric = intf.GetGenericTypeDefinition();
                    if (intfGeneric == null)
                    {
                        continue;
                    }
                    Type[] typeArgs = intf.GetGenericArguments();

                    // ILineArgument<>
                    if (intfGeneric == typeof(ILineArgument <>))
                    {
                        factories.Add(Activator.CreateInstance(typeof(Adapter <>).MakeGenericType(typeArgs)) as ILineFactoryByArgument);
                    }
                    // ILineArgument<,>
                    else if (intfGeneric == typeof(ILineArgument <,>))
                    {
                        factories.Add(Activator.CreateInstance(typeof(Adapter <,>).MakeGenericType(typeArgs)) as ILineFactoryByArgument);
                    }
                    // ILineArgument<,,>
                    else if (intfGeneric == typeof(ILineArgument <, ,>))
                    {
                        factories.Add(Activator.CreateInstance(typeof(Adapter <, ,>).MakeGenericType(typeArgs)) as ILineFactoryByArgument);
                    }
                    // ILineArgument<,,,>
                    else if (intfGeneric == typeof(ILineArgument <, , ,>))
                    {
                        factories.Add(Activator.CreateInstance(typeof(Adapter <, ,>).MakeGenericType(typeArgs)) as ILineFactoryByArgument);
                    }
                }

                if (factories.Count == 0)
                {
                    return(null);
                }
                if (factories.Count == 1)
                {
                    return(factories[0]);
                }
                return(new Factories(factories.ToArray()));
            }
            catch (Exception e)
            {
                throw new LineException(null, e.Message, e);
            }
        }
예제 #2
0
        static CultureInfo[] MakeArray(CultureInfo culture)
        {
            StructList8 <CultureInfo> result = new StructList8 <CultureInfo>();

            for (CultureInfo ci = culture; ci != null; ci = ci.Parent)
            {
                if (result.Contains(ci))
                {
                    break;
                }
                else
                {
                    result.Add(ci);
                }
            }
            return(result.ToArray());
        }
예제 #3
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);
        }
        /// <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;
                }
            }
        }