예제 #1
0
        /// <summary>
        /// Create a new RangeVariableToken
        /// </summary>
        /// <param name="name">The name of the visitor for the Any/All query.</param>
        public RangeVariableToken(string name)
        {
            ExceptionUtils.CheckArgumentNotNull(name, "visitor");

            this.name = name;
        }
예제 #2
0
 /// <summary>
 /// Accept a <see cref="IPathSegmentTokenVisitor{T}"/> to walk a tree of <see cref="PathSegmentToken"/>s.
 /// </summary>
 /// <typeparam name="T">Type that the visitor will return after visiting this token.</typeparam>
 /// <param name="visitor">An implementation of the visitor interface.</param>
 /// <returns>An object whose type is determined by the type parameter of the visitor.</returns>
 public override T Accept <T>(IPathSegmentTokenVisitor <T> visitor)
 {
     ExceptionUtils.CheckArgumentNotNull(visitor, "visitor");
     return(visitor.Visit(this));
 }
예제 #3
0
 /// <summary>
 /// Translate a <see cref="PropertySegment"/> using an instance of <see cref="PathSegmentTranslator{T}"/>/>.
 /// </summary>
 /// <typeparam name="T">Type that the translator will return after visiting this token.</typeparam>
 /// <param name="translator">An implementation of the translator interface.</param>
 /// <returns>An object whose type is determined by the type parameter of the translator.</returns>
 /// <exception cref="System.ArgumentNullException">Throws if the input translator is null.</exception>
 public override T TranslateWith <T>(PathSegmentTranslator <T> translator)
 {
     ExceptionUtils.CheckArgumentNotNull(translator, "translator");
     return(translator.Translate(this));
 }
 /// <summary>
 /// Accept a <see cref="QueryNodeVisitor{T}"/> to walk a tree of <see cref="QueryNode"/>s.
 /// </summary>
 /// <typeparam name="T">Type that the visitor will return after visiting this token.</typeparam>
 /// <param name="visitor">An implementation of the visitor interface.</param>
 /// <returns>An object whose type is determined by the type parameter of the visitor.</returns>
 /// <exception cref="System.ArgumentNullException">Throws if the input visitor is null.</exception>
 public override T Accept <T>(QueryNodeVisitor <T> visitor)
 {
     ExceptionUtils.CheckArgumentNotNull(visitor, "visitor");
     return(visitor.Visit(this));
 }
예제 #5
0
 /// <summary>
 /// Accept a <see cref="QueryNodeVisitor{T}"/> that walks a tree of <see cref="QueryNode"/>s.
 /// </summary>
 /// <typeparam name="T">Type that the visitor will return after visiting this token.</typeparam>
 /// <param name="visitor">An implementation of the visitor interface.</param>
 /// <returns>An object whose type is determined by the type parameter of the visitor.</returns>
 /// <exception cref="System.ArgumentNullException">Throws if the input visitor is null.</exception>
 public override T Accept<T>(QueryNodeVisitor<T> visitor)
 {
     DebugUtils.CheckNoExternalCallers();
     ExceptionUtils.CheckArgumentNotNull(visitor, "visitor");
     return visitor.Visit(this);
 }
        internal static object CoerceNumericType(object primitiveValue, IEdmPrimitiveType targetEdmType)
        {
            // This is implemented to match TypePromotionUtils and MetadataUtilsCommon.CanConvertPrimitiveTypeTo()
            ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue");
            ExceptionUtils.CheckArgumentNotNull(targetEdmType, "targetEdmType");

            Type                 fromType            = primitiveValue.GetType();
            TypeCode             fromTypeCode        = ODataPlatformHelper.GetTypeCode(fromType);
            EdmPrimitiveTypeKind targetPrimitiveKind = targetEdmType.PrimitiveKind;

            switch (fromTypeCode)
            {
            case TypeCode.SByte:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.SByte:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int16:
                    return(Convert.ToInt16((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Int32:
                    return(Convert.ToInt32((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((SByte)primitiveValue));
                }

                break;

            case TypeCode.Byte:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Byte:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int16:
                    return(Convert.ToInt16((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Int32:
                    return(Convert.ToInt32((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Byte)primitiveValue));
                }

                break;

            case TypeCode.Int16:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int16:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int32:
                    return(Convert.ToInt32((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Int16)primitiveValue));
                }

                break;

            case TypeCode.Int32:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int32:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((Int32)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Int32)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Int32)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Int32)primitiveValue));
                }

                break;

            case TypeCode.Int64:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int64:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Int64)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Int64)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Int64)primitiveValue));
                }

                break;

            case TypeCode.Single:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Single:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Double:
                    /*to string then to double, avoid losing precision like "(double)123.001f" which is 123.00099945068359, instead of 123.001d.*/
                    return(double.Parse(((Single)primitiveValue).ToString("R", CultureInfo.InvariantCulture), CultureInfo.InvariantCulture));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Single)primitiveValue));
                }

                break;

            case TypeCode.Double:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Double:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Decimal:
                    // TODO: extract these convertion steps to an individual function
                    decimal doubleToDecimalR;

                    // To keep the full presion of the current value, which if necessary is all 17 digits of precision supported by the Double type.
                    if (decimal.TryParse(((Double)primitiveValue).ToString("R", CultureInfo.InvariantCulture), out doubleToDecimalR))
                    {
                        return(doubleToDecimalR);
                    }

                    return(Convert.ToDecimal((Double)primitiveValue));
                }

                break;

            case TypeCode.Decimal:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Decimal:
                    return(primitiveValue);
                }

                break;

            default:
                break;
            }

            return(null);
        }
