Esempio n. 1
0
        /// <summary>
        /// Tracks a call to GetReadStream
        /// </summary>
        /// <param name="data">The context data</param>
        /// <param name="entity">The entity</param>
        /// <param name="name">The name of the stream or null to indicate the default stream</param>
        /// <param name="contentType">The content type from the returned stream response</param>
        /// <param name="headers">The headers from the returned stream response</param>
        public static void TrackGetReadStream(this DataServiceContextData data, object entity, string name, string contentType, IDictionary <string, string> headers)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");
            ExceptionUtilities.CheckArgumentNotNull(headers, "headers");

            EntityDescriptorData descriptorData;

            ExceptionUtilities.Assert(data.TryGetEntityDescriptorData(entity, out descriptorData), "Cannot set save stream on an entity that is not being tracked");

            if (name == null)
            {
                string etag;
                if (headers.TryGetValue(HttpHeaders.ETag, out etag))
                {
                    descriptorData.StreamETag = etag;
                }
            }
            else
            {
                var streamDescriptor = descriptorData.StreamDescriptors.SingleOrDefault(n => n.Name == name);
                ExceptionUtilities.CheckObjectNotNull(streamDescriptor, "Could not find stream descriptor with name '{0}' on entity descriptor: {1}", name, descriptorData);

                streamDescriptor.ContentType = contentType;
                streamDescriptor.UpdateFromHeaders(headers);
            }
        }
        private HttpRequestData CreateInsertRequest(DataServiceContextData dataBeforeSaveChanges, EntityDescriptorData entityDescriptorData)
        {
            Uri insertUri;

            if (entityDescriptorData.InsertLink != null)
            {
                insertUri = entityDescriptorData.InsertLink;
            }
            else
            {
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentForInsert, "Entity descriptor data did not have insert link or parent for insert: {0}", entityDescriptorData);
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentPropertyForInsert, "Entity descriptor data did not have insert link or parent property for insert: {0}", entityDescriptorData);

                var parentDescriptor = dataBeforeSaveChanges.GetEntityDescriptorData(entityDescriptorData.ParentForInsert);
                var linkInfo         = parentDescriptor.LinkInfos.SingleOrDefault(l => l.Name == entityDescriptorData.ParentPropertyForInsert);
                if (linkInfo != null && linkInfo.NavigationLink != null)
                {
                    insertUri = linkInfo.NavigationLink;
                }
                else
                {
                    insertUri = new Uri(UriHelpers.ConcatenateUriSegments(parentDescriptor.EditLink.OriginalString, entityDescriptorData.ParentPropertyForInsert));
                }
            }

            return(new HttpRequestData()
            {
                Verb = HttpVerb.Post, Uri = insertUri
            });
        }
        internal static Uri GetEntityInsertUri(DataServiceContextData contextData, EntityDescriptorData entityDescriptorData)
        {
            Uri insertUri;

            if (entityDescriptorData.InsertLink != null)
            {
                insertUri = entityDescriptorData.InsertLink;
            }
            else
            {
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentForInsert, "Entity descriptor data did not have insert link or parent for insert: {0}", entityDescriptorData);
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentPropertyForInsert, "Entity descriptor data did not have insert link or parent property for insert: {0}", entityDescriptorData);

                var parentDescriptor = contextData.GetEntityDescriptorData(entityDescriptorData.ParentForInsert);
                var linkInfo         = parentDescriptor.LinkInfos.SingleOrDefault(l => l.Name == entityDescriptorData.ParentPropertyForInsert);

                if (linkInfo != null && linkInfo.NavigationLink != null)
                {
                    insertUri = linkInfo.NavigationLink;
                }
                else
                {
                    insertUri = new Uri(UriHelpers.ConcatenateUriSegments(parentDescriptor.EditLink.OriginalString, entityDescriptorData.ParentPropertyForInsert), UriKind.RelativeOrAbsolute);
                    if (!insertUri.IsAbsoluteUri && contextData.BaseUri != null)
                    {
                        insertUri = new Uri(contextData.BaseUri, insertUri);
                    }
                }
            }

            return(insertUri);
        }
