Skip to content

Commit

Permalink
Change logic to let complex use new SingleComplexNode and CollectionC…
Browse files Browse the repository at this point in the history
…omplexNode #643
  • Loading branch information
Zoe-ms committed Jul 25, 2016
1 parent 96d1724 commit 7035581
Show file tree
Hide file tree
Showing 50 changed files with 844 additions and 533 deletions.
Expand Up @@ -1090,9 +1090,6 @@
<Compile Include="$(ODataCrossTargettingSourcePath)\UriParser\SemanticAst\CollectionPropertyAccessNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\CollectionPropertyAccessNode.cs</Link>
</Compile>
<Compile Include="$(ODataCrossTargettingSourcePath)\UriParser\SemanticAst\CollectionPropertyCastNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\CollectionPropertyCastNode.cs</Link>
</Compile>
<Compile Include="$(ODataCrossTargettingSourcePath)\UriParser\SemanticAst\ConstantNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\ConstantNode.cs</Link>
</Compile>
Expand Down Expand Up @@ -1228,9 +1225,6 @@
<Compile Include="$(ODataCrossTargettingSourcePath)\UriParser\SemanticAst\SingleNavigationNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\SingleNavigationNode.cs</Link>
</Compile>
<Compile Include="$(ODataCrossTargettingSourcePath)\UriParser\SemanticAst\SingleValueCastNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\SingleValueCastNode.cs</Link>
</Compile>
<Compile Include="$(ODataCrossTargettingSourcePath)\UriParser\SemanticAst\SingleValueFunctionCallNode.cs">
<Link>Microsoft\OData\Core\UriParser\SemanticAst\SingleValueFunctionCallNode.cs</Link>
</Compile>
Expand Down
5 changes: 4 additions & 1 deletion src/Microsoft.OData.Core/ExceptionUtils.cs
Expand Up @@ -63,7 +63,8 @@ internal static bool IsCatchableExceptionType(Exception e)
/// <typeparam name="T">Type of the argument, used to force usage only for reference types.</typeparam>
/// <param name="value">Argument whose value needs to be checked.</param>
/// <param name="parameterName">Name of the argument, used for exception message.</param>
internal static void CheckArgumentNotNull<T>([ValidatedNotNull] T value, string parameterName) where T : class
/// <returns>The value</returns>
internal static T CheckArgumentNotNull<T>([ValidatedNotNull] T value, string parameterName) where T : class
{
Debug.Assert(!string.IsNullOrEmpty(parameterName), "!string.IsNullOrEmpty(parameterName)");

Expand All @@ -73,6 +74,8 @@ internal static bool IsCatchableExceptionType(Exception e)
throw Error.ArgumentNull(parameterName);
#endif
}

return value;
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.OData.Core/GlobalSuppressions.cs
Expand Up @@ -115,3 +115,4 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Scope = "member", Target = "Microsoft.OData.ContainerBuilderExtensions.#AddService`2(Microsoft.OData.IContainerBuilder,Microsoft.OData.ServiceLifetime,System.Func`2<System.IServiceProvider,!!1>)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Microsoft.OData.UriParser.ODataUriParser.#IsODataQueryOption(System.String)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.OData.UriParser.BindingPathHelper.#MatchBindingPath(Microsoft.OData.Edm.IEdmPathExpression,System.Collections.Generic.List`1<Microsoft.OData.UriParser.ODataPathSegment>)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.OData.UriParser.InnerPathTokenBinder.#BindInnerPathSegment(Microsoft.OData.UriParser.InnerPathToken)")]
2 changes: 0 additions & 2 deletions src/Microsoft.OData.Core/Microsoft.OData.Core.csproj
Expand Up @@ -447,7 +447,6 @@
<Compile Include="UriParser\SemanticAst\CollectionNode.cs" />
<Compile Include="UriParser\SemanticAst\CollectionOpenPropertyAccessNode.cs" />
<Compile Include="UriParser\SemanticAst\CollectionPropertyAccessNode.cs" />
<Compile Include="UriParser\SemanticAst\CollectionPropertyCastNode.cs" />
<Compile Include="UriParser\SemanticAst\ConstantNode.cs" />
<Compile Include="UriParser\SemanticAst\ConvertNode.cs" />
<Compile Include="UriParser\SemanticAst\CountNode.cs" />
Expand Down Expand Up @@ -502,7 +501,6 @@
<Compile Include="UriParser\SemanticAst\SingleResourceFunctionCallNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleEntityNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleNavigationNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleValueCastNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleValueFunctionCallNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleValueNode.cs" />
<Compile Include="UriParser\SemanticAst\SingleValueOpenPropertyAccessNode.cs" />
Expand Down
44 changes: 22 additions & 22 deletions src/Microsoft.OData.Core/Uri/NodeToStringBuilder.cs
Expand Up @@ -115,6 +115,17 @@ public override String Visit(CollectionPropertyAccessNode node)
return this.TranslatePropertyAccess(node.Source, node.Property.Name);
}

