/// <summary> /// Evaluate placeholders into string values. /// </summary> /// <param name="line">original requesting line</param> /// <param name="resolvedLine">(optional Line that was matched from IAsset or inlines</param> /// <param name="pluralLine">(optional) Line that was matched from IAsset or inlines for plural value</param> /// <param name="placeholders"></param> /// <param name="features">contextual data</param> /// <param name="placeholder_values">collection where strings are placed, one for each placeholder</param> /// <param name="culture">the culture in which to evaluate</param> void EvaluatePlaceholderValues(ILine line, ILine resolvedLine, ILine pluralLine, IPlaceholder[] placeholders, ref LineFeatures features, ref StructList12 <string> placeholder_values, CultureInfo culture) { PlaceholderExpressionEvaluator placeholder_evaluator = new PlaceholderExpressionEvaluator(); placeholder_evaluator.Args = features.ValueArgs; placeholder_evaluator.FunctionEvaluationCtx.Culture = culture; placeholder_evaluator.FunctionEvaluationCtx.Line = line; placeholder_evaluator.FunctionEvaluationCtx.ResolvedLine = resolvedLine; placeholder_evaluator.FunctionEvaluationCtx.PluralLine = pluralLine; placeholder_evaluator.FunctionEvaluationCtx.StringResolver = this; placeholder_evaluator.FunctionEvaluationCtx.EnumResolver = EnumResolver; if (features.FormatProviders.Count == 1) { placeholder_evaluator.FunctionEvaluationCtx.FormatProvider = features.FormatProviders[0]; } else if (features.FormatProviders.Count > 1) { placeholder_evaluator.FunctionEvaluationCtx.FormatProvider = new FormatProviderComposition(features.FormatProviders.ToArray()); } if (features.Functions.Count == 1) { placeholder_evaluator.FunctionEvaluationCtx.Functions = features.Functions[0]; } else if (features.Functions.Count > 1) { placeholder_evaluator.FunctionEvaluationCtx.Functions = new FunctionsMap(features.Functions); } for (int i = 0; i < placeholders.Length; i++) { try { // Get placeholder IPlaceholder ph = placeholders[i]; // Evaluate value string ph_value = placeholder_evaluator.toString(placeholder_evaluator.Evaluate(ph.Expression)); // Add to array placeholder_values.Add(ph_value); // Update code features.Status.UpPlaceholder(placeholder_evaluator.Status); } catch (Exception e) { // Log exceptions features.Log(e); // Mark error features.Status.UpPlaceholder(LineStatus.PlaceholderErrorExpressionEvaluation); // Put empty value placeholder_values.Add(null); } } }
/// <summary> /// Try parse <paramref name="str"/> into parameters. /// </summary> /// <param name="str"></param> /// <param name="parameters"></param> /// <returns></returns> public override bool TryParse(string str, ref StructList12 <KeyValuePair <string, string> > parameters) { if (str == null) { return(false); } MatchCollection matches = ParsePattern.Matches(str); foreach (Match m in matches) { if (!m.Success) { return(false); } Group k_key = m.Groups["key"], k_value = m.Groups["value"]; if (!k_key.Success || !k_value.Success) { return(false); } string parameterName = UnescapeLiteral(k_key.Value); string parameterValue = UnescapeLiteral(k_value.Value); parameters.Add(new KeyValuePair <string, string>(parameterName, parameterValue)); } return(true); }
/// <summary> /// Prune out arguments that are disqualified by <paramref name="qualifier"/>. /// </summary> /// <param name="line"></param> /// <param name="qualifier">Argument qualifier that is used for determining which parts to keep in the line</param> /// <param name="lineFactory">(optional) extra line factory</param> /// <returns>a modified <paramref name="line"/></returns> /// <exception cref="LineException"></exception> public static ILine Prune(this ILine line, ILineQualifier qualifier, ILineFactory lineFactory = null) { // Qualified parts to append. Order: tail to root. StructList12 <ILineArgument> list = new StructList12 <ILineArgument>(); ILineArgumentQualifier lineArgumentQualifier = qualifier as ILineArgumentQualifier; // Earliest qualified line part. The start tail, where to start appending qualified parts ILine startTail = line; // Line part's arguments. Order: root to tail StructList8 <ILineArgument> tmp = new StructList8 <ILineArgument>(); // Start tail buffered args. Order: root to tail StructList8 <ILineArgument> startTailArgsBuffer = new StructList8 <ILineArgument>(); // Add parts for (ILine l = line; l != null; l = l.GetPreviousPart()) { tmp.Clear(); if (l is ILineArgumentEnumerable lineArguments) { foreach (ILineArgument lineArgument in lineArguments) { tmp.Add(lineArgument); } } if (l is ILineArgument argument) { tmp.Add(argument); } // Now qualify bool linePartQualifies = true; string parameterName, parameterValue; for (int i = tmp.Count - 1; i >= 0; i--) { ILineArgument a = tmp[i]; bool argumentQualifies = true; if (lineArgumentQualifier != null) { // Qualify as an argument. if (!a.IsNonCanonicalKey()) { argumentQualifies = lineArgumentQualifier.QualifyArgument(a); } // Qualify as non-canonical parameter else if (a.TryGetParameter(out parameterName, out parameterValue)) { // Calculate occurance index int occIx = -1; if (lineArgumentQualifier.NeedsOccuranceIndex) { occIx = 0; for (int j = i - 1; j >= 0; j--) { ILineArgument b = list[j]; string parameterName2, parameterValue2; if (b.TryGetParameter(out parameterName2, out parameterValue2)) { continue; } if (parameterValue2 != null && parameterName == parameterName2) { occIx++; } } } argumentQualifies = lineArgumentQualifier.QualifyArgument(a, occIx); } } if (!argumentQualifies) { tmp.RemoveAt(i); } linePartQualifies &= argumentQualifies; } // This part didn't qualify if (!linePartQualifies) { // Append previous start tail to append args if (startTailArgsBuffer.Count > 0) { for (int i = 0; i < startTailArgsBuffer.Count; i++) { list.Add(startTailArgsBuffer[i]); } startTailArgsBuffer.Clear(); startTail = null; } // Add parts that did qualify to append list for (int i = 0; i < tmp.Count; i++) { list.Add(tmp[i]); } // preceding part might be better for start tail startTail = l.GetPreviousPart(); } else // This part qualified { // Add to start tail buffer, in case preceding startTail fails qualifications for (int i = 0; i < tmp.Count; i++) { startTailArgsBuffer.Add(tmp[i]); } } } // Append qualified parts. ILineFactory appender1 = null; line.TryGetAppender(out appender1); // Nothing qualified, no start, create dummy if (startTail == null && list.Count == 0) { // Create dummy ILineFactory appender2 = null; line.TryGetAppender(out appender2); ILinePart dummy = null; if (lineFactory == null || !lineFactory.TryCreate(null, out dummy)) { if (appender2 == null || !appender2.TryCreate(null, out dummy)) { throw new LineException(line, $"LineFactory doesn't have capability to create {nameof(ILinePart)}"); } } return(dummy); } // Append parts ILine result = startTail; for (int i = list.Count - 1; i >= 0; i--) { ILineArgument arg = list[i]; if (lineFactory == null || !lineFactory.TryCreate(result, arg, out result)) { if (appender1 == null || !appender1.TryCreate(result, arg, out result)) { throw new LineException(line, $"LineFactory doesn't have capability to concat {arg}"); } } } return(result); }
/// <summary> /// Forward event /// </summary> /// <param name="sender"></param> void OnEvent(object sender) { var _observer = Observer; if (_observer == null) { return; } // Create new token if (!IsDisposing) { this.changeToken = FileProvider.Watch(Filter); } // Get new snapshot DateTimeOffset time = DateTimeOffset.UtcNow; Dictionary <string, IEntry> newSnapshot = ReadSnapshot(); // List of events StructList12 <IEvent> events = new StructList12 <IEvent>(); // Find adds foreach (KeyValuePair <string, IEntry> newEntry in newSnapshot) { string path = newEntry.Key; // Find matching previous entry IEntry prevEntry; if (previousSnapshot.TryGetValue(path, out prevEntry)) { // Send change event if (!EntryComparer.PathDateLengthTypeEqualityComparer.Equals(newEntry.Value, prevEntry)) { events.Add(new ChangeEvent(this, time, path)); } } // Send create event else { events.Add(new CreateEvent(this, time, path)); } } // Find Deletes foreach (KeyValuePair <string, IEntry> oldEntry in previousSnapshot) { string path = oldEntry.Key; if (!newSnapshot.ContainsKey(path)) { events.Add(new DeleteEvent(this, time, path)); } } // Replace entires previousSnapshot = newSnapshot; // Dispatch events if (events.Count > 0) { ((FileSystemBase)this.FileSystem).DispatchEvents(ref events); } // Start watching again if (!IsDisposing) { this.watcher = changeToken.RegisterChangeCallback(OnEvent, this); } }