Esempio n. 4
0
        /// <summary>
        /// Tracks the DeleteLink method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackDeleteLink(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot delete link:", "source");

            EntityDescriptorData targetDescriptorData = GetTrackedEntityDescriptorData(data, target, "Cannot delete link:", "target");

            LinkDescriptorData descriptorData;

            if (data.TryGetLinkDescriptorData(sourceDescriptorData, sourcePropertyName, targetDescriptorData, out descriptorData) &&
                descriptorData.State == EntityStates.Added)
            {
                data.RemoveDescriptorData(descriptorData);
            }
            else
            {
                CheckStateIsNot(EntityStates.Added, sourceDescriptorData, "Cannot delete link:", "source");
                CheckStateIsNot(EntityStates.Added, targetDescriptorData, "Cannot delete link:", "target");

                if (descriptorData == null)
                {
                    data.CreateLinkDescriptorData(EntityStates.Deleted, data.GetNextChangeOrder(), sourceDescriptorData, sourcePropertyName, targetDescriptorData);
                }
                else if (descriptorData.State != EntityStates.Deleted)
                {
                    data.ChangeStateAndChangeOrder(descriptorData, EntityStates.Deleted, data.GetNextChangeOrder());
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Tracks the AttachLink method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackAttachLink(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");

            LinkDescriptorData linkDescriptorData;

            if (data.TryGetLinkDescriptorData(source, sourcePropertyName, target, out linkDescriptorData))
            {
                throw new TaupoInvalidOperationException(
                          string.Format(CultureInfo.InvariantCulture, "The link already exists: {0}.", linkDescriptorData.ToString()));
            }

            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot attach link:", "source");

            CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot attach link:", "source");
            CheckStateIsNot(EntityStates.Added, sourceDescriptorData, "Cannot attach link:", "source");

            EntityDescriptorData targetDescriptorData = null;

            if (target != null)
            {
                targetDescriptorData = GetTrackedEntityDescriptorData(data, target, "Cannot attach link:", "target");
                CheckStateIsNot(EntityStates.Deleted, targetDescriptorData, "Cannot attach link:", "target");
                CheckStateIsNot(EntityStates.Added, targetDescriptorData, "Cannot attach link:", "target");
            }

            data.CreateLinkDescriptorData(EntityStates.Unchanged, data.GetNextChangeOrder(), sourceDescriptorData, sourcePropertyName, targetDescriptorData);
        }
Esempio n. 6
0
        /// <summary>
        /// Tracks the Detach method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="entity">The entity.</param>
        /// <returns>Returns the expected result of the Detach method call.</returns>
        public static bool TrackDetach(this DataServiceContextData data, object entity)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");

            EntityDescriptorData entityDescriptorData;

            if (data.TryGetEntityDescriptorData(entity, out entityDescriptorData))
            {
                if (data.EntityDescriptorsData.Any(ed => ed.ParentForInsert == entity && !object.ReferenceEquals(ed, entityDescriptorData)))
                {
                    throw new TaupoInvalidOperationException(
                              string.Format(CultureInfo.InvariantCulture, "Cannot detach entity as it's used as a parent for insert. Entity descriptor data: {0}.", entityDescriptorData));
                }

                foreach (LinkDescriptorData link in data.LinkDescriptorsData
                         .Where(l => l.SourceDescriptor == entityDescriptorData || l.TargetDescriptor == entityDescriptorData).ToList())
                {
                    data.RemoveDescriptorData(link);
                }

                return(data.RemoveDescriptorData(entityDescriptorData));
            }

            return(false);
        }
        private ExpectedClientRequest CreateEntityInsertRequest(DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, SaveChangesOptions options)
        {
            ExceptionUtilities.Assert(!entityDescriptorData.IsMediaLinkEntry, "Can only be used for non media-link-entries");

            var insertUri = GetEntityInsertUri(contextData, entityDescriptorData);

            ExpectedClientRequest request = new ExpectedClientRequest()
            {
                Verb = HttpVerb.Post, Uri = insertUri
            };

            string preference = contextData.AddAndUpdateResponsePreference.ToHeaderValue();
            DataServiceProtocolVersion dsv = GetDataServiceVersion(HttpVerb.Post, preference);

            dsv = dsv.IncreaseVersionIfRequired(this.VersionCalculator.CalculateDataServiceVersion(entityDescriptorData, contextData.MaxProtocolVersion));

            var payload = this.BuildEntityPayload(contextData, propertyValuesBeforeSave, entityDescriptorData, dsv);

            request.Body = payload;

            this.AddFoldedLinksToEntityInsertPayload(contextData, entityDescriptorData, payload);

            request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(dsv);
            request.Headers[HttpHeaders.IfMatch]            = null;
            request.Headers[HttpHeaders.Prefer]             = preference;

            this.SetDefaultAcceptHeader(request, options);
            this.SetContentTypeHeaderForEntity(request);

            string hintString = @"Entity insert\r\n{{\r\n  Descriptor = {0}\r\n  Options = {1}\r\n}}";

            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData, options);

            return(request);
        }
        private void AddFoldedLinksToEntityInsertPayload(DataServiceContextData contextData, EntityDescriptorData entityDescriptorData, EntityInstance payload)
        {
            var entityType = this.ModelSchema.EntityTypes.Single(t => t.FullName == entityDescriptorData.EntityClrType.FullName);

            foreach (var linkDescriptor in contextData.LinkDescriptorsData.Where(l => l.SourceDescriptor == entityDescriptorData))
            {
                if (linkDescriptor.TargetDescriptor.State == EntityStates.Added)
                {
                    continue;
                }

                var navigationProperty = entityType.AllNavigationProperties.Single(n => n.Name == linkDescriptor.SourcePropertyName);

                string contentType = MimeTypes.ApplicationAtomXml + ";type=";
                if (navigationProperty.ToAssociationEnd.Multiplicity == EndMultiplicity.Many)
                {
                    contentType += "feed";
                }
                else
                {
                    contentType += "entry";
                }

                // note: the edit-link is used rather than identity because the server needs to be able to query for the target entity
                // and the identity may not be an actual uri
                var link = new DeferredLink()
                {
                    UriString = linkDescriptor.TargetDescriptor.EditLink.OriginalString
                }
                .WithContentType(contentType).WithTitleAttribute(linkDescriptor.SourcePropertyName);

                payload.Add(new NavigationPropertyInstance(linkDescriptor.SourcePropertyName, link));
            }
        }
        private ExpectedClientRequest CreateEntityUpdateRequest(DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, SaveChangesOptions options)
        {
            var request = new ExpectedClientRequest()
            {
                Verb = GetUpdateVerb(options),
                Uri  = entityDescriptorData.EditLink,
            };

            string preference = contextData.AddAndUpdateResponsePreference.ToHeaderValue();
            var    dsv        = GetDataServiceVersion(request.Verb, preference);

            dsv = dsv.IncreaseVersionIfRequired(this.VersionCalculator.CalculateDataServiceVersion(entityDescriptorData, contextData.MaxProtocolVersion));

            request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(dsv);
            request.Headers[HttpHeaders.IfMatch]            = entityDescriptorData.ETag;
            request.Headers[HttpHeaders.Prefer]             = preference;

            this.SetDefaultAcceptHeader(request, options);
            this.SetContentTypeHeaderForEntity(request);

            request.Body = this.BuildEntityPayload(contextData, propertyValuesBeforeSave, entityDescriptorData, dsv);

            string hintString = @"Entity update\r\n{{\r\n  Descriptor = {0}\r\n  Options = {1}\r\n}}";

            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData, options);

            return(request);
        }
        /// <summary>
        /// Wraps the specified product. If product is a DataServiceContext then registeres it for tracking.
        /// </summary>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="product">The product.</param>
        /// <returns>The wrapper for the product instance.</returns>
        public TResult Wrap <TResult>(object product) where TResult : IWrappedObject
        {
            if (product == null)
            {
                return(default(TResult));
            }

            Type[] argTypes   = new Type[] { typeof(IWrapperScope), typeof(object) };
            Type   resultType = typeof(TResult);

            ConstructorInfo ctor = resultType.GetInstanceConstructor(true, argTypes);

            ExceptionUtilities.CheckObjectNotNull(ctor, "Cannot find constructor: {0}(IWrapperScope, object)", typeof(TResult).Name);

            DSClient.DataServiceContext context = product as DSClient.DataServiceContext;

            if (context != null)
            {
                DataServiceProtocolVersion maxProtocolVersion = DataServiceProtocolVersion.Unspecified;
#if !WINDOWS_PHONE
                maxProtocolVersion = context.MaxProtocolVersion.ToTestEnum();
#endif
                var contextData = DataServiceContextData.CreateDataServiceContextDataFromDataServiceContext(context, maxProtocolVersion);

                this.contextDatas.Add(context, contextData);
            }

            return((TResult)ctor.Invoke(new object[] { this, product }));
        }
