/// <summary> /// Resolve "StringFormat" and "String" into respective line arguments. /// </summary> /// <param name="previous"></param> /// <param name="parameterName"></param> /// <param name="parameterValue"></param> /// <param name="resolvedLineArgument"></param> /// <returns></returns> public bool TryResolveParameter(ILine previous, string parameterName, string parameterValue, out ILineArgument resolvedLineArgument) { if (parameterValue != null && parameterValue != "") { if (parameterName == "String") { IStringFormat stringFormat = previous.FindStringFormat() ?? CSharpFormat.Default; IString value = stringFormat.Parse(parameterValue); resolvedLineArgument = new LineArgument <ILineString, IString>(value); return(true); } else if (parameterName == "StringFormat") { IStringFormat stringFormat; if (TryResolve(parameterValue, out stringFormat)) { resolvedLineArgument = new LineArgument <ILineStringFormat, IStringFormat>(stringFormat); return(true); } } } resolvedLineArgument = default; return(false); }
/// <summary> /// Resolve "Culture" parameter into arguments. /// </summary> /// <param name="previous">(optional)</param> /// <param name="parameterName"></param> /// <param name="parameterValue"></param> /// <param name="resolvedLineArgument"></param> /// <returns></returns> public bool TryResolveParameter(ILine previous, string parameterName, string parameterValue, out ILineArgument resolvedLineArgument) { if (parameterValue != null && parameterValue != "" && parameterName == "Culture") { CultureInfo cultureInfo; if (TryResolve(parameterValue, out cultureInfo)) { resolvedLineArgument = new LineArgument <ILineCulture, CultureInfo>(cultureInfo); return(true); } } resolvedLineArgument = default; return(false); }
/// <summary> /// Resolve "Culture" parameter into arguments. /// </summary> /// <param name="previous">(optional)</param> /// <param name="parameterName"></param> /// <param name="parameterValue"></param> /// <param name="resolvedLineArgument"></param> /// <returns></returns> public bool TryResolveParameter(ILine previous, string parameterName, string parameterValue, out ILineArgument resolvedLineArgument) { if (parameterValue != null && parameterValue != "" && parameterName == "PluralRules") { IPluralRules value; if (TryResolve(parameterValue, out value)) { resolvedLineArgument = new LineArgument <ILinePluralRules, IPluralRules>(value); return(true); } } resolvedLineArgument = default; return(false); }
/// <summary> /// Add an enumeration of key,value pairs. Each key will constructed a new node. /// /// If <paramref name="groupingRule"/> the nodes are laid out in the order occurance of name pattern parts. /// /// For example grouping pattern "{Type}/{Culture}{anysection}{Key}" would order nodes as following: /// <code> /// "type:MyController": { /// "key:Success": "Success", /// "culture:en:key:Success": "Success", /// } /// </code> /// /// Non-capture parts such as "/" in pattern "{Section}/{Culture}", specify separator of tree node levels. /// /// </summary> /// <param name="tree"></param> /// <param name="lines"></param> /// <param name="groupingRule"></param> /// <param name="parameterInfos"></param> /// <returns></returns> public static ILineTree AddRange(this ILineTree tree, IEnumerable <ILine> lines, ILinePattern groupingRule, IParameterInfos parameterInfos) // Todo separate to sortRule + groupingRule { // Use another method //if (groupingRule == null) { node.AddRange(lines); return node; } StructList16 <ILineParameter> parameters = new StructList16 <ILineParameter>(null); foreach (var line in lines) { parameters.Clear(); line.GetParameterParts(ref parameters); parameterListSorter.Reverse(ref parameters); // Key for the current level. ILine levelKey = null; // Build levels with this collection List <ILine> key_levels = new List <ILine>(); // Visit both lists concurrently ILineParameter next_parameter = default; if (groupingRule != null) { foreach (var part in groupingRule.AllParts) { // Is not a capture part if (part.CaptureIndex < 0) { // Non-capture part has "/", go to next level. eg. "{nn}/{nn}" if (part.Text != null && part.Text.Contains("/")) { if (levelKey != null) { key_levels.Add(levelKey); } levelKey = null; } // Next part continue; } // Capture part has "/" in prefix, start next level if (levelKey != null && part.PrefixSeparator.Contains("/")) { if (levelKey != null) { key_levels.Add(levelKey); } levelKey = null; } // Look ahead to see if there is a parameter that matches this capture part int next_parameter_ix = -1; for (int ix = 0; ix < parameters.Count; ix++) { // Copy next_parameter = parameters[ix]; // Already added before if (next_parameter.ParameterName == null) { continue; } // Get name string parameter_name = next_parameter.ParameterName; // Parameter matches the name in the pattern's capture part if (parameter_name == part.ParameterName) { next_parameter_ix = ix; break; } // Matches with "anysection" //IParameterInfo info; //if (part.ParameterName == "anysection" && ParameterInfos.Default.TryGetValue(parameter_name, out info) && info.IsSection) { next_parameter_ix = ix; break; } } // No matching parameter for this capture part if (next_parameter_ix < 0) { continue; } // This part is canonical, hint, or parameter. if (!next_parameter.IsNonCanonicalKey(parameterInfos)) { // There (may be) are other canonical parts between part_ix and next_part_is. We have to add them here. for (int ix = 0; ix < next_parameter_ix; ix++) { // Copy ILineParameter parameter = parameters[ix]; // Has been added before if ((parameter.ParameterName == null) || parameter.IsNonCanonicalKey(parameterInfos)) { continue; } // Append to level's key levelKey = LineAppender.NonResolving.Create(levelKey, LineArgument.ToArgument(parameter)); // Mark handled parameters[ix] = unused; } } // Append to level's key levelKey = LineAppender.NonResolving.Create(levelKey, LineArgument.ToArgument(next_parameter)); // Mark handled parameters[next_parameter_ix] = unused; // Yield level if (part.PostfixSeparator.Contains("/")) { key_levels.Add(levelKey); levelKey = null; } } } // Append rest of the parameters for (int ix = 0; ix < parameters.Count; ix++) { // Copy ILineParameter parameter = parameters[ix]; if (parameter.ParameterName != null && parameter.ParameterName != "String") { levelKey = LineAppender.NonResolving.Create(levelKey, LineArgument.ToArgument(parameter)); } } // yield levelKey if (levelKey != null) { key_levels.Add(levelKey); levelKey = null; } // Yield line tree.AddRecursive(key_levels, line.GetString()); key_levels.Clear(); parameters.Clear(); } return(tree); }
/// <summary> /// Try append new <see cref="ILine"/> to <paramref name="previous"/>. /// </summary> /// <param name="factory"></param> /// <param name="previous">(optional) previous part</param> /// <param name="a0"></param> /// <param name="a1"></param> /// <param name="a2"></param> /// <param name="line">result</param> /// <typeparam name="Intf"></typeparam> /// <typeparam name="A0"></typeparam> /// <typeparam name="A1"></typeparam> /// <typeparam name="A2"></typeparam> /// <returns>true if succeeded</returns> public static bool TryCreate <Intf, A0, A1, A2>(this ILineFactory factory, ILine previous, A0 a0, A1 a1, A2 a2, out Intf line) where Intf : ILine { if (factory == null) { line = default; return(false); } Intf result = default; if (factory is ILineFactory <Intf, A0, A1, A2> _casted && _casted.TryCreate(factory, previous, a0, a1, a2, out result)) { line = result; return(true); } ILineFactory <Intf, A0, A1, A2> casted; if (factory is ILineFactoryCastable castable && (casted = castable.Cast <Intf, A0, A1, A2>()) != null && casted.TryCreate(factory, previous, a0, a1, a2, out result)) { line = result; return(true); } ILine result_ = null; if (factory is ILineFactoryByArgument __casted && __casted.TryCreate(factory, previous, LineArgument.Create <Intf, A0, A1, A2>(a0, a1, a2), out result_) && result_ is Intf result__) { line = result__; return(true); } line = default; return(false); }
/// <summary> /// Append new <see cref="ILine"/> to <paramref name="previous"/>. /// </summary> /// <param name="factory"></param> /// <param name="a0"></param> /// <param name="a1"></param> /// <param name="a2"></param> /// <param name="previous">(optional) previous part</param> /// <typeparam name="Intf"></typeparam> /// <typeparam name="A0"></typeparam> /// <typeparam name="A1"></typeparam> /// <typeparam name="A2"></typeparam> /// <returns>Line</returns> /// <exception cref="LineException">If part could not append <typeparamref name="Intf"/></exception> public static Intf Create <Intf, A0, A1, A2>(this ILineFactory factory, ILine previous, A0 a0, A1 a1, A2 a2) where Intf : ILine { if (factory == null) { throw new LineException(previous, "Appender is not found."); } Intf result = default; if (factory is ILineFactory <Intf, A0, A1, A2> _casted && _casted.TryCreate(factory, previous, a0, a1, a2, out result)) { return(result); } ILineFactory <Intf, A0, A1, A2> casted; if (factory is ILineFactoryCastable castable && (casted = castable.Cast <Intf, A0, A1, A2>()) != null && casted.TryCreate(factory, previous, a0, a1, a2, out result)) { return(result); } ILine result_ = null; if (factory is ILineFactoryByArgument __casted && __casted.TryCreate(factory, previous, LineArgument.Create <Intf, A0, A1, A2>(a0, a1, a2), out result_) && result_ is Intf result__) { return(result__); } throw new LineException(previous, $"Appender doesn't have capability to append {nameof(Intf)}."); }