예제 #7
0
        /// <summary>
        /// Creates a <see cref="SearchClause"/>.
        /// </summary>
        /// <param name="expression">The filter expression - this should evaluate to a single boolean value. Cannot be null.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the input expression or rangeVariable is null.</exception>
        public SearchClause(SingleValueNode expression)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");

            this.expression = expression;
        }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataWriter"/> for <paramref name="entry"/>.
 /// </summary>
 /// <param name="entry">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataEntry entry, ODataFeedAndEntrySerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(entry, "entry");
     entry.SerializationInfo = serializationInfo;
 }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataWriter"/> for <paramref name="property"/>.
 /// </summary>
 /// <param name="property">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataProperty property, ODataPropertySerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(property, "property");
     property.SerializationInfo = serializationInfo;
 }
예제 #10
0
 /// <summary>
 /// Check if this segment is equal to another segment.
 /// </summary>
 /// <param name="other">the other segment to check.</param>
 /// <returns>true if the other segment is equal.</returns>
 /// <exception cref="System.ArgumentNullException">throws if the input other is null.</exception>
 internal override bool Equals(ODataPathSegment other)
 {
     ExceptionUtils.CheckArgumentNotNull(other, "other");
     return(other is CountSegment);
 }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataWriter"/> for <paramref name="feed"/>.
 /// </summary>
 /// <param name="feed">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataFeed feed, ODataFeedAndEntrySerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(feed, "feed");
     feed.SerializationInfo = serializationInfo;
 }
예제 #12
0
        /// <summary>
        /// Write the literal token as URI part to this builder.
        /// </summary>
        /// <param name="literal">To write as URI part.</param>
        protected virtual void WriteLiteral(LiteralQueryToken literal)
        {
            ExceptionUtils.CheckArgumentNotNull(literal, "literal");

            WriteClrLiteral(this.builder, literal.Value);
        }