Esempio n. 11
0
 /// <summary>
 /// Initializes a new instance of the PipelineEmulator class
 /// </summary>
 /// <param name="parent">The parent instance to get dependencies from</param>
 /// <param name="contextData">The current context data</param>
 /// <param name="propertyValuesBeforeSave">The property values of the tracked client objects before the call to SaveChanges</param>
 /// <param name="options">The current save-changes options</param>
 /// <param name="requestResponsePairs">The observed http traffic for the current save-changes call</param>
 public PipelineEmulator(SaveChangesHttpValidatingEmulator parent, DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, SaveChangesOptions options, IEnumerable <KeyValuePair <IHttpRequest, HttpResponseData> > requestResponsePairs)
 {
     this.parent      = parent;
     this.contextData = contextData;
     this.propertyValuesBeforeSave = propertyValuesBeforeSave;
     this.options   = options;
     this.httpQueue = new Queue <KeyValuePair <IHttpRequest, HttpResponseData> >(requestResponsePairs);
 }
        /// <summary>
        /// Verifies the data service context.
        /// </summary>
        /// <param name="contextData">The expected data for the context.</param>
        /// <param name="context">The context to verify.</param>
        public void VerifyDataServiceContext(DataServiceContextData contextData, DataServiceContext context)
        {
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckArgumentNotNull(context, "context");

            var verifier = new Verifier(contextData, context);

            verifier.Verify();
        }
