-
Notifications
You must be signed in to change notification settings - Fork 352
/
Copy pathODataUriUtils.cs
209 lines (182 loc) · 10.4 KB
/
ODataUriUtils.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//---------------------------------------------------------------------
// <copyright file="ODataUriUtils.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.OData.Edm;
using Microsoft.OData.Metadata;
using Microsoft.OData.UriParser;
using Microsoft.OData.Core;
namespace Microsoft.OData
{
/// <summary>
/// URI Utility methods.
/// </summary>
public static class ODataUriUtils
{
/// <summary>
/// Converts the given <paramref name="value"/> to a corresponding CLR type. Expects the
/// <paramref name="value"/> to have already been properly unescaped from an actual Uri.
/// </summary>
/// <param name="value">Value from a Uri to be converted.</param>
/// <param name="version">Version to be compliant with.</param>
/// <returns>A CLR object that the <paramref name="value"/> represents (won't be EnumNode).</returns>
public static object ConvertFromUriLiteral(string value, ODataVersion version)
{
return ODataUriUtils.ConvertFromUriLiteral(value, version, null, null);
}
/// <summary>
/// Converts the given <paramref name="value"/> to a corresponding CLR type. Expects the
/// <paramref name="value"/> to have already been properly unescaped from an actual Uri.
/// </summary>
/// <param name="value">Value from a Uri to be converted.</param>
/// <param name="version">Version to be compliant with.</param>
/// <param name="model">Optional model to perform verification against.</param>
/// <param name="typeReference">Optional IEdmTypeReference to perform verification against.
/// Callers must provide a <paramref name="model"/> containing this type if it is specified.</param>
/// <returns>A CLR object that the <paramref name="value"/> represents or an EnumNode.</returns>
public static object ConvertFromUriLiteral(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
{
ExceptionUtils.CheckArgumentNotNull(value, "value");
if (typeReference != null && model == null)
{
throw new ODataException(SRResources.ODataUriUtils_ConvertFromUriLiteralTypeRefWithoutModel);
}
if (model == null)
{
model = Microsoft.OData.Edm.EdmCoreModel.Instance;
}
// Let ExpressionLexer try to get a primitive
ExpressionLexer lexer = new ExpressionLexer(value, false /*moveToFirstToken*/, false /*useSemicolonDelimiter*/);
Exception error;
ExpressionToken token;
lexer.TryPeekNextToken(out token, out error);
if (token.Kind == ExpressionTokenKind.BracedExpression && typeReference != null && typeReference.IsStructured())
{
return ODataUriConversionUtils.ConvertFromResourceValue(value, model, typeReference);
}
if (token.Kind == ExpressionTokenKind.BracketedExpression)
{
return ODataUriConversionUtils.ConvertFromCollectionValue(value, model, typeReference);
}
QueryNode enumConstNode;
if ((token.Kind == ExpressionTokenKind.Identifier) // then try parsing the entire text as enum value
&& EnumBinder.TryBindIdentifier(lexer.ExpressionText, null, model, out enumConstNode))
{
return ((ConstantNode)enumConstNode).Value;
}
object result = lexer.ReadLiteralToken();
// If we have a typeReference then perform verification and convert if necessary
if (typeReference != null)
{
result = ODataUriConversionUtils.VerifyAndCoerceUriPrimitiveLiteral(result, value, model, typeReference);
}
return result;
}
/// <summary>
/// Converts the given object to a string for use in a Uri. Does not perform any of the escaping that <see cref="System.Uri"/> provides.
/// No type verification is used.
/// </summary>
/// <param name="value">Value to be converted.</param>
/// <param name="version">Version to be compliant with.</param>
/// <param name="isIeee754Compatible">true if value should be IEEE 754 compatible.</param>
/// <returns>A string representation of <paramref name="value"/> for use in a Url.</returns>
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "designed to aid the creation on a URI, not create a full one")]
public static string ConvertToUriLiteral(object value, ODataVersion version, bool isIeee754Compatible)
{
return ODataUriUtils.ConvertToUriLiteral(value, version, null, isIeee754Compatible);
}
/// <summary>
/// Converts the given object to a string for use in a Uri. Does not perform any of the escaping that <see cref="Uri"/> provides.
/// No type verification is used.
/// </summary>
/// <param name="value">Value to be converted.</param>
/// <param name="version">Version to be compliant with.</param>
/// <returns>A string representation of <paramref name="value"/> for use in a Url.</returns>
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "designed to aid the creation on a URI, not create a full one")]
public static string ConvertToUriLiteral(object value, ODataVersion version)
{
return ODataUriUtils.ConvertToUriLiteral(value, version, null, true);
}
/// <summary>
/// Converts the given object to a string in the specified format for use in a Uri. Does not perform any of the escaping that <see cref="Uri"/> provides.
/// Will perform type verification based on the given model if possible.
/// </summary>
/// <param name="value">Value to be converted (can be EnumNode).</param>
/// <param name="version">Version to be compliant with.</param>
/// <param name="model">Optional model to perform verification against.</param>
/// <returns>A string representation of <paramref name="value"/> for use in a Url.</returns>
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "designed to aid the creation on a URI, not create a full one")]
public static string ConvertToUriLiteral(object value, ODataVersion version, IEdmModel model)
{
return ODataUriUtils.ConvertToUriLiteral(value, version, model, true /*isIeee754Compatible*/);
}
/// <summary>
/// Converts the given object to a string in the specified format for use in a Uri. Does not perform any of the escaping that <see cref="System.Uri"/> provides.
/// Will perform type verification based on the given model if possible.
/// </summary>
/// <param name="value">Value to be converted (can be EnumNode).</param>
/// <param name="version">Version to be compliant with.</param>
/// <param name="model">Optional model to perform verification against.</param>
/// <param name="isIeee754Compatible">true if value should be IEEE 754 compatible.</param>
/// <returns>A string representation of <paramref name="value"/> for use in a Url.</returns>
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "designed to aid the creation on a URI, not create a full one")]
public static string ConvertToUriLiteral(object value, ODataVersion version, IEdmModel model, bool isIeee754Compatible)
{
if (value == null)
{
value = new ODataNullValue();
}
if (model == null)
{
model = Microsoft.OData.Edm.EdmCoreModel.Instance;
}
ODataNullValue nullValue = value as ODataNullValue;
if (nullValue != null)
{
return ExpressionConstants.KeywordNull;
}
ODataResourceValue resourceValue = value as ODataResourceValue;
if (resourceValue != null)
{
return ODataUriConversionUtils.ConvertToResourceLiteral(resourceValue, model, version);
}
ODataCollectionValue collectionValue = value as ODataCollectionValue;
if (collectionValue != null)
{
return ODataUriConversionUtils.ConvertToUriCollectionLiteral(collectionValue, model, version, isIeee754Compatible);
}
ODataEnumValue enumValue = value as ODataEnumValue;
if (enumValue != null)
{
return ODataUriConversionUtils.ConvertToUriEnumLiteral(enumValue, version);
}
ODataResourceBase resource = value as ODataResourceBase;
if (resource != null)
{
return ODataUriConversionUtils.ConvertToUriEntityLiteral(resource, model);
}
ODataEntityReferenceLink link = value as ODataEntityReferenceLink;
if (link != null)
{
return ODataUriConversionUtils.ConvertToUriEntityReferenceLiteral(link, model);
}
ODataEntityReferenceLinks links = value as ODataEntityReferenceLinks;
if (links != null)
{
return ODataUriConversionUtils.ConvertToUriEntityReferencesLiteral(links, model);
}
IEnumerable<ODataResourceBase> list = value as IEnumerable<ODataResourceBase>;
if (list != null)
{
return ODataUriConversionUtils.ConvertToUriEntitiesLiteral(list, model);
}
// Try to convert uints to their underlying type first according to the model.
value = model.ConvertToUnderlyingTypeIfUIntValue(value);
return ODataUriConversionUtils.ConvertToUriPrimitiveLiteral(value, version);
}
}
}