/// <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); } }
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()); }
/// <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; } } }