예제 #13
0
        /// <summary>
        /// Write the descriptor token as URI part to this builder.
        /// </summary>
        /// <param name="queryDescriptor">To write as URI part.</param>
        public virtual void WriteQueryDescriptor(QueryDescriptorQueryToken queryDescriptor)
        {
            ExceptionUtils.CheckArgumentNotNull(queryDescriptor, "queryDescriptor");

            this.WriteQuery(queryDescriptor.Path);

            bool writeQueryPrefix = true;

            if (queryDescriptor.Filter != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.FilterQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.WriteQuery(queryDescriptor.Filter);
            }

            if (queryDescriptor.Select != null && queryDescriptor.Select.Properties.Count() > 0)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.WriteSelect(queryDescriptor.Select);
            }

            if (queryDescriptor.Expand != null && queryDescriptor.Expand.Properties.Count() > 0)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.WriteExpand(queryDescriptor.Expand);
            }

            if (queryDescriptor.OrderByTokens.Count() > 0)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.OrderByQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);

                this.WriteOrderBys(queryDescriptor.OrderByTokens);
            }

            foreach (QueryOptionQueryToken queryOption in queryDescriptor.QueryOptions)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.WriteQueryOption(queryOption);
            }

            if (queryDescriptor.Top != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.TopQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.Top);
            }

            if (queryDescriptor.Skip != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.SkipQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.Skip);
            }

            if (queryDescriptor.Format != null)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.FormatQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.Format);
            }

            if (queryDescriptor.InlineCount.HasValue)
            {
                this.WriteQueryPrefixOrSeparator(writeQueryPrefix);
                writeQueryPrefix = false;

                this.builder.Append(UriQueryConstants.InlineCountQueryOption);
                this.builder.Append(ExpressionConstants.SymbolEqual);
                this.builder.Append(queryDescriptor.InlineCount.Value.ToText());
            }
        }
예제 #14
0
        /// <summary>
        /// Create a AggregateTransformationNode.
        /// </summary>
        /// <param name="expressions">A list of <see cref="AggregateExpression"/>.</param>
        public AggregateTransformationNode(IEnumerable <AggregateExpression> expressions)
        {
            ExceptionUtils.CheckArgumentNotNull(expressions, "expressions");

            this.expressions = expressions;
        }
예제 #15
0
 /// <summary>
 /// Build a new System Token
 /// </summary>
 /// <param name="identifier">the identifier for this token.</param>
 /// <param name="nextToken">the next token in the path</param>
 public SystemToken(string identifier, PathSegmentToken nextToken)
     : base(nextToken)
 {
     ExceptionUtils.CheckArgumentNotNull(identifier, "identifier");
     this.identifier = identifier;
 }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataCollectionWriter"/> for <paramref name="collectionStart"/>.
 /// </summary>
 /// <param name="collectionStart">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataCollectionStart collectionStart, ODataCollectionStartSerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(collectionStart, "collectionStart");
     collectionStart.SerializationInfo = serializationInfo;
 }
예제 #17
0
        /// <summary>
        /// Binds an end path token into a PropertyAccessToken, OpenPropertyToken, or FunctionCallToken.
        /// </summary>
        /// <param name="endPathToken">The property access token to bind.</param>
        /// <returns>A Query node representing this endpath token, bound to metadata.</returns>
        internal QueryNode BindEndPath(EndPathToken endPathToken)
        {
            ExceptionUtils.CheckArgumentNotNull(endPathToken, "EndPathToken");
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(endPathToken.Identifier, "EndPathToken.Identifier");

            // Set the parent (get the parent type, so you can check whether the Identifier inside EndPathToken really is legit offshoot of the parent type)
            QueryNode parent = this.DetermineParentNode(endPathToken);

            QueryNode boundFunction;

            SingleValueNode singleValueParent = parent as SingleValueNode;

            if (singleValueParent != null)
            {
                if (endPathToken.Identifier == ExpressionConstants.QueryOptionCount)
                {
                    return(new CountVirtualPropertyNode());
                }

                if (state.IsCollapsed && !IsAggregatedProperty(endPathToken))
                {
                    throw new ODataException(ODataErrorStrings.ApplyBinder_GroupByPropertyNotPropertyAccessValue(endPathToken.Identifier));
                }

                // Now that we have the parent type, can find its corresponding EDM type
                IEdmStructuredTypeReference structuredParentType =
                    singleValueParent.TypeReference == null ? null : singleValueParent.TypeReference.AsStructuredOrNull();

                IEdmProperty property =
                    structuredParentType == null ? null : this.Resolver.ResolveProperty(structuredParentType.StructuredDefinition(), endPathToken.Identifier);

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

                if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, singleValueParent, state, out boundFunction))
                {
                    return(boundFunction);
                }

                return(GeneratePropertyAccessQueryForOpenType(endPathToken, singleValueParent));
            }

            // Collection with any or all expression is already supported and handled separately.
            // Add support of collection with $count segment.
            CollectionNode colNode = parent as CollectionNode;

            if (colNode != null && endPathToken.Identifier.Equals(UriQueryConstants.CountSegment, System.StringComparison.Ordinal))
            {
                // create a collection count node for collection node property.
                return(new CountNode(colNode));
            }

            CollectionNavigationNode collectionParent = parent as CollectionNavigationNode;

            if (collectionParent != null)
            {
                IEdmEntityTypeReference parentType = collectionParent.EntityItemType;
                IEdmProperty            property   = this.Resolver.ResolveProperty(parentType.StructuredDefinition(), endPathToken.Identifier);

                if (property.PropertyKind == EdmPropertyKind.Structural &&
                    !property.Type.IsCollection() &&
                    this.state.InEntitySetAggregation)
                {
                    return(new AggregatedCollectionPropertyNode(collectionParent, property));
                }
            }

            if (functionCallBinder.TryBindEndPathAsFunctionCall(endPathToken, parent, state, out boundFunction))
            {
                return(boundFunction);
            }

            throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyAccessSourceNotSingleValue(endPathToken.Identifier));
        }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataDeltaWriter"/> for <paramref name="deltaFeed"/>.
 /// </summary>
 /// <param name="deltaFeed">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataDeltaFeed deltaFeed, ODataDeltaFeedSerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(deltaFeed, "deltaFeed");
     deltaFeed.SerializationInfo = serializationInfo;
 }
