private void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool firstVariable, bool firstElement) { if (builder == null) { throw new ArgumentNullException("builder"); } if (variableValue == null) { throw new ArgumentNullException("variableValue"); } if (firstElement || variable.Composite) { builder.Append(Type == UriTemplatePartType.Query && firstVariable && firstElement ? '?' : '&').Append(variable.Name).Append('='); } else if (!firstElement) { builder.Append(','); } AppendText(builder, variable, variableValue.ToString(), true); }
private void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool firstVariable, bool firstElement) { if (builder == null) { throw new ArgumentNullException("builder"); } if (variableValue == null) { throw new ArgumentNullException("variableValue"); } if (firstElement || variable.Composite) { builder.Append('.'); } else if (!firstElement) { builder.Append(','); } AppendText(builder, variable, variableValue.ToString(), true); }
protected override void RenderDictionary(StringBuilder builder, VariableReference variable, IDictionary variableValue, bool first) { bool firstElement = true; foreach (DictionaryEntry entry in variableValue) { if (variable.Composite) { builder.Append(Type == UriTemplatePartType.Query && first && firstElement ? '?' : '&'); AppendText(builder, variable, entry.Key.ToString(), true); builder.Append('='); AppendText(builder, variable, entry.Value.ToString(), true); } else { RenderElement(builder, variable, entry.Key, first, firstElement); RenderElement(builder, variable, entry.Value, first, false); } firstElement = false; } }
protected override void RenderDictionary(StringBuilder builder, VariableReference variable, IDictionary variableValue, bool first) { foreach (DictionaryEntry entry in variableValue) { if (variable.Composite) { if (!first) { builder.Append(','); } AppendText(builder, variable, entry.Key.ToString(), _escapeReserved); builder.Append('='); AppendText(builder, variable, entry.Value.ToString(), _escapeReserved); } else { RenderElement(builder, variable, entry.Key, first); RenderElement(builder, variable, entry.Value, false); } first = false; } }
private void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool firstVariable, bool firstElement) { if (builder == null) throw new ArgumentNullException("builder"); if (variableValue == null) throw new ArgumentNullException("variableValue"); if (firstElement || variable.Composite) builder.Append(";").Append(variable.Name); else if (!firstElement) builder.Append(','); string text = variableValue.ToString(); if ((firstElement || variable.Composite) && !string.IsNullOrEmpty(text)) builder.Append('='); AppendText(builder, variable, text, true); }
private static string BuildVariablePattern(VariableReference variable, bool allowReservedSet, string groupName, ICollection<string> requiredVariables, ICollection<string> arrayVariables, ICollection<string> mapVariables) { string characterPattern; if (allowReservedSet) characterPattern = "(?:" + UnreservedCharacterPattern + "|" + ReservedCharacterPattern + ")"; else characterPattern = "(?:" + UnreservedCharacterPattern + ")"; string valueStartPattern; if (!string.IsNullOrEmpty(groupName)) valueStartPattern = "(?<" + groupName + ">"; else valueStartPattern = "(?:"; string valueEndPattern = ")"; string nameStartPattern; if (!string.IsNullOrEmpty(groupName)) nameStartPattern = "(?<" + groupName + "name>"; else nameStartPattern = "(?:"; string nameEndPattern = ")"; string keyStartPattern; if (!string.IsNullOrEmpty(groupName)) keyStartPattern = "(?<" + groupName + "key>"; else keyStartPattern = "(?:"; string keyEndPattern = ")"; string mapValueStartPattern; if (!string.IsNullOrEmpty(groupName)) mapValueStartPattern = "(?<" + groupName + "value>"; else mapValueStartPattern = "(?:"; string mapValueEndPattern = ")"; string countPattern; if (allowReservedSet) countPattern = "*?"; else countPattern = "*"; string positiveCountPattern; if (allowReservedSet) positiveCountPattern = "+?"; else positiveCountPattern = "+"; StringBuilder variablePattern = new StringBuilder(); if (variable.Prefix != null) { // by this point we know to match the variable as a simple string variablePattern.Append("(?:"); variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern); variablePattern.Append("{1,").Append(variable.Prefix).Append("}"); variablePattern.Append(valueEndPattern); variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); variablePattern.Append(")"); return variablePattern.ToString(); } bool treatAsArray = arrayVariables.Contains(variable.Name); bool treatAsMap = mapVariables.Contains(variable.Name); bool considerString = !variable.Composite && !treatAsArray && !treatAsMap; bool considerArray = treatAsArray || !treatAsMap; bool considerMap = treatAsMap || !treatAsArray; variablePattern.Append("(?:"); if (considerString) { // could be a simple string variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern).Append(positiveCountPattern); variablePattern.Append(valueEndPattern); variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } if (considerArray) { if (considerString) variablePattern.Append('|'); // could be an associative array variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); if (variable.Composite) { // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(positiveCountPattern).Append(valueEndPattern); variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } else { // the '=' is only included for non-empty values variablePattern.Append("(?:"); // positiveCountPattern if only one item variablePattern.Append('='); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(positiveCountPattern).Append(valueEndPattern); // countPattern for multiple items (the ',' will make the value non-empty) variablePattern.Append("|="); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append(")+?"); // zero items variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } } if (considerMap) { if (considerString || considerArray) variablePattern.Append('|'); // could be an associative map if (variable.Composite) { variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(mapValueStartPattern).Append(characterPattern).Append(positiveCountPattern).Append(mapValueEndPattern); variablePattern.Append("|").Append(mapValueStartPattern).Append(mapValueEndPattern); variablePattern.Append(")"); variablePattern.Append(valueEndPattern); } else { variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); // the ',' between the key and value allows countPattern and still never empty variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(',').Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); /* Composite variables appear as separate path parameters that are aggregated by the Match method. * This expression only needs to handle the non-composite case. */ variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(',').Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); variablePattern.Append(")*?"); // zero items variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } } variablePattern.Append(")"); return variablePattern.ToString(); }
protected override void RenderEnumerable(StringBuilder builder, VariableReference variable, IEnumerable variableValue, bool first) { bool firstElement = true; foreach (object value in variableValue) { if (value == null) continue; RenderElement(builder, variable, value, first, firstElement); firstElement = false; } }
protected override void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool first) { RenderElement(builder, variable, variableValue, first, true); }
protected override void RenderDictionary(StringBuilder builder, VariableReference variable, IDictionary variableValue, bool first) { bool firstElement = true; foreach (DictionaryEntry entry in variableValue) { if (variable.Composite) { builder.Append(';'); AppendText(builder, variable, entry.Key.ToString(), true); builder.Append('='); AppendText(builder, variable, entry.Value.ToString(), true); } else { RenderElement(builder, variable, entry.Key, first, firstElement); RenderElement(builder, variable, entry.Value, first, false); } firstElement = false; } }
private static string BuildVariablePattern(VariableReference variable, bool allowReservedSet, string groupName, ICollection<string> requiredVariables, ICollection<string> arrayVariables, ICollection<string> mapVariables) { string characterPattern; if (allowReservedSet) characterPattern = "(?:" + UnreservedCharacterPattern + "|" + ReservedCharacterPattern + ")"; else characterPattern = "(?:" + UnreservedCharacterPattern + ")"; string valueStartPattern; if (!string.IsNullOrEmpty(groupName)) valueStartPattern = "(?<" + groupName + ">"; else valueStartPattern = "(?:"; string valueEndPattern = ")"; string keyStartPattern; if (!string.IsNullOrEmpty(groupName)) keyStartPattern = "(?<" + groupName + "key>"; else keyStartPattern = "(?:"; string keyEndPattern = ")"; string mapValueStartPattern; if (!string.IsNullOrEmpty(groupName)) mapValueStartPattern = "(?<" + groupName + "value>"; else mapValueStartPattern = "(?:"; string mapValueEndPattern = ")"; string countPattern; if (allowReservedSet) countPattern = "*?"; else countPattern = "*"; StringBuilder variablePattern = new StringBuilder(); if (variable.Prefix != null) { // by this point we know to match the variable as a simple string variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern); variablePattern.Append("{0,").Append(variable.Prefix).Append("}"); variablePattern.Append(valueEndPattern); return variablePattern.ToString(); } bool treatAsArray = arrayVariables.Contains(variable.Name); bool treatAsMap = mapVariables.Contains(variable.Name); bool considerString = !variable.Composite && !treatAsArray && !treatAsMap; bool considerArray = treatAsArray || !treatAsMap; bool considerMap = treatAsMap || !treatAsArray; variablePattern.Append("(?:"); if (considerString) { // could be a simple string variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(valueEndPattern); } if (considerArray) { if (considerString) variablePattern.Append('|'); // could be an associative array variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append(")*?"); } if (considerMap) { if (considerString || considerArray) variablePattern.Append('|'); // could be an associative map char separator = variable.Composite ? '=' : ','; variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(separator).Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(separator).Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); variablePattern.Append(")*?"); } variablePattern.Append(")"); return variablePattern.ToString(); }
protected override void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool first) { RenderElement(builder, variable, variableValue, first, true); }
private static string BuildVariablePattern(VariableReference variable, bool allowReservedSet, string groupName, ICollection <string> requiredVariables, ICollection <string> arrayVariables, ICollection <string> mapVariables) { string characterPattern; if (allowReservedSet) { characterPattern = "(?:" + UnreservedCharacterPattern + "|" + ReservedCharacterPattern + ")"; } else { characterPattern = "(?:" + UnreservedCharacterPattern + ")"; } string valueStartPattern; if (!string.IsNullOrEmpty(groupName)) { valueStartPattern = "(?<" + groupName + ">"; } else { valueStartPattern = "(?:"; } string valueEndPattern = ")"; string keyStartPattern; if (!string.IsNullOrEmpty(groupName)) { keyStartPattern = "(?<" + groupName + "key>"; } else { keyStartPattern = "(?:"; } string keyEndPattern = ")"; string mapValueStartPattern; if (!string.IsNullOrEmpty(groupName)) { mapValueStartPattern = "(?<" + groupName + "value>"; } else { mapValueStartPattern = "(?:"; } string mapValueEndPattern = ")"; string countPattern; if (allowReservedSet) { countPattern = "*?"; } else { countPattern = "*"; } StringBuilder variablePattern = new StringBuilder(); if (variable.Prefix != null) { // by this point we know to match the variable as a simple string variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern); variablePattern.Append("{0,").Append(variable.Prefix).Append("}"); variablePattern.Append(valueEndPattern); return(variablePattern.ToString()); } bool treatAsArray = arrayVariables.Contains(variable.Name); bool treatAsMap = mapVariables.Contains(variable.Name); bool considerString = !variable.Composite && !treatAsArray && !treatAsMap; bool considerArray = treatAsArray || !treatAsMap; bool considerMap = treatAsMap || !treatAsArray; variablePattern.Append("(?:"); if (considerString) { // could be a simple string variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(valueEndPattern); } if (considerArray) { if (considerString) { variablePattern.Append('|'); } // could be an associative array variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append(")*?"); } if (considerMap) { if (considerString || considerArray) { variablePattern.Append('|'); } // could be an associative map char separator = variable.Composite ? '=' : ','; variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(separator).Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(separator).Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); variablePattern.Append(")*?"); } variablePattern.Append(")"); return(variablePattern.ToString()); }
private void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool firstVariable, bool firstElement) { if (builder == null) throw new ArgumentNullException("builder"); if (variableValue == null) throw new ArgumentNullException("variableValue"); if (firstElement || variable.Composite) builder.Append("/"); else if (!firstElement) builder.Append(','); AppendText(builder, variable, variableValue.ToString(), true); }
/// <summary> /// Render a single variable, where the variable value is a <see cref="string"/> or other single-valued /// element. /// </summary> /// <param name="builder">The <see cref="StringBuilder"/> to render to.</param> /// <param name="variable">The variable being rendered.</param> /// <param name="variableValue">The value of the variable being rendered.</param> /// <param name="first"> /// <see langword="true"/> if this is the first variable being rendered from this expression; otherwise, /// <see langword="false"/>. Variables which do not have an associated parameter, or whose parameter value /// is <see langword="null"/>, are treated as though they were completely omitted for the purpose of /// determining the first variable. /// </param> /// <exception cref="ArgumentNullException"> /// <para>If <paramref name="builder"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="variable"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="variableValue"/> is <see langword="null"/>.</para> /// </exception> protected abstract void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool first);
/// <summary> /// Render a single variable, where the variable value is a collection (<see cref="IEnumerable"/>). /// </summary> /// <param name="builder">The <see cref="StringBuilder"/> to render to.</param> /// <param name="variable">The variable being rendered.</param> /// <param name="variableValue">The value of the variable being rendered.</param> /// <param name="first"> /// <see langword="true"/> if this is the first variable being rendered from this expression; otherwise, /// <see langword="false"/>. Variables which do not have an associated parameter, or whose parameter value /// is <see langword="null"/>, are treated as though they were completely omitted for the purpose of /// determining the first variable. /// </param> /// <exception cref="ArgumentNullException"> /// <para>If <paramref name="builder"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="variable"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="variableValue"/> is <see langword="null"/>.</para> /// </exception> protected abstract void RenderEnumerable(StringBuilder builder, VariableReference variable, IEnumerable variableValue, bool first);
/// <summary> /// Render a single variable, where the variable value is an associative map (<see cref="IDictionary"/>). /// </summary> /// <param name="builder">The <see cref="StringBuilder"/> to render to.</param> /// <param name="variable">The variable being rendered.</param> /// <param name="variableValue">The value of the variable being rendered.</param> /// <param name="first"> /// <see langword="true"/> if this is the first variable being rendered from this expression; otherwise, /// <see langword="false"/>. Variables which do not have an associated parameter, or whose parameter value /// is <see langword="null"/>, are treated as though they were completely omitted for the purpose of /// determining the first variable. /// </param> /// <exception cref="ArgumentNullException"> /// <para>If <paramref name="builder"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="variable"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="variableValue"/> is <see langword="null"/>.</para> /// </exception> protected abstract void RenderDictionary(StringBuilder builder, VariableReference variable, IDictionary variableValue, bool first);
private void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool firstVariable, bool firstElement) { if (builder == null) throw new ArgumentNullException("builder"); if (variableValue == null) throw new ArgumentNullException("variableValue"); if (firstElement || variable.Composite) builder.Append(Type == UriTemplatePartType.Query && firstVariable && firstElement ? '?' : '&').Append(variable.Name).Append('='); else if (!firstElement) builder.Append(','); AppendText(builder, variable, variableValue.ToString(), true); }
protected override KeyValuePair <VariableReference, object>[] MatchImpl(string text, ICollection <string> requiredVariables, ICollection <string> arrayVariables, ICollection <string> mapVariables) { List <string> variablePatterns = new List <string>(); for (int i = 0; i < Variables.Count; i++) { bool allowReservedSet = false; variablePatterns.Add(BuildVariablePattern(Variables[i], allowReservedSet, "var" + i, requiredVariables, arrayVariables, mapVariables)); } StringBuilder matchPattern = new StringBuilder(); matchPattern.Append("^;"); AppendOneOrMoreUnorderedToEnd(matchPattern, variablePatterns, 0); matchPattern.Append("$"); Match match = Regex.Match(text, matchPattern.ToString()); List <KeyValuePair <VariableReference, object> > results = new List <KeyValuePair <VariableReference, object> >(); for (int i = 0; i < Variables.Count; i++) { VariableReference variable = Variables[i]; Group group = match.Groups["var" + i]; if (!group.Success || group.Captures.Count == 0) { continue; } if (!variable.Composite) { /* ;id=x;id=y is only valid for {;id*}; * {;id} would produce ;id=x,y instead. */ Group nameGroup = match.Groups["var" + i + "name"]; if (nameGroup.Success && nameGroup.Captures.Count > 1) { return(null); } Debug.Assert(nameGroup.Success && nameGroup.Captures.Count == 1, "nameGroup.Success && nameGroup.Captures.Count == 1"); } if (Variables[i].Prefix != null) { if (group.Success && group.Captures.Count == 1) { results.Add(new KeyValuePair <VariableReference, object>(Variables[i], DecodeCharacters(group.Captures[0].Value))); } continue; } bool treatAsArray = arrayVariables.Contains(Variables[i].Name); bool treatAsMap = mapVariables.Contains(Variables[i].Name); bool considerString = !Variables[i].Composite && !treatAsArray && !treatAsMap; bool considerArray = treatAsArray || !treatAsMap; bool considerMap = treatAsMap || !treatAsArray; // first check for a map Group mapKeys = match.Groups["var" + i + "key"]; if (mapKeys.Success && mapKeys.Captures.Count > 0) { Debug.Assert(considerMap, "considerMap"); Group mapValues = match.Groups["var" + i + "value"]; Dictionary <string, string> map = new Dictionary <string, string>(); for (int j = 0; j < mapKeys.Captures.Count; j++) { map.Add(DecodeCharacters(mapKeys.Captures[j].Value), DecodeCharacters(mapValues.Captures[j].Value)); } results.Add(new KeyValuePair <VariableReference, object>(Variables[i], map)); continue; } // next try an array if (!considerString || group.Captures.Count > 1) { Debug.Assert(considerArray, "considerArray"); List <string> list = new List <string>(group.Captures.Count); foreach (Capture capture in group.Captures) { list.Add(DecodeCharacters(capture.Value)); } results.Add(new KeyValuePair <VariableReference, object>(Variables[i], list)); continue; } Debug.Assert(considerString, "considerString"); results.Add(new KeyValuePair <VariableReference, object>(Variables[i], DecodeCharacters(group.Captures[0].Value))); } return(results.ToArray()); }
private static UriTemplatePart[] ParseTemplate(string template) { List <UriTemplatePart> parts = new List <UriTemplatePart>(); int previousEnd = 0; foreach (Match match in ExpressionExpression.Matches(template)) { if (match.Index > previousEnd) { parts.Add(new UriTemplatePartLiteral(template.Substring(previousEnd, match.Index - previousEnd))); } UriTemplatePartType type = UriTemplatePartType.SimpleStringExpansion; Group op = match.Groups["Operator"]; if (op.Success && op.Length > 0) { switch (op.Value) { case "+": type = UriTemplatePartType.ReservedStringExpansion; break; case "#": type = UriTemplatePartType.FragmentExpansion; break; case ".": type = UriTemplatePartType.LabelExpansion; break; case "/": type = UriTemplatePartType.PathSegments; break; case ";": type = UriTemplatePartType.PathParameters; break; case "?": type = UriTemplatePartType.Query; break; case "&": type = UriTemplatePartType.QueryContinuation; break; case "=": case ",": case "!": case "@": case "|": throw new NotSupportedException(string.Format("Operator is reserved for future expansion: {0}", op.Value)); default: throw new InvalidOperationException("Unreachable"); } } Group variableList = match.Groups["VariableList"]; VariableReference[] variables; if (variableList.Success) { string[] specs = variableList.Value.Split(','); variables = new VariableReference[specs.Length]; for (int i = 0; i < specs.Length; i++) { variables[i] = VariableReference.Parse(specs[i]); } } else { variables = new VariableReference[0]; } UriTemplatePart part; switch (type) { case UriTemplatePartType.SimpleStringExpansion: part = new UriTemplatePartSimpleExpansion(variables, true); break; case UriTemplatePartType.ReservedStringExpansion: part = new UriTemplatePartSimpleExpansion(variables, false); break; case UriTemplatePartType.FragmentExpansion: part = new UriTemplatePartFragmentExpansion(variables); break; case UriTemplatePartType.LabelExpansion: part = new UriTemplatePartLabelExpansion(variables); break; case UriTemplatePartType.PathSegments: part = new UriTemplatePartPathSegmentExpansion(variables); break; case UriTemplatePartType.PathParameters: part = new UriTemplatePartPathParametersExpansion(variables); break; case UriTemplatePartType.Query: part = new UriTemplatePartQueryExpansion(variables, false); break; case UriTemplatePartType.QueryContinuation: part = new UriTemplatePartQueryExpansion(variables, true); break; case UriTemplatePartType.Literal: default: throw new InvalidOperationException("Unreachable"); } parts.Add(part); previousEnd = match.Index + match.Length; } if (previousEnd < template.Length) { parts.Add(new UriTemplatePartLiteral(template.Substring(previousEnd))); } return(parts.ToArray()); }
private static string BuildVariablePattern(VariableReference variable, bool allowReservedSet, string groupName, ICollection <string> requiredVariables, ICollection <string> arrayVariables, ICollection <string> mapVariables) { string characterPattern; if (allowReservedSet) { characterPattern = "(?:" + UnreservedCharacterPattern + "|" + ReservedCharacterPattern + ")"; } else { characterPattern = "(?:" + UnreservedCharacterPattern + ")"; } string valueStartPattern; if (!string.IsNullOrEmpty(groupName)) { valueStartPattern = "(?<" + groupName + ">"; } else { valueStartPattern = "(?:"; } string valueEndPattern = ")"; string nameStartPattern; if (!string.IsNullOrEmpty(groupName)) { nameStartPattern = "(?<" + groupName + "name>"; } else { nameStartPattern = "(?:"; } string nameEndPattern = ")"; string keyStartPattern; if (!string.IsNullOrEmpty(groupName)) { keyStartPattern = "(?<" + groupName + "key>"; } else { keyStartPattern = "(?:"; } string keyEndPattern = ")"; string mapValueStartPattern; if (!string.IsNullOrEmpty(groupName)) { mapValueStartPattern = "(?<" + groupName + "value>"; } else { mapValueStartPattern = "(?:"; } string mapValueEndPattern = ")"; string countPattern; if (allowReservedSet) { countPattern = "*?"; } else { countPattern = "*"; } string positiveCountPattern; if (allowReservedSet) { positiveCountPattern = "+?"; } else { positiveCountPattern = "+"; } StringBuilder variablePattern = new StringBuilder(); if (variable.Prefix != null) { // by this point we know to match the variable as a simple string variablePattern.Append("(?:"); variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern); variablePattern.Append("{1,").Append(variable.Prefix).Append("}"); variablePattern.Append(valueEndPattern); variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); variablePattern.Append(")"); return(variablePattern.ToString()); } bool treatAsArray = arrayVariables.Contains(variable.Name); bool treatAsMap = mapVariables.Contains(variable.Name); bool considerString = !variable.Composite && !treatAsArray && !treatAsMap; bool considerArray = treatAsArray || !treatAsMap; bool considerMap = treatAsMap || !treatAsArray; variablePattern.Append("(?:"); if (considerString) { // could be a simple string variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(valueStartPattern); variablePattern.Append(characterPattern).Append(positiveCountPattern); variablePattern.Append(valueEndPattern); variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } if (considerArray) { if (considerString) { variablePattern.Append('|'); } // could be an associative array variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); if (variable.Composite) { // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(positiveCountPattern).Append(valueEndPattern); variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } else { // the '=' is only included for non-empty values variablePattern.Append("(?:"); // positiveCountPattern if only one item variablePattern.Append('='); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(positiveCountPattern).Append(valueEndPattern); // countPattern for multiple items (the ',' will make the value non-empty) variablePattern.Append("|="); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern).Append(characterPattern).Append(countPattern).Append(valueEndPattern); variablePattern.Append(")+?"); // zero items variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } } if (considerMap) { if (considerString || considerArray) { variablePattern.Append('|'); } // could be an associative map if (variable.Composite) { variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); variablePattern.Append(mapValueStartPattern).Append(characterPattern).Append(positiveCountPattern).Append(mapValueEndPattern); variablePattern.Append("|").Append(mapValueStartPattern).Append(mapValueEndPattern); variablePattern.Append(")"); variablePattern.Append(valueEndPattern); } else { variablePattern.Append(nameStartPattern).Append(Regex.Escape(variable.Name)).Append(nameEndPattern); // the '=' is only included for non-empty values variablePattern.Append("(?:="); // the ',' between the key and value allows countPattern and still never empty variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(',').Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); /* Composite variables appear as separate path parameters that are aggregated by the Match method. * This expression only needs to handle the non-composite case. */ variablePattern.Append("(?:,"); variablePattern.Append(valueStartPattern); variablePattern.Append(keyStartPattern); variablePattern.Append(characterPattern).Append(countPattern); variablePattern.Append(keyEndPattern); variablePattern.Append(',').Append(mapValueStartPattern).Append(characterPattern).Append(countPattern).Append(mapValueEndPattern); variablePattern.Append(valueEndPattern); variablePattern.Append(")*?"); // zero items variablePattern.Append("|").Append(valueStartPattern).Append(valueEndPattern); variablePattern.Append(")"); } } variablePattern.Append(")"); return(variablePattern.ToString()); }
protected override void RenderElement(StringBuilder builder, VariableReference variable, object variableValue, bool first) { if (builder == null) throw new ArgumentNullException("builder"); if (variableValue == null) throw new ArgumentNullException("variableValue"); if (!first) builder.Append(','); AppendText(builder, variable, variableValue.ToString(), _escapeReserved); }