/// <summary>
/// Translates a <see cref="CollectionComplexNode"/> into a corresponding <see cref="String"/>.
/// </summary>
/// <param name="node">The node to translate.</param>
/// <returns>The translated String.</returns>
public override String Visit(CollectionComplexNode node)
{
ExceptionUtils.CheckArgumentNotNull(node, "node");
return this.TranslatePropertyAccess(node.Source, node.Property.Name);
}

/// <summary>
/// Translates a <see cref="CollectionPropertyAccessNode"/> into a corresponding <see cref="String"/>.
/// </summary>
Expand Down Expand Up @@ -153,17 +164,6 @@ public override String Visit(CollectionResourceCastNode node)
return this.TranslatePropertyAccess(node.Source, node.ItemStructuredType.Definition.ToString());
}

/// <summary>
/// Visit an CollectionPropertyCastNode
/// </summary>
/// <param name="node">the node to visit</param>
/// <returns>The translated String of CollectionPropertyCastNode</returns>
public override String Visit(CollectionPropertyCastNode node)
{
ExceptionUtils.CheckArgumentNotNull(node, "node");
return this.TranslatePropertyAccess(node.Source, node.CollectionType.Definition.ToString());
}

/// <summary>
/// Translates a <see cref="ResourceRangeVariableReferenceNode"/> into a corresponding <see cref="String"/>.
/// </summary>
Expand Down Expand Up @@ -204,17 +204,6 @@ public override String Visit(SingleResourceCastNode node)
return this.TranslatePropertyAccess(node.Source, node.StructuredTypeReference.Definition.ToString());
}

/// <summary>
/// Translates a <see cref="SingleValueCastNode"/> into a corresponding <see cref="String"/>.
/// </summary>
/// <param name="node">The node to translate.</param>
/// <returns>The translated String of SingleValueCastNode.</returns>
public override String Visit(SingleValueCastNode node)
{
ExceptionUtils.CheckArgumentNotNull(node, "node");
return this.TranslatePropertyAccess(node.Source, node.TypeReference.Definition.ToString());
}

/// <summary>
/// Translates a <see cref="SingleNavigationNode"/> into a corresponding <see cref="String"/>.
/// </summary>
Expand Down Expand Up @@ -327,6 +316,17 @@ public override String Visit(SingleValuePropertyAccessNode node)
return this.TranslatePropertyAccess(node.Source, node.Property.Name);
}

/// <summary>
/// Translates a <see cref="SingleComplexNode"/> into a corresponding <see cref="String"/>.
/// </summary>
/// <param name="node">The node to translate.</param>
/// <returns>The translated String.</returns>
public override String Visit(SingleComplexNode node)
{
ExceptionUtils.CheckArgumentNotNull(node, "node");
return this.TranslatePropertyAccess(node.Source, node.Property.Name);
}