예제 #19
0
 /// <summary>
 /// Constructs a <see cref="BindingState"/> with the given <paramref name="configuration"/>.
 /// </summary>
 /// <param name="configuration">The configuration used for binding.</param>
 internal BindingState(ODataUriParserConfiguration configuration)
 {
     ExceptionUtils.CheckArgumentNotNull(configuration, "configuration");
     this.configuration         = configuration;
     this.BindingRecursionDepth = 0;
 }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataDeltaWriter"/> for <paramref name="deltaDeletedEntry"/>.
 /// </summary>
 /// <param name="deltaDeletedEntry">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataDeltaDeletedEntry deltaDeletedEntry, ODataDeltaSerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(deltaDeletedEntry, "deltaDeletedEntry");
     deltaDeletedEntry.SerializationInfo = serializationInfo;
 }
예제 #21
0
        /// <summary>
        /// Generate an expand item (and a select item for the implicit nav prop if necessary) based on an ExpandTermToken
        /// </summary>
        /// <param name="tokenIn">the expandTerm token to visit</param>
        /// <returns>the expand item for this expand term token.</returns>
        private SelectItem GenerateExpandItem(ExpandTermToken tokenIn)
        {
            ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn");

            PathSegmentToken currentToken = tokenIn.PathToNavigationProp;

            IEdmStructuredType      currentLevelEntityType = this.EdmType;
            List <ODataPathSegment> pathSoFar         = new List <ODataPathSegment>();
            PathSegmentToken        firstNonTypeToken = currentToken;

            if (currentToken.IsNamespaceOrContainerQualified())
            {
                pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, this.configuration.Resolver, ref currentLevelEntityType, out firstNonTypeToken));
            }

            IEdmProperty edmProperty = this.configuration.Resolver.ResolveProperty(currentLevelEntityType, firstNonTypeToken.Identifier);

            if (edmProperty == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.FullTypeName(), currentToken.Identifier));
            }

            IEdmNavigationProperty currentNavProp     = edmProperty as IEdmNavigationProperty;
            IEdmStructuralProperty currentComplexProp = edmProperty as IEdmStructuralProperty;

            if (currentNavProp == null && currentComplexProp == null)
            {
                throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationPropertyOrComplexProperty(currentToken.Identifier, currentLevelEntityType.FullTypeName()));
            }

            if (currentComplexProp != null)
            {
                currentNavProp = ParseComplexTypesBeforeNavigation(currentComplexProp, ref firstNonTypeToken, pathSoFar);
            }

            // ensure that we're always dealing with proper V4 syntax
            if (firstNonTypeToken.NextToken != null && firstNonTypeToken.NextToken.NextToken != null)
            {
                throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath);
            }

            bool isRef = false;

            if (firstNonTypeToken.NextToken != null)
            {
                // lastly... make sure that, since we're on a NavProp, that the next token isn't null.
                if (firstNonTypeToken.NextToken.Identifier == UriQueryConstants.RefSegment)
                {
                    isRef = true;
                }
                else
                {
                    throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath);
                }
            }

            // Add the segments in select and expand to parsed segments
            this.parsedSegments.AddRange(pathSoFar);

            IEdmNavigationSource targetNavigationSource = null;

            if (this.NavigationSource != null)
            {
                IEdmPathExpression bindingPath;
                targetNavigationSource = this.NavigationSource.FindNavigationTarget(currentNavProp, BindingPathHelper.MatchBindingPath, this.parsedSegments, out bindingPath);
            }

            NavigationPropertySegment navSegment = new NavigationPropertySegment(currentNavProp, targetNavigationSource);

            pathSoFar.Add(navSegment);
            this.parsedSegments.Add(navSegment);   // Add the navigation property segment to parsed segments for future usage.
            ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar);

            // call MetadataBinder to build the filter clause
            FilterClause filterOption = null;

            if (tokenIn.FilterOption != null)
            {
                MetadataBinder binder       = this.BuildNewMetadataBinder(targetNavigationSource);
                FilterBinder   filterBinder = new FilterBinder(binder.Bind, binder.BindingState);
                filterOption = filterBinder.BindFilter(tokenIn.FilterOption);
            }

            // call MetadataBinder again to build the orderby clause
            OrderByClause orderbyOption = null;

            if (tokenIn.OrderByOptions != null)
            {
                MetadataBinder binder        = this.BuildNewMetadataBinder(targetNavigationSource);
                OrderByBinder  orderByBinder = new OrderByBinder(binder.Bind);
                orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, tokenIn.OrderByOptions);
            }

            SearchClause searchOption = null;

            if (tokenIn.SearchOption != null)
            {
                MetadataBinder binder       = this.BuildNewMetadataBinder(targetNavigationSource);
                SearchBinder   searchBinder = new SearchBinder(binder.Bind);
                searchOption = searchBinder.BindSearch(tokenIn.SearchOption);
            }

            ComputeClause computeOption = null;

            if (tokenIn.ComputeOption != null)
            {
                MetadataBinder binder        = this.BuildNewMetadataBinder(targetNavigationSource);
                ComputeBinder  computeBinder = new ComputeBinder(binder.Bind);
                computeOption = computeBinder.BindCompute(tokenIn.ComputeOption);
            }

            ApplyClause applyOption = null;

            if (tokenIn.ApplyOptions != null)
            {
                MetadataBinder binder      = this.BuildNewMetadataBinder(targetNavigationSource);
                ApplyBinder    applyBinder = new ApplyBinder(binder.Bind, binder.BindingState);
                applyOption = applyBinder.BindApply(tokenIn.ApplyOptions);
            }

            if (isRef)
            {
                return(new ExpandedReferenceSelectItem(pathToNavProp, targetNavigationSource, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, computeOption, applyOption));
            }

            SelectExpandClause subSelectExpand;

            if (tokenIn.ExpandOption != null)
            {
                subSelectExpand = this.GenerateSubExpand(tokenIn);
            }
            else
            {
                subSelectExpand = BuildDefaultSubExpand();
            }

            subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption);

            LevelsClause levelsOption = ParseLevels(tokenIn.LevelsOption, currentLevelEntityType, currentNavProp);

            return(new ExpandedNavigationSelectItem(pathToNavProp, targetNavigationSource, subSelectExpand, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, levelsOption, computeOption, applyOption));
        }
 /// <summary>
 /// Provide additional serialization information to the <see cref="ODataDeltaWriter"/> for <paramref name="deltalink"/>.
 /// </summary>
 /// <param name="deltalink">The instance to set the serialization info.</param>
 /// <param name="serializationInfo">The serialization info to set.</param>
 public static void SetSerializationInfo(this ODataDeltaLinkBase deltalink, ODataDeltaSerializationInfo serializationInfo)
 {
     ExceptionUtils.CheckArgumentNotNull(deltalink, "deltalink");
     deltalink.SerializationInfo = serializationInfo;
 }
