/// <summary> /// Constructs a KeyLookupNode. /// </summary> /// <param name="source">The collection that this key is referring to.</param> /// <param name="keyPropertyValues">List of the properties and their values that we use to look up our return value.</param> /// <exception cref="System.ArgumentNullException">Throws if the input source is null.</exception> public KeyLookupNode(CollectionResourceNode source, IEnumerable <KeyPropertyValue> keyPropertyValues) { ExceptionUtils.CheckArgumentNotNull(source, "source"); this.source = source; this.navigationSource = source.NavigationSource; this.entityTypeReference = source.ItemStructuredType as IEdmEntityTypeReference; this.keyPropertyValues = keyPropertyValues; }
/// <summary> /// Creates a <see cref="ResourceRangeVariable"/>. /// </summary> /// <param name="name"> The name of the associated any/all parameter (null if none)</param> /// <param name="structuredType">The structured type of each item in the collection that this range variable iterates over.</param> /// <param name="navigationSource">The navigation source of the collection this node iterates over.</param> /// <exception cref="System.ArgumentNullException">Throws if the input name or entityType is null.</exception> public ResourceRangeVariable(string name, IEdmStructuredTypeReference structuredType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(name, "name"); ExceptionUtils.CheckArgumentNotNull(structuredType, "structuredType"); this.name = name; this.structuredTypeReference = structuredType; this.collectionResourceNode = null; this.navigationSource = navigationSource; }
/// <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(CollectionResourceNode 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)); }
/// <summary> /// Create a CollectionCastNode with the given source node and the given target type. /// </summary> /// <param name="source">Parent <see cref="CollectionNode"/> that is being cast.</param> /// <param name="structuredType">Type to cast to.</param> /// <exception cref="System.ArgumentNullException">Throws if the input source or structuredType are null.</exception> public CollectionResourceCastNode(CollectionResourceNode source, IEdmStructuredType structuredType) { ExceptionUtils.CheckArgumentNotNull(source, "source"); ExceptionUtils.CheckArgumentNotNull(structuredType, "structuredType"); this.source = source; this.edmTypeReference = structuredType.GetTypeReference(); this.navigationSource = source.NavigationSource; // creating a new collection type here because the type in the request is just the item type, there is no user-provided collection type. this.collectionTypeReference = EdmCoreModel.GetCollection(this.edmTypeReference); }
/// <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(CollectionResourceNode 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); }
/// <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(CollectionResourceNode 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); } }
/// <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(CollectionResourceNode 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.ItemStructuredType as IEdmEntityTypeReference; 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.ItemStructuredType.FullName())); } }
/// <summary> /// Binds a DottedIdentifierToken and it's parent node (if needed). /// </summary> /// <param name="dottedIdentifierToken">Token to bind to metadata.</param> /// <returns>A bound node representing the cast.</returns> internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierToken) { 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(); } } SingleResourceNode parentAsSingleResource = parent as SingleResourceNode; IEdmSchemaType childType = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier, this.Resolver); IEdmStructuredType childStructuredType = childType as IEdmStructuredType; if (childStructuredType == null) { SingleValueNode singleValueNode = parent as SingleValueNode; FunctionCallBinder functionCallBinder = new FunctionCallBinder(bindMethod, state); QueryNode functionCallNode; if (functionCallBinder.TryBindDottedIdentifierAsFunctionCall(dottedIdentifierToken, singleValueNode, out functionCallNode)) { return(functionCallNode); } else if ((!string.IsNullOrEmpty(dottedIdentifierToken.Identifier)) && (dottedIdentifierToken.Identifier[dottedIdentifierToken.Identifier.Length - 1] == '\'')) { // check if it is enum or not QueryNode enumNode; if (EnumBinder.TryBindDottedIdentifierAsEnum(dottedIdentifierToken, parentAsSingleResource, state, this.Resolver, out enumNode)) { return(enumNode); } else { throw new ODataException(ODataErrorStrings.Binder_IsNotValidEnumConstant(dottedIdentifierToken.Identifier)); } } else { IEdmTypeReference edmTypeReference = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier, this.Resolver).ToTypeReference(); if (edmTypeReference is IEdmPrimitiveTypeReference || edmTypeReference is IEdmEnumTypeReference) { IEdmPrimitiveType childPrimitiveType = childType as IEdmPrimitiveType; if (childPrimitiveType != null && dottedIdentifierToken.NextToken != null) { return(new SingleValueCastNode(singleValueNode, childPrimitiveType)); } else { 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); this.state.ParsedSegments.Add(new TypeSegment(childType, parentType, null)); CollectionResourceNode parentAsCollection = parent as CollectionResourceNode; if (parentAsCollection != null) { return(new CollectionResourceCastNode(parentAsCollection, childStructuredType)); } return(new SingleResourceCastNode(parentAsSingleResource, childStructuredType)); }