/// <summary>
/// Translates a <see cref="ParameterAliasNode"/> into a corresponding <see cref="String"/>.
/// </summary>
Expand Down
17 changes: 15 additions & 2 deletions src/Microsoft.OData.Core/UriParser/Aggregation/ApplyBinder.cs
Expand Up @@ -140,11 +140,16 @@ private GroupByTransformationNode BindGroupByToken(GroupByToken token)
{
var bindResult = this.bindMethod(propertyToken);
var property = bindResult as SingleValuePropertyAccessNode;
var complexProperty = bindResult as SingleComplexNode;

if (property != null)
{
RegisterProperty(properties, ReversePropertyPath(property));
}
else if (complexProperty != null)
{
RegisterProperty(properties, ReversePropertyPath(complexProperty));
}
else
{
var openProperty = bindResult as SingleValueOpenPropertyAccessNode;
Expand Down Expand Up @@ -184,6 +189,7 @@ private GroupByTransformationNode BindGroupByToken(GroupByToken token)
private static bool IsPropertyNode(SingleValueNode node)
{
return node.Kind == QueryNodeKind.SingleValuePropertyAccess ||
node.Kind == QueryNodeKind.SingleComplexNode ||
node.Kind == QueryNodeKind.SingleNavigationNode;
}

Expand All @@ -197,6 +203,10 @@ private static Stack<SingleValueNode> ReversePropertyPath(SingleValueNode node)
{
node = ((SingleValuePropertyAccessNode)node).Source;
}
else if (node.Kind == QueryNodeKind.SingleComplexNode)
{
node = (SingleValueNode)((SingleComplexNode)node).Source;
}
else if (node.Kind == QueryNodeKind.SingleNavigationNode)
{
node = ((SingleNavigationNode)node).NavigationSource as SingleValueNode;
Expand Down Expand Up @@ -228,8 +238,7 @@ private static void RegisterProperty(IList<GroupByPropertyNode> properties, Stac
else
{
// It's the leaf just add.
var accessNode = property as SingleValuePropertyAccessNode;
properties.Add(new GroupByPropertyNode(propertyName, property, accessNode.TypeReference));
properties.Add(new GroupByPropertyNode(propertyName, property, property.TypeReference));
}
}

Expand All @@ -239,6 +248,10 @@ private static string GetNodePropertyName(SingleValueNode property)
{
return ((SingleValuePropertyAccessNode)property).Property.Name;
}
else if (property.Kind == QueryNodeKind.SingleComplexNode)
{
return ((SingleComplexNode)property).Property.Name;
}
else if (property.Kind == QueryNodeKind.SingleNavigationNode)
{
return ((SingleNavigationNode)property).NavigationProperty.Name;
Expand Down
Expand Up @@ -52,7 +52,7 @@ internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierTo
}
}

SingleResourceNode parentAsSingleValue = parent as SingleResourceNode;
SingleResourceNode parentAsSingleResource = parent as SingleResourceNode;
IEdmSchemaType childType = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier, this.Resolver);
IEdmStructuredType childStructuredType = childType as IEdmStructuredType;
if (childStructuredType == null)
Expand All @@ -68,7 +68,7 @@ internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierTo
{
// check if it is enum or not
QueryNode enumNode;
if (EnumBinder.TryBindDottedIdentifierAsEnum(dottedIdentifierToken, parentAsSingleValue, state, out enumNode))
if (EnumBinder.TryBindDottedIdentifierAsEnum(dottedIdentifierToken, parentAsSingleResource, state, out enumNode))
{
return enumNode;
}
Expand Down Expand Up @@ -96,45 +96,13 @@ internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierTo

this.state.ParsedSegments.Add(new TypeSegment(childType, parentType, null));

IEdmEntityType childEntityType = childStructuredType as IEdmEntityType;
if (childEntityType != null)
CollectionResourceNode parentAsCollection = parent as CollectionResourceNode;
if (parentAsCollection != null)
{
CollectionResourceNode parentAsCollection = parent as CollectionResourceNode;
if (parentAsCollection != null)
{
return new CollectionResourceCastNode(parentAsCollection, childEntityType);
}

// parent can be null for casts on the implicit parameter; this is OK
if (parent == null)
{
return new SingleResourceCastNode(null, childEntityType);
}

Debug.Assert(parentAsSingleValue != null, "If parent of the cast node was not collection, it should be a single value.");
return new SingleResourceCastNode(parentAsSingleValue, childEntityType);
return new CollectionResourceCastNode(parentAsCollection, childStructuredType);
}
else
{
IEdmComplexType childComplexType = childStructuredType as IEdmComplexType;
Debug.Assert(childComplexType != null, "If it is not entity type, it should be complex type");

CollectionPropertyAccessNode parentAsCollectionProperty = parent as CollectionPropertyAccessNode;
if (parentAsCollectionProperty != null)
{
return new CollectionPropertyCastNode(parentAsCollectionProperty, childComplexType);
}

// parent can be null for casts on the implicit parameter; this is OK
if (parent == null)
{
return new SingleValueCastNode(null, childComplexType);
}

SingleValueNode parentAsSingleValueNode = parent as SingleValueNode;
Debug.Assert(parentAsSingleValueNode != null, "If parent of the cast node was not collection, it should be a single value.");
return new SingleValueCastNode(parentAsSingleValueNode, childComplexType);
}
return new SingleResourceCastNode(parentAsSingleResource, childStructuredType);
}
}
}
25 changes: 18 additions & 7 deletions src/Microsoft.OData.Core/UriParser/Binders/EndPathBinder.cs
Expand Up @@ -41,9 +41,9 @@ internal EndPathBinder(MetadataBinder.QueryTokenVisitor bindMethod, BindingState
/// <param name="property">The <see cref="IEdmProperty"/> that will be bound to this node. Must not be primitive collection</param>
/// <param name="state">The state of binding.</param>
/// <returns>QueryNode bound to this property.</returns>
internal static QueryNode GeneratePropertyAccessQueryNode(SingleValueNode parentNode, IEdmProperty property, BindingState state)
internal static QueryNode GeneratePropertyAccessQueryNode(SingleResourceNode parentNode, IEdmProperty property, BindingState state)
{
ExceptionUtils.CheckArgumentNotNull(parentNode, "parent");
ExceptionUtils.CheckArgumentNotNull(parentNode, "parentNode");
ExceptionUtils.CheckArgumentNotNull(property, "property");

// TODO: Remove this check.
Expand All @@ -54,20 +54,31 @@ internal static QueryNode GeneratePropertyAccessQueryNode(SingleValueNode parent
{
// if this happens to be a top level node (i.e. $filter=MyCollection), then it will fail further up the chain, so
// don't need to worry about checking for that here.
return new CollectionPropertyAccessNode(parentNode, property);
if (property.Type.IsStructuredCollectionType())
{
return new CollectionComplexNode(parentNode, property);
}
else
{
return new CollectionPropertyAccessNode(parentNode, property);
}
}

if (property.PropertyKind == EdmPropertyKind.Navigation)
{
// These are error cases in practice, but we let ourselves throw later for better context-sensitive error messages
var edmNavigationProperty = (IEdmNavigationProperty)property;
var singleEntityParentNode = (SingleResourceNode)parentNode;
if (edmNavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
{
return new CollectionNavigationNode(singleEntityParentNode, edmNavigationProperty, state.ParsedSegments);
return new CollectionNavigationNode(parentNode, edmNavigationProperty, state.ParsedSegments);
}

return new SingleNavigationNode(singleEntityParentNode, edmNavigationProperty, state.ParsedSegments);
return new SingleNavigationNode(parentNode, edmNavigationProperty, state.ParsedSegments);
}

if (property.Type.IsComplex())
{
return new SingleComplexNode(parentNode, property);
}

return new SingleValuePropertyAccessNode(parentNode, property);
Expand Down Expand Up @@ -158,7 +169,7 @@ internal QueryNode BindEndPath(EndPathToken endPathToken)

if (property != null)
{
return GeneratePropertyAccessQueryNode(singleValueParent, property, state);
return GeneratePropertyAccessQueryNode(singleValueParent as SingleResourceNode, property, state);
}

if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, singleValueParent, state, out boundFunction))
Expand Down

0 comments on commit 7035581

Please sign in to comment.