예제 #23
0
        /// <summary>
        /// Visits a <see cref="QueryToken"/> in the lexical tree and binds it to metadata producing a semantic <see cref="QueryNode"/>.
        /// </summary>
        /// <param name="token">The query token on the input.</param>
        /// <returns>The bound query node output.</returns>
        protected internal QueryNode Bind(QueryToken token)
        {
            ExceptionUtils.CheckArgumentNotNull(token, "token");
            this.BindingState.RecurseEnter();
            QueryNode result;

            switch (token.Kind)
            {
            case QueryTokenKind.Any:
                result = this.BindAnyAll((AnyToken)token);
                break;

            case QueryTokenKind.All:
                result = this.BindAnyAll((AllToken)token);
                break;

            case QueryTokenKind.InnerPath:
                result = this.BindInnerPathSegment((InnerPathToken)token);
                break;

            case QueryTokenKind.Literal:
                result = this.BindLiteral((LiteralToken)token);
                break;

            case QueryTokenKind.StringLiteral:
                result = this.BindStringLiteral((StringLiteralToken)token);
                break;

            case QueryTokenKind.BinaryOperator:
                result = this.BindBinaryOperator((BinaryOperatorToken)token);
                break;

            case QueryTokenKind.UnaryOperator:
                result = this.BindUnaryOperator((UnaryOperatorToken)token);
                break;

            case QueryTokenKind.EndPath:
                result = this.BindEndPath((EndPathToken)token);
                break;

            case QueryTokenKind.FunctionCall:
                result = this.BindFunctionCall((FunctionCallToken)token);
                break;

            case QueryTokenKind.DottedIdentifier:
                result = this.BindCast((DottedIdentifierToken)token);
                break;

            case QueryTokenKind.RangeVariable:
                result = this.BindRangeVariable((RangeVariableToken)token);
                break;

            case QueryTokenKind.FunctionParameterAlias:
                result = this.BindParameterAlias((FunctionParameterAliasToken)token);
                break;

            case QueryTokenKind.FunctionParameter:
                result = this.BindFunctionParameter((FunctionParameterToken)token);
                break;

            default:
                throw new ODataException(ODataErrorStrings.MetadataBinder_UnsupportedQueryTokenKind(token.Kind));
            }

            if (result == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_BoundNodeCannotBeNull(token.Kind));
            }

            this.BindingState.RecurseLeave();
            return(result);
        }
