Beispiel #1
0
        private void TestCast <TParam, TReturn>(EntityCollectionNode source, IEdmEntityType cast, Expression <Func <TParam, TReturn> > expectedExpression)
        {
            var node   = new EntityCollectionCastNode(source, cast);
            var result = this.testSubject.TranslateNode(node);

            CompareExpressions(expectedExpression.Body, result);
        }
Beispiel #2
0
        /// <summary>
        /// Binds a DottedIdentifierToken and it's parent node (if needed).
        /// </summary>
        /// <param name="dottedIdentifierToken">Token to bind to metadata.</param>
        /// <param name="state">State of the Binding.</param>
        /// <returns>A bound node representing the cast.</returns>
        internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierToken, BindingState state)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(dottedIdentifierToken, "castToken");
            ExceptionUtils.CheckArgumentNotNull(state, "state");

            QueryNode parent;
            IEdmType  parentType;

            if (dottedIdentifierToken.NextToken == null)
            {
                parent     = NodeFactory.CreateRangeVariableReferenceNode(state.ImplicitRangeVariable);
                parentType = state.ImplicitRangeVariable.TypeReference.Definition;
            }
            else
            {
                parent     = this.bindMethod(dottedIdentifierToken.NextToken);
                parentType = parent.GetEdmType();
            }

            SingleEntityNode parentAsSingleValue = parent as SingleEntityNode;

            IEdmSchemaType childType       = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier);
            IEdmEntityType childEntityType = childType as IEdmEntityType;

            if (childEntityType == null)
            {
                FunctionCallBinder functionCallBinder = new FunctionCallBinder(bindMethod);
                QueryNode          functionCallNode;
                if (functionCallBinder.TryBindDottedIdentifierAsFunctionCall(dottedIdentifierToken, parentAsSingleValue, state, out functionCallNode))
                {
                    return(functionCallNode);
                }
                else
                {
                    throw new ODataException(ODataErrorStrings.CastBinder_ChildTypeIsNotEntity(dottedIdentifierToken.Identifier));
                }
            }

            // Check whether childType is a derived type of the type of its parent node
            UriEdmHelpers.CheckRelatedTo(parentType, childType);

            EntityCollectionNode parentAsCollection = parent as EntityCollectionNode;

            if (parentAsCollection != null)
            {
                return(new EntityCollectionCastNode(parentAsCollection, childEntityType));
            }

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

            Debug.Assert(parentAsSingleValue != null, "If parent of the cast node was not collection, it should be a single value.");
            return(new SingleEntityCastNode(parentAsSingleValue, childEntityType));
        }
Beispiel #3
0
        /// <summary>
        /// Tries to bind key values to a key lookup on a collection.
        /// </summary>
        /// <param name="collectionNode">Already bound collection node.</param>
        /// <param name="namedValues">The named value tokens to bind.</param>
        /// <param name="model">The model to be used.</param>
        /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param>
        /// <param name="keyLookupNode">The bound key lookup.</param>
        /// <returns>Returns true if binding succeeded.</returns>
        private bool TryBindToDeclaredKey(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues, IEdmModel model, IEdmEntityType collectionItemEntityType, out QueryNode keyLookupNode)
        {
            Dictionary <string, IEdmProperty> keys = new Dictionary <string, IEdmProperty>(StringComparer.Ordinal);

            foreach (IEdmStructuralProperty property in collectionItemEntityType.Key())
            {
                keys[property.Name] = property;
            }

            return(TryBindToKeys(collectionNode, namedValues, model, collectionItemEntityType, keys, out keyLookupNode));
        }
Beispiel #4
0
        public void TranslatorShouldConvertWeaklyBackedEntityCollectionCast()
        {
            EntityCollectionNode source = this.CollectionNavigationFromParameter("c");
            QueryNode            node   = new EntityCollectionCastNode(source, this.weaklyBackedCustomerEdmType);
            var result = this.testSubject.TranslateNode(node);

            var parameterExpression = Expression.Parameter(typeof(Customer), "c");
            var propertyExpression  = Expression.Property(parameterExpression, "OtherFriends");
            var expected            = Expression.Call(typeof(DataServiceProviderMethods), "OfType", new[] { typeof(Customer), typeof(object) }, propertyExpression, Expression.Constant(this.weaklyBackedDerivedType));

            expected = Expression.Call(typeof(Enumerable), "Cast", new[] { typeof(object) }, expected);
            CompareExpressions(expected, result);
        }
        /// <summary>
        /// Checks whether a query node is a collection query node representing a collection of entities.
        /// </summary>
        /// <param name="query">The <see cref="QueryNode"/> to check.</param>
        /// <returns>The converted <see cref="CollectionNode"/> or null if <paramref name="query"/> is not an entity collection node.</returns>
        internal static EntityCollectionNode AsEntityCollectionNode(this QueryNode query)
        {
            Debug.Assert(query != null, "query != null");

            EntityCollectionNode collectionNode = query as EntityCollectionNode;

            if (collectionNode != null &&
                collectionNode.ItemType != null &&
                collectionNode.ItemType.IsODataEntityTypeKind())
            {
                return(collectionNode);
            }

            return(null);
        }