Esempio n. 13
0
        /// <summary>
        /// Tracks the UpdateObject method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="entity">The entity.</param>
        public static void TrackUpdateObject(this DataServiceContextData data, object entity)
        {
            var descriptorData = GetTrackedEntityDescriptorData(data, entity, "Failed to track UpdateObject:", "entity");

            if (descriptorData.State == EntityStates.Unchanged)
            {
                data.ChangeStateAndChangeOrder(descriptorData, EntityStates.Modified, data.GetNextChangeOrder());
            }
        }
Esempio n. 14
0
        /// <summary>
        /// Validates the requests sent, updates the expected state, and produces the expected response data for a single call to SaveChanges
        /// </summary>
        /// <param name="contextData">The context data at the time save-changes was called</param>
        /// <param name="propertyValuesBeforeSave">The property values of the tracked client objects before the call to SaveChanges</param>
        /// <param name="options">The save changes options used</param>
        /// <param name="requestResponsePairs">The observed HTTP traffic during save-changes</param>
        /// <returns>The expected response data</returns>
        public DataServiceResponseData ValidateAndTrackChanges(DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, SaveChangesOptions options, IEnumerable <KeyValuePair <HttpRequestData, HttpResponseData> > requestResponsePairs)
        {
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckArgumentNotNull(requestResponsePairs, "requestResponsePairs");

            var castPairs = requestResponsePairs.Select(p => new KeyValuePair <IHttpRequest, HttpResponseData>(p.Key, p.Value));
            var emulator  = new PipelineEmulator(this, contextData, propertyValuesBeforeSave, options, castPairs);

            return(emulator.Run());
        }