예제 #24
0
 /// <summary>
 /// Constructs a SingleNavigationNode.
 /// </summary>
 /// <param name="source">The previous node in the path.</param>
 /// <param name="navigationProperty">The navigation property this node represents.</param>
 /// <param name="bindingPath">The binding path of navigation property</param>
 /// <exception cref="System.ArgumentNullException">Throws if the input navigationProperty or source is null.</exception>
 /// <exception cref="ArgumentException">Throws if the input navigationProperty targets more than one entity.</exception>
 public SingleNavigationNode(SingleResourceNode source, IEdmNavigationProperty navigationProperty, IEdmPathExpression bindingPath)
     : this(ExceptionUtils.CheckArgumentNotNull(source, "source").NavigationSource, navigationProperty, bindingPath)
 {
     this.source = source;
 }
예제 #25
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="parameterAliasValueExpressions">The parameter alias value expressions from uri.</param>
 public ParameterAliasValueAccessor(IDictionary <string, string> parameterAliasValueExpressions)
 {
     ExceptionUtils.CheckArgumentNotNull(parameterAliasValueExpressions, "parameterAliasValueExpressions");
     this.ParameterAliasValueExpressions = new Dictionary <string, string>(parameterAliasValueExpressions, StringComparer.Ordinal);
     this.ParameterAliasValueNodesCached = new Dictionary <string, SingleValueNode>(StringComparer.Ordinal);
 }