Beispiel #6
0
        /// <summary>
        /// Tries to bind key values to a key lookup on a collection.
        /// </summary>
        /// <param name="collectionNode">Already bound collection node.</param>
        /// <param name="namedValues">The named value tokens to bind.</param>
        /// <param name="model">The model to be used.</param>
        /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param>
        /// <param name="keyLookupNode">The bound key lookup.</param>
        /// <returns>Returns true if binding succeeded.</returns>
        private bool TryBindToDeclaredAlternateKey(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues, IEdmModel model, IEdmEntityType collectionItemEntityType, out QueryNode keyLookupNode)
        {
            IEnumerable <IDictionary <string, IEdmProperty> > alternateKeys = model.GetAlternateKeysAnnotation(collectionItemEntityType);

            foreach (IDictionary <string, IEdmProperty> keys in alternateKeys)
            {
                if (TryBindToKeys(collectionNode, namedValues, model, collectionItemEntityType, keys, out keyLookupNode))
                {
                    return(true);
                }
            }

            keyLookupNode = null;
            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Binds key values to a key lookup on a collection.
        /// </summary>
        /// <param name="collectionNode">Already bound collection node.</param>
        /// <param name="namedValues">The named value tokens to bind.</param>
        /// <param name="model">The model to be used.</param>
        /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param>
        /// <param name="keys">Dictionary of aliases to structural property names for the key.</param>
        /// <param name="keyLookupNode">The bound key lookup.</param>
        /// <returns>Returns true if binding succeeded.</returns>
        private bool TryBindToKeys(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues, IEdmModel model, IEdmEntityType collectionItemEntityType, IDictionary <string, IEdmProperty> keys, out QueryNode keyLookupNode)
        {
            List <KeyPropertyValue> keyPropertyValues = new List <KeyPropertyValue>();
            HashSet <string>        keyPropertyNames  = new HashSet <string>(StringComparer.Ordinal);

            foreach (NamedValue namedValue in namedValues)
            {
                KeyPropertyValue keyPropertyValue;

                if (!this.TryBindKeyPropertyValue(namedValue, collectionItemEntityType, keys, out keyPropertyValue))
                {
                    keyLookupNode = null;
                    return(false);
                }

                Debug.Assert(keyPropertyValue != null, "keyPropertyValue != null");
                Debug.Assert(keyPropertyValue.KeyProperty != null, "keyPropertyValue.KeyProperty != null");

                if (!keyPropertyNames.Add(keyPropertyValue.KeyProperty.Name))
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_DuplicitKeyPropertyInKeyValues(keyPropertyValue.KeyProperty.Name));
                }

                keyPropertyValues.Add(keyPropertyValue);
            }

            if (keyPropertyValues.Count == 0)
            {
                // No key values specified, for example '/Customers()', do not include the key lookup at all
                keyLookupNode = collectionNode;
                return(true);
            }
            else if (keyPropertyValues.Count != collectionItemEntityType.Key().Count())
            {
                keyLookupNode = null;
                return(false);
            }
            else
            {
                keyLookupNode = new KeyLookupNode(collectionNode, new ReadOnlyCollection <KeyPropertyValue>(keyPropertyValues));
                return(true);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Binds key values to a key lookup on a collection.
        /// </summary>
        /// <param name="collectionNode">Already bound collection node.</param>
        /// <param name="namedValues">The named value tokens to bind.</param>
        /// <returns>The bound key lookup.</returns>
        internal QueryNode BindKeyValues(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(namedValues != null, "namedValues != null");
            Debug.Assert(collectionNode != null, "CollectionNode != null");

            IEdmEntityTypeReference collectionItemType = collectionNode.EntityItemType;
            List <KeyPropertyValue> keyPropertyValues  = new List <KeyPropertyValue>();

            IEdmEntityType collectionItemEntityType = collectionItemType.EntityDefinition();

            HashSet <string> keyPropertyNames = new HashSet <string>(StringComparer.Ordinal);

            foreach (NamedValue namedValue in namedValues)
            {
                KeyPropertyValue keyPropertyValue = this.BindKeyPropertyValue(namedValue, collectionItemEntityType);
                Debug.Assert(keyPropertyValue != null, "keyPropertyValue != null");
                Debug.Assert(keyPropertyValue.KeyProperty != null, "keyPropertyValue.KeyProperty != null");

                if (!keyPropertyNames.Add(keyPropertyValue.KeyProperty.Name))
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_DuplicitKeyPropertyInKeyValues(keyPropertyValue.KeyProperty.Name));
                }

                keyPropertyValues.Add(keyPropertyValue);
            }

            if (keyPropertyValues.Count == 0)
            {
                // No key values specified, for example '/Customers()', do not include the key lookup at all
                return(collectionNode);
            }
            else if (keyPropertyValues.Count != collectionItemEntityType.Key().Count())
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_NotAllKeyPropertiesSpecifiedInKeyValues(collectionNode.ItemType.ODataFullName()));
            }
            else
            {
                return(new KeyLookupNode(collectionNode, new ReadOnlyCollection <KeyPropertyValue>(keyPropertyValues)));
            }
        }