Esempio n. 15
0
        /// <summary>
        /// Tracks the AttachTo method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="entitySetName">Name of the entity set.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="identity">The identity.</param>
        /// <param name="entityETag">The etag for the entity.</param>
        /// <param name="editLink">The edit link for the entity</param>
        public static void TrackAttachTo(this DataServiceContextData data, string entitySetName, object entity, Uri identity, string entityETag, Uri editLink)
        {
            CheckEntitySetName(ref entitySetName);
            CheckEntityIsNotTracked(data, entity);
            CheckIdentity(data, identity);

            data.CreateEntityDescriptorData(EntityStates.Unchanged, data.GetNextChangeOrder(), entity)
            .SetEntitySetName(entitySetName)
            .SetETag(entityETag)
            .SetIdentity(identity)
            .SetEditLink(editLink);
        }
Esempio n. 16
0
        private static void CheckEntityIsNotTracked(DataServiceContextData data, object entity)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");

            EntityDescriptorData descriptorData;

            if (data.TryGetEntityDescriptorData(entity, out descriptorData))
            {
                throw new TaupoInvalidOperationException(
                          string.Format(CultureInfo.InvariantCulture, "Specified entity is already tracked by the descriptor data: {0}.", descriptorData.ToString()));
            }
        }
        private void ApplyNextResponseHeadersAndPayload(DataServiceContextData dataBeforeSaveChanges, EntityDescriptorData entityDescriptorData, Queue <DSClient.OperationResponse> responseQueue)
        {
            ExceptionUtilities.CheckArgumentNotNull(dataBeforeSaveChanges, "dataBeforeSaveChanges");
            ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData");
            ExceptionUtilities.CheckArgumentNotNull(responseQueue, "responseQueue");

            ExceptionUtilities.Assert(responseQueue.Count > 0, "Response queue unexpectedly empty");

            var responseForRequest = responseQueue.Dequeue();

            entityDescriptorData.UpdateFromHeaders(responseForRequest.Headers);
        }
Esempio n. 18
0
        /// <summary>
        /// Tracks the DeleteObject method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="entity">The entity.</param>
        public static void TrackDeleteObject(this DataServiceContextData data, object entity)
        {
            var descriptorData = GetTrackedEntityDescriptorData(data, entity, "Failed to track DeleteObject:", "entity");

            if (descriptorData.State == EntityStates.Added)
            {
                data.RemoveDescriptorData(descriptorData);
            }
            else if (descriptorData.State != EntityStates.Deleted)
            {
                data.ChangeStateAndChangeOrder(descriptorData, EntityStates.Deleted, data.GetNextChangeOrder());
            }
        }