예제 #26
0
 /// <summary>
 /// Constructs a SingleNavigationNode.
 /// </summary>
 /// <param name="source">he previous node in the path.</param>
 /// <param name="navigationProperty">The navigation property this node represents.</param>
 /// <param name="segments">The path segments parsed in path and query option.</param>
 internal SingleNavigationNode(SingleResourceNode source, IEdmNavigationProperty navigationProperty, List <ODataPathSegment> segments)
     : this(ExceptionUtils.CheckArgumentNotNull(source, "source").NavigationSource, navigationProperty, segments)
 {
     this.source = source;
 }
예제 #27
0
 /// <summary>
 /// Accept a <see cref="IPathSegmentTokenVisitor"/> to walk a tree of <see cref="PathSegmentToken"/>s.
 /// </summary>
 /// <param name="visitor">An implementation of the visitor interface.</param>
 public override void Accept(IPathSegmentTokenVisitor visitor)
 {
     ExceptionUtils.CheckArgumentNotNull(visitor, "visitor");
     visitor.Visit(this);
 }
예제 #28
0
 /// <summary>
 /// Creates an OrderByBinder
 /// </summary>
 /// <param name="bindMethod">Method to use to visit the token tree and bind the tokens recursively.</param>
 internal OrderByBinder(MetadataBinder.QueryTokenVisitor bindMethod)
 {
     ExceptionUtils.CheckArgumentNotNull(bindMethod, "bindMethod");
     this.bindMethod = bindMethod;
 }
예제 #29
0
 /// <summary>
 /// Handle a <see cref="PropertySegment"/> using an instance of <see cref="PathSegmentHandler"/>.
 /// </summary>
 /// <param name="handler">An implementation of the handler interface.</param>
 /// <exception cref="System.ArgumentNullException">Throws if the input handler is null.</exception>
 public override void HandleWith(PathSegmentHandler handler)
 {
     ExceptionUtils.CheckArgumentNotNull(handler, "handler");
     handler.Handle(this);
 }
