예제 #1
0
 /// <summary>
 /// Constructor to create a new navigation link scope.
 /// </summary>
 /// <param name="writerState">The writer state for the new scope.</param>
 /// <param name="navLink">The navigation link for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal NavigationLinkScope(WriterState writerState, ODataNavigationLink navLink, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
     : base(writerState, navLink, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
 {
 }
예제 #2
0
 /// <summary>
 /// Create a new entry scope.
 /// </summary>
 /// <param name="entry">The entry for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 /// <returns>The newly create scope.</returns>
 protected abstract EntryScope CreateEntryScope(ODataEntry entry, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri);
예제 #3
0
 /// <summary>
 /// Constructor to create a new feed scope.
 /// </summary>
 /// <param name="feed">The feed for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal FeedScope(ODataFeed feed, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
     : base(WriterState.Feed, feed, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
 {
     this.serializationInfo = feed.SerializationInfo;
 }
예제 #4
0
            /// <summary>
            /// Constructor to create a new entry scope.
            /// </summary>
            /// <param name="entry">The entry for the new scope.</param>
            /// <param name="serializationInfo">The serialization info for the current entry.</param>
            /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
            /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
            /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
            /// <param name="writingResponse">true if we are writing a response, false if it's a request.</param>
            /// <param name="writerBehavior">The <see cref="ODataWriterBehavior"/> instance controlling the behavior of the writer.</param>
            /// <param name="selectedProperties">The selected properties of this scope.</param>
            /// <param name="odataUri">The ODataUri info of this scope.</param>
            /// <param name="enableValidation">Enable validation or not.</param>
            internal EntryScope(ODataEntry entry, ODataFeedAndEntrySerializationInfo serializationInfo, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, bool writingResponse, ODataWriterBehavior writerBehavior, SelectedPropertiesNode selectedProperties, ODataUri odataUri, bool enableValidation = true)
                : base(WriterState.Entry, entry, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
            {
                Debug.Assert(writerBehavior != null, "writerBehavior != null");

                if (entry != null)
                {
                    this.duplicatePropertyNamesChecker = new DuplicatePropertyNamesChecker(writerBehavior.AllowDuplicatePropertyNames, writingResponse, !enableValidation);
                }

                this.serializationInfo = serializationInfo;
            }
예제 #5
0
        private void PushScope(WriterState state, ODataItem item, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
        {
            Debug.Assert(
                state == WriterState.Error ||
                state == WriterState.Entry && (item == null || item is ODataEntry) ||
                state == WriterState.Feed && item is ODataFeed ||
                state == WriterState.NavigationLink && item is ODataNavigationLink ||
                state == WriterState.NavigationLinkWithContent && item is ODataNavigationLink ||
                state == WriterState.Start && item == null ||
                state == WriterState.Completed && item == null,
                "Writer state and associated item do not match.");

            Scope scope;
            switch (state)
            {
                case WriterState.Entry:
                    scope = this.CreateEntryScope((ODataEntry)item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                case WriterState.Feed:
                    scope = this.CreateFeedScope((ODataFeed)item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                case WriterState.NavigationLink:            // fall through
                case WriterState.NavigationLinkWithContent:
                    scope = this.CreateNavigationLinkScope(state, (ODataNavigationLink)item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                case WriterState.Start:                     // fall through
                case WriterState.Completed:                 // fall through
                case WriterState.Error:
                    scope = new Scope(state, item, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
                    break;
                default:
                    string errorMessage = Strings.General_InternalError(InternalErrorCodes.ODataWriterCore_Scope_Create_UnreachableCodePath);
                    Debug.Assert(false, errorMessage);
                    throw new ODataException(errorMessage);
            }

            this.scopes.Push(scope);
        }
예제 #6
0
 /// <summary>
 /// Constructor creating a new writer scope.
 /// </summary>
 /// <param name="state">The writer state of this scope.</param>
 /// <param name="item">The item attached to this scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of this scope should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal Scope(WriterState state, ODataItem item, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     this.state = state;
     this.item = item;
     this.entityType = entityType;
     this.navigationSource = navigationSource;
     this.skipWriting = skipWriting;
     this.selectedProperties = selectedProperties;
     this.odataUri = odataUri;
 }
        private void VerifyCombination(SelectedPropertiesNode left, SelectedPropertiesNode right, Action<SelectedPropertiesNode> verify)
        {
            var result = SelectedPropertiesNode.CombineNodes(left, right);
            verify(result);

            result = SelectedPropertiesNode.CombineNodes(right, left);
            verify(result);
        }
 private void AddMissingOperationsForAll(SelectedPropertiesNode selectedProperties)
 {
     AddMissingOperations(this.entry, this.entityType, selectedProperties, this.model, type => this.allOperations, entry => new NoOpEntityMetadataBuilder(entry), e => false);
 }
예제 #9
0
        /// <summary>Process sub expand node, set name for the node.</summary>
        /// <param name="nodeName">Node name for the subexpandnode.</param>
        /// <param name="subExpandNode">Generated sub expand node.</param>
        /// <returns>The sub expanded node passed in.</returns>
        private static SelectedPropertiesNode ProcessSubExpand(string nodeName, SelectedPropertiesNode subExpandNode)
        {
            if (subExpandNode != null)
            {
                subExpandNode.nodeName = nodeName;
            }

            return subExpandNode;
        }
예제 #10
0
        /// <summary>Create SelectedPropertiesNode using selected name list and expand node list.</summary>
        /// <param name="selectList">A list of selected item names.</param>
        /// <param name="expandList">A list of sub expanded nodes.</param>
        /// <returns>The generated SelectedPropertiesNode.</returns>
        private static SelectedPropertiesNode CombineSelectAndExpandResult(IList<string> selectList, IList<SelectedPropertiesNode> expandList)
        {
            List<string> rawSelect = selectList.ToList();
            rawSelect.RemoveAll(expandList.Select(m => m.nodeName).Contains);

            SelectedPropertiesNode node = new SelectedPropertiesNode(SelectionType.PartialSubtree)
            {
                selectedProperties = CreateSelectedPropertiesHashSet(),
                children = new Dictionary<string, SelectedPropertiesNode>(StringComparer.Ordinal)
            };

            foreach (string selectItem in rawSelect)
            {
                if (ProjectedPropertiesAnnotation.StarSegment == selectItem)
                {
                    node.hasWildcard = true;
                }
                else
                {
                    node.selectedProperties.Add(selectItem);
                }
            }

            foreach (var expandItem in expandList)
            {
                node.children[expandItem.nodeName] = expandItem;
            }

            return node;
        }
예제 #11
0
        /// <summary>
        /// Ensures that a child annotation for the specified segment name already exists; if not creates one.
        /// </summary>
        /// <param name="segmentName">The segment name to get the child annotation for.</param>
        /// <returns>The existing or newly created child annotation for the <paramref name="segmentName"/>.</returns>
        private SelectedPropertiesNode EnsureChildAnnotation(string segmentName)
        {
            Debug.Assert(segmentName != null, "segmentName != null");

            if (this.children == null)
            {
                this.children = new Dictionary<string, SelectedPropertiesNode>(StringComparer.Ordinal);
            }

            SelectedPropertiesNode childNode;
            if (!this.children.TryGetValue(segmentName, out childNode))
            {
                childNode = new SelectedPropertiesNode(SelectionType.PartialSubtree);
                this.children.Add(segmentName, childNode);
            }

            return childNode;
        }
예제 #12
0
        /// <summary>
        /// Recursively combines the left and right nodes. Used when there are type segments present in the select paths which
        /// causes there to be multiple children for the same property/navigation.
        /// </summary>
        /// <param name="left">The left node.</param>
        /// <param name="right">The right node.</param>
        /// <returns>The combined node.</returns>
        internal static SelectedPropertiesNode CombineNodes(SelectedPropertiesNode left, SelectedPropertiesNode right)
        {
            Debug.Assert(left != null, "left != null");
            Debug.Assert(right != null, "right != null");

            // if either one includes the entire subtree, then so does the result
            if (left.selectionType == SelectionType.EntireSubtree || right.selectionType == SelectionType.EntireSubtree)
            {
                return EntireSubtree;
            }

            // if the left hand side is empty, then use the right hand side
            if (left.selectionType == SelectionType.Empty)
            {
                // even if this is empty too, this all works
                return right;
            }

            // likewise, if the right hand side is empty, use the left
            if (right.selectionType == SelectionType.Empty)
            {
                return left;
            }

            Debug.Assert(left.selectionType == SelectionType.PartialSubtree, "left.selectionType == SelectionType.PartialSubtree");
            Debug.Assert(right.selectionType == SelectionType.PartialSubtree, "right.selectionType == SelectionType.PartialSubtree");

            var combined = new SelectedPropertiesNode(SelectionType.PartialSubtree)
            {
                hasWildcard = left.hasWildcard | right.hasWildcard
            };

            // copy over selected properties, combining as needed
            if (left.selectedProperties != null && right.selectedProperties != null)
            {
                combined.selectedProperties = CreateSelectedPropertiesHashSet(left.selectedProperties.AsEnumerable().Concat(right.selectedProperties));
            }
            else if (left.selectedProperties != null)
            {
                combined.selectedProperties = CreateSelectedPropertiesHashSet(left.selectedProperties);
            }
            else if (right.selectedProperties != null)
            {
                combined.selectedProperties = CreateSelectedPropertiesHashSet(right.selectedProperties);
            }

            // copy over children, combining as needed
            if (left.children != null && right.children != null)
            {
                combined.children = new Dictionary<string, SelectedPropertiesNode>(left.children);
                foreach (var child in right.children)
                {
                    SelectedPropertiesNode fromLeft;
                    if (combined.children.TryGetValue(child.Key, out fromLeft))
                    {
                        combined.children[child.Key] = CombineNodes(fromLeft, child.Value);
                    }
                    else
                    {
                        combined.children[child.Key] = child.Value;
                    }
                }
            }
            else if (left.children != null)
            {
                combined.children = new Dictionary<string, SelectedPropertiesNode>(left.children);
            }
            else if (right.children != null)
            {
                combined.children = new Dictionary<string, SelectedPropertiesNode>(right.children);
            }

            return combined;
        }
        private static void AddMissingOperations(ODataEntry entry, IEdmEntityType entityType, SelectedPropertiesNode selectedProperties, IEdmModel model, Func<IEdmType, IEdmOperation[]> getOperations, Func<ODataEntry, ODataEntityMetadataBuilder> getEntityMetadataBuilder = null, Func<IEdmEntityType, bool> typeIsOpen = null)
        {
            var metadataContext = new TestMetadataContext 
            {
                GetModelFunc = () => model,
                GetMetadataDocumentUriFunc = () => new Uri("http://temp.org/$metadata"),
                GetServiceBaseUriFunc = () => new Uri("http://temp.org/"),
                GetBindableOperationsForTypeFunc = getOperations,
                GetEntityMetadataBuilderFunc = getEntityMetadataBuilder,
                OperationsBoundToEntityTypeMustBeContainerQualifiedFunc = typeIsOpen,
            };

            var entryContext = ODataEntryMetadataContext.Create(entry, new TestFeedAndEntryTypeContext(), /*serializationInfo*/null, entityType, metadataContext, selectedProperties);
            var generator = new ODataMissingOperationGenerator(entryContext, metadataContext);
            List<ODataAction> actions = generator.GetComputedActions().ToList();
            List<ODataFunction> functions = generator.GetComputedFunctions().ToList();
            actions.ForEach(entry.AddAction);
            functions.ForEach(entry.AddFunction);
        }
예제 #14
0
 /// <summary>
 /// Creates a new navigation link scope.
 /// </summary>
 /// <param name="writerState">The writer state for the new scope.</param>
 /// <param name="navLink">The navigation link for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 /// <returns>The newly created navigation link scope.</returns>
 protected virtual NavigationLinkScope CreateNavigationLinkScope(WriterState writerState, ODataNavigationLink navLink, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     return new NavigationLinkScope(writerState, navLink, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
 }
 internal SelectedPropertiesNodeAssertions(SelectedPropertiesNode node) : base(node)
 {
 }
예제 #16
0
 /// <summary>
 /// Place where derived writers can perform custom steps before the entry is writen, at the begining of WriteStartEntryImplementation.
 /// </summary>
 /// <param name="entry">Entry to write.</param>
 /// <param name="typeContext">The context object to answer basic questions regarding the type of the entry or feed.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 protected virtual void PrepareEntryForWriteStart(ODataEntry entry, ODataFeedAndEntryTypeContext typeContext, SelectedPropertiesNode selectedProperties)
 {
     // No-op Atom and Verbose JSON. The JSON Light writer will override this method and inject the appropriate metadata builder
     // into the entry before writing.
     // When we support AutoComputePayloadMetadata for all formats in the future, we can inject the metadata builder in here and
     // remove virtual from this method.
 }
예제 #17
0
 protected override ODataWriterCore.EntryScope CreateEntryScope(ODataEntry entry, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     throw new NotImplementedException();
 }