Esempio n. 19
0
        private static EntityDescriptorData GetTrackedEntityDescriptorData(DataServiceContextData data, object entity, string errorMessage, string argumentName)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");

            EntityDescriptorData descriptorData;

            if (!data.TryGetEntityDescriptorData(entity, out descriptorData))
            {
                throw new TaupoInvalidOperationException(errorMessage + " " + argumentName + " is not tracked by the data service context data.");
            }

            return(descriptorData);
        }
        private void TrackSetSaveStream(DataServiceContextData data, MethodBase methodToTrack, object[] parameterValues)
        {
            string name;
            int    streamParameterIndex;
            bool   closeStream;
            IEnumerable <KeyValuePair <string, string> > headers;

            // if the second arg is not a string, then it is an MR, in which case null is correct
            if (methodToTrack.GetParameters()[1].Name == "name")
            {
                name = (string)parameterValues[1];
                streamParameterIndex = 2;
                closeStream          = (bool)parameterValues[3];
                var args = parameterValues[4] as DSClient.DataServiceRequestArgs;
                if (args == null)
                {
                    headers = new HttpHeaderCollection()
                    {
                        ContentType = (string)parameterValues[4]
                    };
                }
                else
                {
                    headers = args.Headers;
                }
            }
            else
            {
                name = null;
                streamParameterIndex = 1;
                closeStream          = (bool)parameterValues[2];
                var args = parameterValues[3] as DSClient.DataServiceRequestArgs;
                if (args == null)
                {
                    headers = new HttpHeaderCollection()
                    {
                        ContentType = (string)parameterValues[3], Slug = (string)parameterValues[4]
                    };
                }
                else
                {
                    headers = args.Headers;
                }
            }

            var streamProxy = parameterValues[streamParameterIndex] as IStreamLogger;

            ExceptionUtilities.CheckObjectNotNull(streamProxy, "Stream was not wrapped by a stream logger");
            data.TrackSetSaveStream(parameterValues[0], name, streamProxy, closeStream, headers);
        }
        private static HttpRequestData BuildBatchRequest(DataServiceContextData contextDataClone)
        {
            ExceptionUtilities.CheckObjectNotNull(contextDataClone.BaseUri, "Base uri cannot be null in batch cases");
            var batchRequest = new HttpRequestData()
            {
                Verb = HttpVerb.Post,
                Uri  = new Uri(UriHelpers.ConcatenateUriSegments(contextDataClone.BaseUri.OriginalString, Endpoints.Batch))
            };

            SetExpectedIfMatchHeader(batchRequest, null);
            SetUnexpectedPreferHeader(batchRequest);
            SetExpectedXHTTPMethodHeader(batchRequest, false);
            return(batchRequest);
        }
        /// <summary>
        /// Verifies that the values on the server are correct
        /// </summary>
        /// <param name="continuation">The async continuation</param>
        /// <param name="contextData">The context data</param>
        public void VerifyChangesOnServer(IAsyncContinuation continuation, DataServiceContextData contextData)
        {
            ExceptionUtilities.CheckArgumentNotNull(continuation, "continuation");
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            this.currentContextData = contextData;

            IEnumerable <ChangeData> expectedChanges;

            ExceptionUtilities.Assert(this.expectedChangeCache.TryGetValue(contextData, out expectedChanges), "Expected changes for given context have not been initialized");
            this.expectedChangeCache.Remove(contextData);

            AsyncHelpers.AsyncForEach(expectedChanges, continuation, this.VerifyChangeOnServer);
        }
Esempio n. 23
0
        /// <summary>
        /// Tracks the AddRelatedObject method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackAddRelatedObject(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            CheckEntityIsNotTracked(data, target);

            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot add link:", "source");

            CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot add related object:", "source");

            EntityDescriptorData targetDescriptorData = data.CreateEntityDescriptorData(EntityStates.Added, data.GetNextChangeOrder(), target);

            data.CreateLinkDescriptorData(EntityStates.Added, uint.MaxValue, sourceDescriptorData, sourcePropertyName, targetDescriptorData);

            targetDescriptorData
            .SetParentForInsert(source)
            .SetParentPropertyForInsert(sourcePropertyName);
        }
        private EntityInstance BuildEntityPayload(
            DataServiceContextData contextData,
            IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave,
            EntityDescriptorData entityDescriptorData,
            DataServiceProtocolVersion dsv)
        {
            IEnumerable <NamedValue> propertyValues;

            ExceptionUtilities.Assert(propertyValuesBeforeSave.TryGetValue(entityDescriptorData.Entity, out propertyValues), "Could not find property values for descriptor: {0}", entityDescriptorData);

            var entityType     = this.ModelSchema.EntityTypes.Single(t => t.FullName == entityDescriptorData.EntityClrType.FullName);
            var entityInstance = this.PayloadBuilder.EntityInstance(entityType, propertyValues);

            new ExpectedPayloadNormalizer(contextData, dsv).Normalize(entityInstance, entityDescriptorData);

            return(entityInstance);
        }