예제 #30
0
        /// <summary>
        /// Find any related keys from the parent key segment, if it exists, and add them to the raw key values that
        /// we already have from the uri.
        /// </summary>
        /// <param name="rawKeyValuesFromUri">The raw key values as we've parsed them from the uri.</param>
        /// <param name="targetEntityKeyProperties">The list of key properties on the target entity.</param>
        /// <param name="currentNavigationProperty">The current navigation property that we're trying to follow using the raw key values</param>
        /// <param name="keySegmentOfParentEntity">The key segment of the parent entity in this path, if it exists. Null otherwise</param>
        /// <returns>A new SegmentArgumentParser with any keys that were found added to its list of NamedValues.</returns>
        /// <throws>Thorws if the input currentNavigationProperty is null.</throws>
        public static SegmentArgumentParser FindAndUseKeysFromRelatedSegment(SegmentArgumentParser rawKeyValuesFromUri, IEnumerable <IEdmStructuralProperty> targetEntityKeyProperties, IEdmNavigationProperty currentNavigationProperty, KeySegment keySegmentOfParentEntity)
        {
            ExceptionUtils.CheckArgumentNotNull(currentNavigationProperty, "currentNavigationProperty");
            ExceptionUtils.CheckArgumentNotNull(rawKeyValuesFromUri, "rawKeyValuesFromUri");

            ReadOnlyCollection <IEdmStructuralProperty> targetKeyPropertyList = targetEntityKeyProperties != null ? new ReadOnlyCollection <IEdmStructuralProperty>(targetEntityKeyProperties.ToList()) : new ReadOnlyCollection <IEdmStructuralProperty>(new List <IEdmStructuralProperty>());

            // should only get here if the number of raw parameters from the uri is different than the number of key properties for the target entity.
            Debug.Assert(rawKeyValuesFromUri.ValueCount < targetKeyPropertyList.Count(), "rawKeyValuesFromUri.ValueCount < targetEntityKeyProperties.Count()");

            // if the raw key from the uri has positional values, there must be only one of them
            // its important to cache this value here because we'll change it when we add new
            // named values below (the implementation of AreValuesNamed is just namedValues !=null)
            bool hasPositionalValues = !rawKeyValuesFromUri.AreValuesNamed;

            if (hasPositionalValues && rawKeyValuesFromUri.ValueCount > 1)
            {
                return(rawKeyValuesFromUri);
            }

            if (keySegmentOfParentEntity == null)
            {
                return(rawKeyValuesFromUri);
            }

            // TODO: p2 merge the below 2 pieces of codes
            // find out if any target entity key properties have referential constraints that link them to the previous rawKeyValuesFromUri.
            List <EdmReferentialConstraintPropertyPair> keysFromReferentialIntegrityConstraint = ExtractMatchingPropertyPairsFromNavProp(currentNavigationProperty, targetKeyPropertyList).ToList();

            foreach (EdmReferentialConstraintPropertyPair keyFromReferentialIntegrityConstraint in keysFromReferentialIntegrityConstraint)
            {
                KeyValuePair <string, object> valueFromParent = keySegmentOfParentEntity.Keys.SingleOrDefault(x => x.Key == keyFromReferentialIntegrityConstraint.DependentProperty.Name);
                if (valueFromParent.Key != null)
                {
                    // if the key from the referential integrity constraint is one of the target key properties
                    // and that key property isn't already populated in the raw key values from the uri, then
                    // we set that value to the value from the parent key segment.
                    if (targetKeyPropertyList.Any(x => x.Name == keyFromReferentialIntegrityConstraint.PrincipalProperty.Name))
                    {
                        rawKeyValuesFromUri.AddNamedValue(
                            keyFromReferentialIntegrityConstraint.PrincipalProperty.Name,
                            ConvertKeyValueToUriLiteral(valueFromParent.Value, rawKeyValuesFromUri.KeyAsSegment));
                    }
                }
            }

            // also need to look to see if any nav props exist in the target set that refer back to this same set, which might have
            // referential constraints also.
            keysFromReferentialIntegrityConstraint.Clear();
            IEdmNavigationProperty reverseNavProp = currentNavigationProperty.Partner;

            if (reverseNavProp != null)
            {
                keysFromReferentialIntegrityConstraint.AddRange(ExtractMatchingPropertyPairsFromReversedNavProp(reverseNavProp, targetKeyPropertyList));
            }

            foreach (EdmReferentialConstraintPropertyPair keyFromReferentialIntegrityConstraint in keysFromReferentialIntegrityConstraint)
            {
                KeyValuePair <string, object> valueFromParent = keySegmentOfParentEntity.Keys.SingleOrDefault(x => x.Key == keyFromReferentialIntegrityConstraint.PrincipalProperty.Name);
                if (valueFromParent.Key != null)
                {
                    // if the key from the referential integrity constraint is one of the target key properties
                    // and that key property isn't already populated in the raw key values from the uri, then
                    // we set that value to the value from the parent key segment.
                    if (targetKeyPropertyList.Any(x => x.Name == keyFromReferentialIntegrityConstraint.DependentProperty.Name))
                    {
                        rawKeyValuesFromUri.AddNamedValue(
                            keyFromReferentialIntegrityConstraint.DependentProperty.Name,
                            ConvertKeyValueToUriLiteral(valueFromParent.Value, rawKeyValuesFromUri.KeyAsSegment));
                    }
                }
            }

            // if we had a positional value before, then we need to add that value as a new named value.
            // the name that we choose will be the only value from the target entity key properties
            // that isn't already set in the NamedValues list.
            if (hasPositionalValues)
            {
                if (rawKeyValuesFromUri.NamedValues != null)
                {
                    List <IEdmStructuralProperty> unassignedProperties = targetKeyPropertyList.Where(x => !rawKeyValuesFromUri.NamedValues.ContainsKey(x.Name)).ToList();

                    if (unassignedProperties.Count == 1)
                    {
                        rawKeyValuesFromUri.AddNamedValue(unassignedProperties[0].Name, rawKeyValuesFromUri.PositionalValues[0]);
                    }
                    else
                    {
                        return(rawKeyValuesFromUri);
                    }

                    // clear out the positional value so that we keep a consistent state in the
                    // raw keys from uri.
                    rawKeyValuesFromUri.PositionalValues.Clear();
                }
                else
                {
                    return(rawKeyValuesFromUri);
                }
            }

            return(rawKeyValuesFromUri);
        }