Beispiel #9
0
        /// <summary>
        /// Binds key values to a key lookup on a collection.
        /// </summary>
        /// <param name="collectionNode">Already bound collection node.</param>
        /// <param name="namedValues">The named value tokens to bind.</param>
        /// <param name="model">The model to be used.</param>
        /// <returns>The bound key lookup.</returns>
        internal QueryNode BindKeyValues(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues, IEdmModel model)
        {
            Debug.Assert(namedValues != null, "namedValues != null");
            Debug.Assert(collectionNode != null, "CollectionNode != null");
            Debug.Assert(model != null, "model != null");

            IEdmEntityTypeReference collectionItemType = collectionNode.EntityItemType;

            IEdmEntityType collectionItemEntityType = collectionItemType.EntityDefinition();
            QueryNode      keyLookupNode;

            if (TryBindToDeclaredKey(collectionNode, namedValues, model, collectionItemEntityType, out keyLookupNode))
            {
                return(keyLookupNode);
            }
            else if (TryBindToDeclaredAlternateKey(collectionNode, namedValues, model, collectionItemEntityType, out keyLookupNode))
            {
                return(keyLookupNode);
            }
            else
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_NotAllKeyPropertiesSpecifiedInKeyValues(collectionNode.ItemType.FullName()));
            }
        }
Beispiel #10
0
        /// <summary>
        /// Binds a DottedIdentifierToken and it's parent node (if needed).
        /// </summary>
        /// <param name="dottedIdentifierToken">Token to bind to metadata.</param>
        /// <param name="state">State of the Binding.</param>
        /// <returns>A bound node representing the cast.</returns>
        internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierToken, BindingState state)
        {
            ExceptionUtils.CheckArgumentNotNull(dottedIdentifierToken, "castToken");
            ExceptionUtils.CheckArgumentNotNull(state, "state");

            QueryNode parent     = null;
            IEdmType  parentType = null;

            if (state.ImplicitRangeVariable != null)
            {
                if (dottedIdentifierToken.NextToken == null)
                {
                    parent     = NodeFactory.CreateRangeVariableReferenceNode(state.ImplicitRangeVariable);
                    parentType = state.ImplicitRangeVariable.TypeReference.Definition;
                }
                else
                {
                    parent     = this.bindMethod(dottedIdentifierToken.NextToken);
                    parentType = parent.GetEdmType();
                }
            }

            SingleEntityNode   parentAsSingleValue = parent as SingleEntityNode;
            IEdmSchemaType     childType           = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier);
            IEdmStructuredType childStructuredType = childType as IEdmStructuredType;

            if (childStructuredType == null)
            {
                FunctionCallBinder functionCallBinder = new FunctionCallBinder(bindMethod);
                QueryNode          functionCallNode;
                if (functionCallBinder.TryBindDottedIdentifierAsFunctionCall(dottedIdentifierToken, parentAsSingleValue, state, out functionCallNode))
                {
                    return(functionCallNode);
                }
                else if ((!string.IsNullOrEmpty(dottedIdentifierToken.Identifier)) &&
                         (dottedIdentifierToken.Identifier[dottedIdentifierToken.Identifier.Length - 1] == '\''))
                {
                    // check if it is enum or not
                    EnumBinder enumBinder = new EnumBinder(this.bindMethod);
                    QueryNode  enumNode;
                    if (enumBinder.TryBindDottedIdentifierAsEnum(dottedIdentifierToken, parentAsSingleValue, state, out enumNode))
                    {
                        return(enumNode);
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.Binder_IsNotValidEnumConstant(dottedIdentifierToken.Identifier));
                    }
                }
                else
                {
                    IEdmTypeReference edmTypeReference = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier).ToTypeReference();
                    if (edmTypeReference is IEdmPrimitiveTypeReference || edmTypeReference is IEdmEnumTypeReference)
                    {
                        return(new ConstantNode(dottedIdentifierToken.Identifier, dottedIdentifierToken.Identifier));
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.CastBinder_ChildTypeIsNotEntity(dottedIdentifierToken.Identifier));
                    }
                }
            }

            // Check whether childType is a derived type of the type of its parent node
            UriEdmHelpers.CheckRelatedTo(parentType, childType);

            IEdmEntityType childEntityType = childStructuredType as IEdmEntityType;

            if (childEntityType != null)
            {
                EntityCollectionNode parentAsCollection = parent as EntityCollectionNode;
                if (parentAsCollection != null)
                {
                    return(new EntityCollectionCastNode(parentAsCollection, childEntityType));
                }

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

                Debug.Assert(parentAsSingleValue != null, "If parent of the cast node was not collection, it should be a single value.");
                return(new SingleEntityCastNode(parentAsSingleValue, childEntityType));
            }
            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));
            }
        }