Esempio n. 1
0
        /// <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);
        }
Esempio n. 4
0
        /// <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)}.");
        }