Esempio n. 25
0
        /// <summary>
        /// Tracks the AddObject method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="entitySetName">Name of the entity set.</param>
        /// <param name="entity">The entity.</param>
        public static void TrackAddObject(this DataServiceContextData data, string entitySetName, object entity)
        {
            CheckEntitySetName(ref entitySetName);
            CheckEntityIsNotTracked(data, entity);

            var entityDescriptorData = data.CreateEntityDescriptorData(EntityStates.Added, data.GetNextChangeOrder(), entity)
                                       .SetEntitySetName(entitySetName);

            if (data.ResolveEntitySet != null)
            {
                entityDescriptorData.InsertLink = data.ResolveEntitySet(entitySetName);
            }
            else
            {
                entityDescriptorData.InsertLink = new Uri(UriHelpers.ConcatenateUriSegments(data.BaseUri.OriginalString, entitySetName));
            }
        }
Esempio n. 26
0
        private static void CheckIdentity(DataServiceContextData data, Uri identity)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");

            if (identity == null)
            {
                throw new TaupoInvalidOperationException("Entity identity cannot be null or empty.");
            }

            EntityDescriptorData descriptorData;

            if (data.TryGetEntityDescriptorData(identity, out descriptorData))
            {
                throw new TaupoInvalidOperationException(
                          string.Format(CultureInfo.InvariantCulture, "There is already an entity descriptor data with the specified identity: {0}.", descriptorData.ToString()));
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Calculates an entity id based on the base uri, entity set resolver, set name, and entity key values
        /// </summary>
        /// <param name="contextData">The context data</param>
        /// <param name="entitySetName">the entity set name</param>
        /// <param name="entity">The entity to generate an id for</param>
        /// <returns>The id for the given entity</returns>
        public Uri CalculateEntityId(DataServiceContextData contextData, string entitySetName, object entity)
        {
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(entitySetName, "entitySetName");
            ExceptionUtilities.CheckArgumentNotNull(entity, "entity");

            if (contextData.BaseUri != null)
            {
                ExceptionUtilities.Assert(contextData.BaseUri.IsAbsoluteUri, "Base uri must be absolute. Uri was: '{0}'", contextData.BaseUri.OriginalString);
                return(new Uri(UriHelpers.ConcatenateUriSegments(contextData.BaseUri.AbsoluteUri, Uri.EscapeDataString(entitySetName) + this.CalculateEntityKey(entity))));
            }
            else
            {
                ExceptionUtilities.CheckObjectNotNull(contextData.ResolveEntitySet, "Entity set resolver cannot be null if base uri is null");
                var resolvedUri = contextData.ResolveEntitySet(entitySetName);
                ExceptionUtilities.CheckObjectNotNull(resolvedUri, "Entity set resolver returned null for set name '{0}'", entitySetName);
                return(new Uri(resolvedUri.AbsoluteUri + this.CalculateEntityKey(entity)));
            }
        }
Esempio n. 28
0
        /// <summary>
        /// Tracks a call to SetSaveStream
        /// </summary>
        /// <param name="data">The context data.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="name">The name of the stream or null to indicate the default stream.</param>
        /// <param name="saveStreamLogger">A logger for the save stream</param>
        /// <param name="closeStream">A value indicating whether or not to close the stream</param>
        /// <param name="headers">The headers for the request</param>
        public static void TrackSetSaveStream(this DataServiceContextData data, object entity, string name, IStreamLogger saveStreamLogger, bool closeStream, IEnumerable <KeyValuePair <string, string> > headers)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");
            ExceptionUtilities.CheckArgumentNotNull(saveStreamLogger, "saveStreamLogger");
            ExceptionUtilities.CheckArgumentNotNull(headers, "headers");

            EntityDescriptorData descriptorData;

            ExceptionUtilities.Assert(data.TryGetEntityDescriptorData(entity, out descriptorData), "Cannot set save stream on an entity that is not being tracked");

            StreamDescriptorData streamDescriptor;

            if (name == null)
            {
                if (descriptorData.State == EntityStates.Added)
                {
                    descriptorData.DefaultStreamState = EntityStates.Added;
                }
                else
                {
                    descriptorData.DefaultStreamState = EntityStates.Modified;
                }

                streamDescriptor = descriptorData.DefaultStreamDescriptor;
            }
            else
            {
                streamDescriptor = descriptorData.StreamDescriptors.SingleOrDefault(n => n.Name == name);
                if (streamDescriptor == null)
                {
                    streamDescriptor = descriptorData.CreateStreamDescriptorData(EntityStates.Modified, data.GetNextChangeOrder(), name);
                }
                else
                {
                    data.ChangeStateAndChangeOrder(streamDescriptor, EntityStates.Modified, data.GetNextChangeOrder());
                }
            }

            // we need to trap what the product reads from the stream to compare it against what is sent on the wire
            streamDescriptor.SaveStream = new SaveStreamData(saveStreamLogger, closeStream, headers);
        }
Esempio n. 29
0
        /// <summary>
        /// Tracks the SetLink method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackSetLink(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(sourcePropertyName, "sourcePropertyName");

            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot set link:", "source");

            CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot set link:", "source");

            EntityDescriptorData targetDescriptorData = null;

            if (target != null)
            {
                targetDescriptorData = GetTrackedEntityDescriptorData(data, target, "Cannot set link:", "target");
                CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot set link:", "target");
            }

            var relatedToSource = data.LinkDescriptorsData.Where(e => e.SourceDescriptor.Entity == source && e.SourcePropertyName == sourcePropertyName).ToList();

            if (relatedToSource.Count > 1)
            {
                throw new TaupoInvalidOperationException("Cannot set link: source contains multiple links for the property: " + sourcePropertyName);
            }

            LinkDescriptorData existingLinkDescriptorData = relatedToSource.FirstOrDefault();

            if (existingLinkDescriptorData == null)
            {
                data.CreateLinkDescriptorData(EntityStates.Modified, data.GetNextChangeOrder(), sourceDescriptorData, sourcePropertyName, targetDescriptorData);
            }
            else
            {
                if (existingLinkDescriptorData.State != EntityStates.Modified || existingLinkDescriptorData.TargetDescriptor != targetDescriptorData)
                {
                    data.ChangeStateAndChangeOrder(existingLinkDescriptorData, EntityStates.Modified, data.GetNextChangeOrder());
                }

                existingLinkDescriptorData.TargetDescriptor = targetDescriptorData;
            }
        }
Esempio n. 30
0
        /// <summary>
        /// Executes SaveChanges method on the specified context and verifies the results.
        /// </summary>
        /// <param name="continuation">The async continuation</param>
        /// <param name="contextData">The context data.</param>
        /// <param name="context">The context to verify SaveChanges.</param>
        /// <param name="options">The options for saving changes. Passing null will use the context's default.</param>
        /// <param name="onCompletion">callback for when save changes verification completes</param>
        public virtual void VerifySaveChanges(IAsyncContinuation continuation, DataServiceContextData contextData, DSClient.DataServiceContext context, SaveChangesOptions?options, Action <IAsyncContinuation, DSClient.DataServiceResponse> onCompletion)
        {
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckArgumentNotNull(context, "context");
            ExceptionUtilities.CheckArgumentNotNull(onCompletion, "onCompletion");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            // ensure that two calls are not being processed in parallel
            ExceptionUtilities.Assert(this.Input == null, "Input was not null, possibly due to simultaneous calls or using the wrong async continuation");
            ExceptionUtilities.Assert(this.State == null, "State was not null, possibly due to simultaneous calls or using the wrong async continuation");
            continuation = continuation.OnContinueOrFail(
                () =>
            {
                this.Input = null;
                this.State = null;
            });

            this.Input = new VerifierInput()
            {
                ContextData  = contextData,
                Context      = context,
                Options      = options,
                OnCompletion = onCompletion,
            };

            AsyncHelpers.RunActionSequence(
                continuation,
                this.InitializeState,
                this.VerifyContextState,
                this.CallProductApi,
                this.VerifyRequests,
                this.VerifyResponse,
                this.VerifyContextState,
                this.VerifyServerState,
                this.Complete);
        }