Example #1
0
        public void Create(FeedEntry entry)
        {
            if (IsValid(entry))
            {
                IFeedEntryEntityWrapper cWrapper = FeedEntryWrapperFactory.Create(_context.ResourceKind, _context);
                SdataTransactionResult  trResult = cWrapper.Add(entry);
                if (trResult.HttpStatus == System.Net.HttpStatusCode.Created ||
                    trResult.HttpStatus == System.Net.HttpStatusCode.OK)
                {
                    if (string.IsNullOrEmpty(entry.Id))
                    {
                        entry.Id = trResult.Location;
                    }

                    _request.Response.FeedEntry = entry;
                    _request.Response.Protocol.SendKnownResponseHeader(System.Net.HttpResponseHeader.Location, entry.Id);
                }
                else
                {
                    _request.Response.StatusCode = trResult.HttpStatus;
                    _request.Response.Diagnoses  = new Diagnoses();
                    _request.Response.Diagnoses.Add(GetDiagnosis(trResult));
                    //throw new InvalidDataException(trResult.HttpStatus + ": " + trResult.HttpMessage);
                }
            }
            else
            {
                throw new RequestException("Please use valid single resource url");
            }
        }
Example #2
0
 public CRUD(IRequest request)
 {
     _context = new RequestContext(request.Uri);
     _wrapper = FeedEntryWrapperFactory.Create(_context.ResourceKind, _context);
     _request = request;
 }
        public void Update(FeedEntry entry)
        {
            // only atom entry supported!!!
            if (_request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry)
            {
                throw new RequestException("Atom entry content type expected");
            }

            // resource key must exist in url
            if (string.IsNullOrEmpty(_requestContext.ResourceKey))
            {
                throw new RequestException("ResourceKey missing in requested url.");
            }

            string         requestEndPointUrl;
            RequestContext entryResourceAsRequestContext;

            string url;             // The url that references an existing resource
            string localId;         // will be parsed from urlAttrValue and set to the key attribute of the result resource payload
            Guid   uuid;            // the new uuid

            // retrieve the feed entry
            //entry = FeedComponentFactory.Create<ILinkingResourceFeedEntry>(request.Stream);


            // Get the uuid from query
            uuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(_requestContext.ResourceKey);


            if (null == entry)
            {
                throw new RequestException("sdata payload element missing");
            }

            // the consumer MUST provide an sdata:url attribute that references an existing resource.
            url = entry.Uri;
            if (string.IsNullOrEmpty(url))
            {
                throw new RequestException("sdata url attribute missing for resource payload element.");
            }


            // Parse the url of thew url attribute to get the local id.
            // Additionally we check for equality of the urls of the request url and
            // in the linked element up to the resourceKind.
            requestEndPointUrl            = _requestContext.OriginEndPoint;
            entryResourceAsRequestContext = new RequestContext(new Sage.Common.Syndication.SDataUri(url));    // TODO: not really nice here.
            string linkedResourceUrl = entryResourceAsRequestContext.OriginEndPoint;

            if (!string.Equals(requestEndPointUrl, linkedResourceUrl, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new RequestException("Request url and linked entry resource not matching.");
            }

            string resourceKindName = _requestContext.ResourceKind.ToString();

            localId = entryResourceAsRequestContext.ResourceKey;



            // The correlation store
            ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);


            // update the correlation entry in the sync store.
            // if uuid is not in use -> throw exception
            // if resource is already linked -> remove existing link, reassign link
            // if resource is not yet linked -> reassign link
            CorrelatedResSyncInfo[] correlations;
            CorrelatedResSyncInfo   correlationToModify = null;

            // retrieve the correlation we want to reassign by given uuid
            correlations = correlatedResSyncInfoStore.GetByUuid(resourceKindName, new Guid[] { uuid });
            if (correlations.Length > 0)
            {
                correlationToModify = correlations[0];
            }
            else
            {
                throw new RequestException("Uuid not in use");
            }

            //remember the old Correlation for the new localId, will be deleted after the update.
            CorrelatedResSyncInfo[] oldCorrelations = correlatedResSyncInfoStore.GetByLocalId(resourceKindName, new string[] { localId });

            // change the local ID to link to the new resource.
            // change the modification stamp and reset the tick
            correlationToModify.LocalId = localId;
            correlationToModify.ResSyncInfo.ModifiedStamp = DateTime.Now;
            correlationToModify.ResSyncInfo.Tick          = 1;

            // update the correlation
            correlatedResSyncInfoStore.Update(resourceKindName, correlationToModify);

            //If updating went OK, delete the old correlation for the new localId (should be only 1, for-loop just to be sure to catch em all)
            foreach (CorrelatedResSyncInfo oldCorrelation in oldCorrelations)
            {
                correlatedResSyncInfoStore.Delete(resourceKindName, oldCorrelation.ResSyncInfo.Uuid);
            }

            // If the service consumer only needs to retrieve the URL, not the actual payload,
            // it may do so by adding an empty select parameter to its request:
            // a) select parameter not exist -> return deep resource payload
            // b) select exists and empty -> return no resource payload
            // c) select exists and not empty -> return deep resource payload as we do not yet support payload filtering
            //    with select parameter.
            string tmpValue;
            // ?select
            bool includeResourcePayloads = true;    // default value, but check for select parameter now

            if (_requestContext.SdataUri.QueryArgs.TryGetValue("select", out tmpValue))
            {
                if (string.IsNullOrEmpty(_requestContext.SdataUri.QueryArgs["select"]))
                {
                    includeResourcePayloads = false;
                }
            }


            // Create an entity wrapper if resource data should be requested. Otherwise
            // leave wrapper null.
            IFeedEntryEntityWrapper wrapper = null;

            //if (includeResourcePayloads) //TODO: Comment this in as soon as there is a possibility to send empty payload objects
            wrapper = FeedEntryWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);

            /* Create the response entry */
            _request.Response.FeedEntry   = (FeedEntry)this.BuildFeedEntryForCorrelation(correlationToModify, wrapper);
            _request.Response.ContentType = MediaType.AtomEntry;
        }
        public void Create(FeedEntry entry)
        {
            // only atom entry supported!!!

            if (_request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry)
            {
                throw new RequestException("Atom entry content type expected");
            }

            string         requestEndPointUrl;
            RequestContext entryResourceAsRequestContext;

            string url;             // The url that references an existing resource
            string localId;         // will be parsed from urlAttrValue and set to the key attribute of the result resource payload
            Guid   uuid;            // the new uuid

            if (null == entry)
            {
                throw new RequestException("sdata payload element missing");
            }

            // the consumer MUST provide an sdata:url attribute that references an existing resource.
            url = entry.Uri;
            if (string.IsNullOrEmpty(url))
            {
                throw new RequestException("sdata url attribute missing for resource payload element.");
            }


            // Parse the url of thew url attribute to get the local id.
            // Additionally we check for equality of the urls of the request url and
            // in the linked element up to the resourceKind.
            requestEndPointUrl            = _requestContext.OriginEndPoint;
            entryResourceAsRequestContext = new RequestContext(new Sage.Common.Syndication.SDataUri(url));    // TODO: not really nice here.
            string linkedResourceUrl = entryResourceAsRequestContext.OriginEndPoint;

            if (!string.Equals(requestEndPointUrl, linkedResourceUrl, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new RequestException("Request url and linked entry resource not matching.");
            }

            string resourceKindName = _requestContext.ResourceKind.ToString();

            localId = entryResourceAsRequestContext.ResourceKey;

            ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);

            CheckExisting(correlatedResSyncInfoStore, localId);

            // try to get the new uuid from uuid attribute
            // if this attribute is not set a new one is created
            if (null == entry.UUID || entry.UUID == Guid.Empty)
            {
                uuid = Guid.NewGuid();
            }
            else
            {
                uuid = entry.UUID;
            }


            // store a new correlation entry to the sync store
            ResSyncInfo           newResSyncInfo = new ResSyncInfo(uuid, requestEndPointUrl, 0, string.Empty, DateTime.Now);
            CorrelatedResSyncInfo newInfo        = new CorrelatedResSyncInfo(localId, newResSyncInfo);

            correlatedResSyncInfoStore.Add(resourceKindName, newInfo);



            // If the service consumer only needs to retrieve the URL, not the actual payload,
            // it may do so by adding an empty select parameter to its request:
            // a) select parameter not exist -> return deep resource payload
            // b) select exists and empty -> return no resource payload
            // c) select exists and not empty -> return deep resource payload as we do not yet support payload filtering
            //    with select parameter.
            string tmpValue;
            // ?select
            bool includeResourcePayloads = true;    // default value, but check for select parameter now

            if (_requestContext.SdataUri.QueryArgs.TryGetValue("select", out tmpValue))
            {
                if (string.IsNullOrEmpty(_requestContext.SdataUri.QueryArgs["select"]))
                {
                    includeResourcePayloads = false;
                }
            }


            // Create an entity wrapper if resource data should be requested. Otherwise
            // leave wrapper null.
            IFeedEntryEntityWrapper wrapper = null;

            //if (includeResourcePayloads) //TODO: Comment this in as soon as there is a possibility to send empty payload objects
            wrapper = FeedEntryWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);

            /* Create the response entry */
            _request.Response.FeedEntry   = (FeedEntry)this.BuildFeedEntryForCorrelation(newInfo, wrapper);
            _request.Response.ContentType = MediaType.AtomEntry;

            _request.Response.StatusCode = System.Net.HttpStatusCode.Created;
            _request.Response.Protocol.SendUnknownResponseHeader("location", FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, uuid));
        }
        public void Read()
        {
            string                      resourceKindName;
            EntryRequestType            entryRequestType; // Multi or Single
            bool                        includeResourcePayloads;
            ICorrelatedResSyncInfoStore correlatedResSyncStore;

            CorrelatedResSyncInfo[] correlatedResSyncInfos;
            int      totalResult;               // number of correlations found
            PageInfo normalizedPageInfo;        // normalized pageInfo -> will be used for paging, etc.

            resourceKindName = _requestContext.ResourceKind.ToString();

            // multi or single entry request?
            entryRequestType = (String.IsNullOrEmpty(_requestContext.ResourceKey)) ? EntryRequestType.Multi : EntryRequestType.Single;

            // get store to request the correlations
            correlatedResSyncStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);


            // receive correlated resource synchronization entries
            if (entryRequestType == EntryRequestType.Multi)
            {
                int pageNumber = PagingHelpers.GetPageNumber(_request.Uri.StartIndex, _request.Uri.Count);

                correlatedResSyncInfos = correlatedResSyncStore.GetPaged(resourceKindName, pageNumber, (int)(_request.Uri.Count ?? DEFAULT_ITEMS_PER_PAGE), out totalResult);
            }
            else
            {
                Guid uuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(_requestContext.ResourceKey);
                correlatedResSyncInfos = correlatedResSyncStore.GetByUuid(resourceKindName, new Guid[] { uuid });
                totalResult            = correlatedResSyncInfos.Length;
                if (totalResult > 1)
                {
                    throw new ApplicationException("More than one resource for uuid exists.");
                }
                if (totalResult == 0)
                {
                    throw new RequestException("No resource found");
                }
            }


            // If the service consumer only needs to retrieve the URL, not the actual payload,
            // it may do so by adding an empty select parameter to its request:
            // a) select parameter not exist -> return deep resource payload
            // b) select exists and empty -> return no resource payload
            // c) select exists and not empty -> return deep resource payload as we do not yet support payload filtering
            //    with select parameter.
            string tmpValue;

            // ?select
            includeResourcePayloads = true;    // default value, but check for select parameter now
            if (_requestContext.SdataUri.QueryArgs.TryGetValue("select", out tmpValue))
            {
                if (string.IsNullOrEmpty(_requestContext.SdataUri.QueryArgs["select"]))
                {
                    includeResourcePayloads = false;
                }
            }



            if (entryRequestType == EntryRequestType.Single)
            {
                IFeedEntryEntityWrapper wrapper = null;
                //if (includeResourcePayloads) //TODO: Comment this in as soon as there is a possibility to send empty payload objects
                wrapper = FeedEntryWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);

                _request.Response.FeedEntry   = this.BuildFeedEntryForCorrelation(correlatedResSyncInfos[0], wrapper);
                _request.Response.ContentType = MediaType.AtomEntry;
            }
            else
            {
                // Create an empty feed
                Feed <FeedEntry> feed = new Feed <FeedEntry>();
                feed.Author      = new FeedAuthor();
                feed.Author.Name = "Northwind Adapter";
                feed.Category    = new FeedCategory("http://schemas.sage.com/sdata/categories", "collection", "Resource Collection");
                DateTime updateTime = DateTime.Now;

                string feedUrl             = _requestContext.SdataUri.ToString();             // the url requested
                string feedUrlWithoutQuery = (new Uri(feedUrl)).GetLeftPart(UriPartial.Path); // the url without query

                normalizedPageInfo = PagingHelpers.Normalize(_request.Uri.StartIndex, _request.Uri.Count, totalResult);

                IFeedEntryEntityWrapper wrapper = null;
                //if (includeResourcePayloads) //TODO: Comment this in as soon as there is a possibility to send empty payload objects
                wrapper = FeedEntryWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);

                // create a feed entry for each correlation.
                IEnumerator <CorrelatedResSyncInfo> pagedCorrelationEnumerator = PagingHelpers.GetPagedEnumerator <CorrelatedResSyncInfo>(normalizedPageInfo, correlatedResSyncInfos);
                while (pagedCorrelationEnumerator.MoveNext())
                {
                    // Create and append a feed entry per each id
                    FeedEntry entry = this.BuildFeedEntryForCorrelation(pagedCorrelationEnumerator.Current, wrapper);
                    if (entry != null)
                    {
                        feed.Entries.Add(entry);
                    }
                }


                // set feed title
                feed.Title = string.Format("{0} linked {1}", feed.Entries.Count, resourceKindName);

                // set feed update
                feed.Updated = updateTime;

                // set id
                feed.Id = feedUrl;

                // add links (general)
                feed.Links.AddRange(LinkFactory.CreateFeedLinks(_requestContext, feedUrl));

                #region PAGING & OPENSEARCH

                // add links (paging)
                feed.Links.AddRange(LinkFactory.CreatePagingLinks(normalizedPageInfo, totalResult, feedUrlWithoutQuery));

                /* OPENSEARCH */
                feed.ItemsPerPage = normalizedPageInfo.Count;
                feed.StartIndex   = normalizedPageInfo.StartIndex;
                feed.TotalResults = totalResult;

                #endregion

                _request.Response.Feed        = feed;
                _request.Response.ContentType = MediaType.Atom;
            }
        }
            // Asynchronous called method
            private void Execute(NorthwindConfig config, Digest targetDigest)
            {
                #region Declaration

                SdataContext                sdataContext;
                SupportedResourceKinds      resource;
                IAppBookmarkInfoStore       appBookmarkInfoStore;
                ICorrelatedResSyncInfoStore correlatedResSyncInfoStore;
                ISyncSyncDigestInfoStore    syncDigestStore;
                ISynctickProvider           tickProvider;
                string     resourceKind;
                string     EndPoint;
                int        nexttick = 1;
                Token      lastToken;
                Token      nextToken;
                Identity[] changedIdentites;
                IFeedEntryEntityWrapper wrapper;

                #endregion

                #region init

                sdataContext               = _parentPerformer._requestContext.SdataContext;
                resource                   = _parentPerformer._requestContext.ResourceKind;
                resourceKind               = resource.ToString();
                EndPoint                   = _parentPerformer._requestContext.DatasetLink + resourceKind;
                appBookmarkInfoStore       = NorthwindAdapter.StoreLocator.GetAppBookmarkStore(sdataContext);
                correlatedResSyncInfoStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(sdataContext);
                syncDigestStore            = NorthwindAdapter.StoreLocator.GetSyncDigestStore(sdataContext);
                tickProvider               = NorthwindAdapter.StoreLocator.GettickProvider(sdataContext);

                wrapper = FeedEntryWrapperFactory.Create(resource, _parentPerformer._requestContext);

                #endregion

                #region get last token or create a new one

                if (!appBookmarkInfoStore.Get <Token>(resourceKind, out lastToken))
                {
                    lastToken             = new Token();
                    lastToken.InitRequest = true;
                }

                #endregion


                #region Get local identities of changed entries since last synchronisation

                changedIdentites = wrapper.Entity.GetLastChanges(lastToken, config, out nextToken);

                #endregion

                if (resource == SupportedResourceKinds.phoneNumbers)
                {
                    #region workaround for phones
                    for (int index = 0; index < changedIdentites.Length; index++)
                    {
                        string phoneid = changedIdentites[index].Id + Sage.Integration.Northwind.Application.API.Constants.PhoneIdPostfix;
                        string faxId   = changedIdentites[index].Id + Sage.Integration.Northwind.Application.API.Constants.FaxIdPostfix;


                        // receive the resource payloads for the phone id and for the fax id
                        // so that we can calculate their current etags.
                        FeedEntry phoneResourcePayloadContainer = wrapper.GetFeedEntry(phoneid);
                        FeedEntry faxResourcePayloadConatainer  = wrapper.GetFeedEntry(faxId);

                        string etag;
                        CorrelatedResSyncInfo[] correlatedResSyncInfos;

                        #region Phone
                        if (phoneResourcePayloadContainer != null)
                        {
                            // calculate etag of the resource
                            etag = EtagServices.ComputeEtag(phoneResourcePayloadContainer, true);   // new etag

                            // retrieve correlations for the current identity from synch storage
                            correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { phoneid });

                            // if no correlation exists AND resource has been deleted:
                            // -> continue with next id
                            // else if no correlation exists:
                            // -> get next tick, create new correlation and add correlation to synch store
                            // otherwise and if the etag stored in synch store is different than etag previously calculated:
                            // -> get next tick, modify existing correlation and update it in synch store.
                            if (correlatedResSyncInfos.Length == 0 && phoneResourcePayloadContainer.IsDeleted)
                            {
                                continue;
                            }
                            else if (correlatedResSyncInfos.Length == 0)
                            {
                                nexttick = tickProvider.CreateNexttick(resourceKind); // create next tick

                                ResSyncInfo           resyncInfo = new ResSyncInfo(Guid.NewGuid(), EndPoint, nexttick, etag, DateTime.Now);
                                CorrelatedResSyncInfo info       = new CorrelatedResSyncInfo(phoneid, resyncInfo);

                                correlatedResSyncInfoStore.Put(resourceKind, info);

                                syncDigestStore.PersistNewer(resourceKind, info.ResSyncInfo);
                            }
                            else if (!correlatedResSyncInfos[0].ResSyncInfo.Etag.Equals(etag))
                            {
                                nexttick = tickProvider.CreateNexttick(resourceKind);
                                correlatedResSyncInfos[0].ResSyncInfo.Etag          = etag;
                                correlatedResSyncInfos[0].ResSyncInfo.Tick          = nexttick;
                                correlatedResSyncInfos[0].ResSyncInfo.EndPoint      = EndPoint;
                                correlatedResSyncInfos[0].ResSyncInfo.ModifiedStamp = DateTime.Now;
                                correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfos[0]);

                                syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfos[0].ResSyncInfo);
                            }
                        }

                        #endregion

                        #region Fax
                        if (faxResourcePayloadConatainer != null)
                        {
                            // calculate etag of the resource
                            etag = EtagServices.ComputeEtag(faxResourcePayloadConatainer, true);   // new etag

                            // retrieve correlations for the current identity from synch storage
                            correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { faxId });

                            // if no correlation exists AND resource has been deleted:
                            // -> continue with next id
                            // else if no correlation exists:
                            // -> get next tick, create new correlation and add correlation to synch store
                            // otherwise and if the etag stored in synch store is different than etag previously calculated:
                            // -> get next tick, modify existing correlation and update it in synch store.
                            if (correlatedResSyncInfos.Length == 0 && faxResourcePayloadConatainer.IsDeleted)
                            {
                                continue;
                            }
                            else if (correlatedResSyncInfos.Length == 0)
                            {
                                nexttick = tickProvider.CreateNexttick(resourceKind); // create next tick

                                ResSyncInfo           resyncInfo = new ResSyncInfo(Guid.NewGuid(), EndPoint, nexttick, etag, DateTime.Now);
                                CorrelatedResSyncInfo info       = new CorrelatedResSyncInfo(faxId, resyncInfo);

                                correlatedResSyncInfoStore.Put(resourceKind, info);

                                syncDigestStore.PersistNewer(resourceKind, info.ResSyncInfo);
                            }
                            else if (!correlatedResSyncInfos[0].ResSyncInfo.Etag.Equals(etag))
                            {
                                nexttick = tickProvider.CreateNexttick(resourceKind);
                                correlatedResSyncInfos[0].ResSyncInfo.Etag          = etag;
                                correlatedResSyncInfos[0].ResSyncInfo.Tick          = nexttick;
                                correlatedResSyncInfos[0].ResSyncInfo.EndPoint      = EndPoint;
                                correlatedResSyncInfos[0].ResSyncInfo.ModifiedStamp = DateTime.Now;
                                correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfos[0]);

                                syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfos[0].ResSyncInfo);
                            }
                        }

                        #endregion
                    }
                    #endregion
                }
                else
                {
                    string    id;
                    FeedEntry resourcePayloadContainer;
                    CorrelatedResSyncInfo[] correlatedResSyncInfos;
                    string etag;

                    // iterate through the collection of ids of all changed resources.
                    for (int index = 0; index < changedIdentites.Length; index++)
                    {
                        // current id from iterated collection
                        id = changedIdentites[index].Id;

                        // get resource payload container for the current identity so that we can calculated the
                        // etag.
                        // continue with next identity if no resource was found.
                        resourcePayloadContainer = wrapper.GetFeedEntry(id);

                        // calculate etag of the current resource payload
                        etag = EtagServices.ComputeEtag(resourcePayloadContainer, true);


                        // retrieve correlations for the current identity from synch storage
                        correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { id });


                        // if no correlation exists AND resource has been deleted:
                        // -> continue with next id
                        // else if no correlation exists:
                        // -> get next tick, create new correlation and add correlation to synch store
                        // otherwise and if the etag stored in synch store is different than etag previously calculated:
                        // -> get next tick, modify existing correlation and update it in synch store.
                        if (resourcePayloadContainer == null || (correlatedResSyncInfos.Length == 0 && resourcePayloadContainer.IsDeleted))
                        {
                            continue;
                        }
                        else if (correlatedResSyncInfos.Length == 0)
                        {
                            nexttick = tickProvider.CreateNexttick(resourceKind); // create next tick

                            ResSyncInfo           resyncInfo = new ResSyncInfo(Guid.NewGuid(), EndPoint, nexttick, etag, DateTime.Now);
                            CorrelatedResSyncInfo info       = new CorrelatedResSyncInfo(id, resyncInfo);

                            correlatedResSyncInfoStore.Put(resourceKind, info);

                            syncDigestStore.PersistNewer(resourceKind, info.ResSyncInfo);
                        }
                        else if (!correlatedResSyncInfos[0].ResSyncInfo.Etag.Equals(etag))
                        {
                            nexttick = tickProvider.CreateNexttick(resourceKind);
                            correlatedResSyncInfos[0].ResSyncInfo.Etag          = etag;
                            correlatedResSyncInfos[0].ResSyncInfo.Tick          = nexttick;
                            correlatedResSyncInfos[0].ResSyncInfo.EndPoint      = EndPoint;
                            correlatedResSyncInfos[0].ResSyncInfo.ModifiedStamp = DateTime.Now;
                            correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfos[0]);

                            syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfos[0].ResSyncInfo);
                        }
                    }
                }

                #region store next token

                appBookmarkInfoStore.Put(resourceKind, nextToken);

                #endregion

                // set tracking phase
                lock (_parentPerformer._asyncStateObj)
                {
                    _parentPerformer._asyncStateObj.Tracking.Phase = TrackingPhase.GETCHANGESBYtick;
                }



                if (null != targetDigest)
                {
                    ICorrelatedResSyncInfoEnumerator enumerator;
                    List <string> EndPoints = new List <string>();
#warning remove this workaround
                    if (targetDigest.Entries != null)
                    {
                        foreach (DigestEntry targetDigestEntry in targetDigest.Entries)
                        {
                            EndPoints.Add(targetDigestEntry.EndPoint);
                            enumerator = correlatedResSyncInfoStore.GetSincetick(resourceKind, targetDigestEntry.EndPoint, ((int)targetDigestEntry.Tick) - 1);
                            while (enumerator.MoveNext())
                            {
                                // No lock needed, as we expect that CorrelatedResSyncInfos list is
                                // only acceeded anywhere else when Tracking phase is 'finish'.
                                //lock(_parentPerformer._asyncStateObj)
                                //{
                                _parentPerformer._asyncStateObj.CorrelatedResSyncInfos.Add(enumerator.Current);
                                //}
                            }
                        }
                    }

                    SyncDigestInfo sourceSyncDigestInfo = syncDigestStore.Get(resourceKind);
                    foreach (SyncDigestEntryInfo digestEntry in sourceSyncDigestInfo)
                    {
                        if (EndPoints.Contains(digestEntry.EndPoint))
                        {
                            continue;
                        }
                        EndPoints.Add(digestEntry.EndPoint);
                        enumerator = correlatedResSyncInfoStore.GetSincetick(resourceKind, digestEntry.EndPoint, -1);
                        while (enumerator.MoveNext())
                        {
                            // No lock needed, as we expect that CorrelatedResSyncInfos list is
                            // only acceeded anywhere else when Tracking phase is 'finish'.
                            //lock(_parentPerformer._asyncStateObj)
                            //{
                            _parentPerformer._asyncStateObj.CorrelatedResSyncInfos.Add(enumerator.Current);
                            //}
                        }
                    }
                    if (!EndPoints.Contains(EndPoint))
                    {
                        enumerator = correlatedResSyncInfoStore.GetSincetick(resourceKind, EndPoint, -1);
                        while (enumerator.MoveNext())
                        {
                            // No lock needed, as we expect that CorrelatedResSyncInfos list is
                            // only acceeded anywhere else when Tracking phase is 'finish'.
                            //lock(_parentPerformer._asyncStateObj)
                            //{
                            _parentPerformer._asyncStateObj.CorrelatedResSyncInfos.Add(enumerator.Current);
                            //}
                        }
                    }
                }

                // Set tracking phase to FINISH
                lock (_parentPerformer._asyncStateObj.Tracking)
                {
                    _parentPerformer._asyncStateObj.Tracking.Phase = TrackingPhase.FINISH;
                }
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="config"></param>
            /// <returns></returns>
            /// <remarks>This method is not threadsafe as the performer must be finished when calling this method.</remarks>
            public Feed <FeedEntry> GetFeed(NorthwindConfig config, PageInfo normalizedPageInfo)
            {
                Feed <FeedEntry>       syncSourceFeed;
                SdataContext           sdataContext;
                SupportedResourceKinds resource;
                string resourceKind;
                string EndPoint;
                Guid   trackingId;

                List <CorrelatedResSyncInfo> correlatedResSyncInfos;

                sdataContext           = _parentPerformer._requestContext.SdataContext;
                resource               = _parentPerformer._requestContext.ResourceKind;
                resourceKind           = resource.ToString();
                correlatedResSyncInfos = _parentPerformer._asyncStateObj.CorrelatedResSyncInfos;
                EndPoint               = _parentPerformer._requestContext.DatasetLink + resourceKind;
                trackingId             = _parentPerformer._requestContext.TrackingId;


                //ISyncSyncDigestInfoStore syncDigestStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetSyncDigestStore(sdataContext);
                ISyncSyncDigestInfoStore syncDigestStore = NorthwindAdapter.StoreLocator.GetSyncDigestStore(sdataContext);
                SyncDigestInfo           syncDigestInfo  = syncDigestStore.Get(resourceKind);

                // Create a new Feed instance
                syncSourceFeed             = new Feed <FeedEntry>();//FeedComponentFactory.Create<ISyncSourceFeed>();
                syncSourceFeed.Author      = new FeedAuthor();
                syncSourceFeed.Author.Name = "Northwind Adapter";
                syncSourceFeed.Category    = new FeedCategory("http://schemas.sage.com/sdata/categories", "collection", "Resource Collection");



                #region Digest

                syncSourceFeed.Digest         = new Digest();
                syncSourceFeed.Digest.Entries = (syncDigestInfo == null) ? new DigestEntry[0] : new DigestEntry[syncDigestInfo.Count];

                // set digest origin
                syncSourceFeed.Digest.Origin = _parentPerformer._requestContext.OriginEndPoint;

                if (syncDigestInfo != null)
                {
                    // convert and set digest entries from synch store object to feed object
                    for (int i = 0; i < syncDigestInfo.Count; i++)
                    {
                        syncSourceFeed.Digest.Entries[i] = new DigestEntry();

                        syncSourceFeed.Digest.Entries[i].ConflictPriority = syncDigestInfo[i].ConflictPriority;
                        syncSourceFeed.Digest.Entries[i].EndPoint         = syncDigestInfo[i].EndPoint;
                        syncSourceFeed.Digest.Entries[i].Tick             = (int)syncDigestInfo[i].Tick;
                        syncSourceFeed.Digest.Entries[i].Stamp            = DateTime.Now;
                    }
                }

                #endregion

                #region Entries

                // retrieve the data connection wrapper
                IFeedEntryEntityWrapper wrapper = FeedEntryWrapperFactory.Create(resource, _parentPerformer._requestContext);

                IEnumerator <CorrelatedResSyncInfo> correlationEnumerator = PagingHelpers.GetPagedEnumerator <CorrelatedResSyncInfo>(normalizedPageInfo, correlatedResSyncInfos.ToArray());
                while (correlationEnumerator.MoveNext())
                {
                    syncSourceFeed.Entries.Add(this.BuildFeedEntry(correlationEnumerator.Current, wrapper));
                }

                #endregion

                // initialize the feed
                string feedUrl             = string.Format("{0}/$syncSource('{1}')", EndPoint, trackingId);
                string feedUrlWithoutQuery = (new Uri(feedUrl)).GetLeftPart(UriPartial.Path);   // the url without query
                // set id tag
                syncSourceFeed.Id = feedUrl;
                // set title tag
                syncSourceFeed.Title = string.Format("{0} synchronization source feed {1}", resourceKind.ToString(), trackingId);
                // set update
                // syncSourceFeed.Updated = DateTime.Now;
                // set syncMode
                syncSourceFeed.SyncMode = SyncMode.catchUp;// syncModeenum.catchUp;

                // add links (general)
                syncSourceFeed.Links.AddRange(LinkFactory.CreateFeedLinks(_parentPerformer._requestContext, feedUrl));

                #region PAGING & OPENSEARCH

                // add links (paging)
                syncSourceFeed.Links.AddRange(LinkFactory.CreatePagingLinks(normalizedPageInfo, correlatedResSyncInfos.Count, feedUrlWithoutQuery));

                /* OPENSEARCH */
                syncSourceFeed.ItemsPerPage = normalizedPageInfo.Count;
                syncSourceFeed.StartIndex   = normalizedPageInfo.StartIndex;
                syncSourceFeed.TotalResults = correlatedResSyncInfos.Count;

                #endregion

                return(syncSourceFeed);
            }
            // Asynchronous called method
            private void Execute(NorthwindConfig config, IFeed feed, Digest sourceDigest)
            {
                #region Declarations

                SdataContext                sdataContext;
                SupportedResourceKinds      resource;
                IAppBookmarkInfoStore       appBookmarkInfoStore;
                ICorrelatedResSyncInfoStore correlatedResSyncInfoStore;
                ISyncSyncDigestInfoStore    syncDigestStore;

                GuidConverter guidConverter = new GuidConverter();
                string        resourceKind;
                string        EndPoint;
                //Digest sourceDigest;
                SyncDigestInfo targetDigest;

                IFeedEntryEntityWrapper wrapper;

                #endregion

                #region init

                sdataContext               = _parentPerformer._requestContext.SdataContext;
                resource                   = _parentPerformer._requestContext.ResourceKind;
                resourceKind               = resource.ToString();
                EndPoint                   = _parentPerformer._requestContext.DatasetLink + resourceKind;
                appBookmarkInfoStore       = NorthwindAdapter.StoreLocator.GetAppBookmarkStore(sdataContext);
                correlatedResSyncInfoStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(sdataContext);
                syncDigestStore            = NorthwindAdapter.StoreLocator.GetSyncDigestStore(sdataContext);
//#warning implement this
                //sourceDigest = new Digest();
                //sourceDigest = ((Feed<FeedEntry>)feed).Digest;
                targetDigest = syncDigestStore.Get(resourceKind);
                wrapper      = FeedEntryWrapperFactory.Create(resource, _parentPerformer._requestContext);

                #endregion

                #region process entries

                bool sourceIsDeleteMode;
                SdataTransactionResult sdTrResult;
                SyncState sourceState;
                SyncState targetState;
                foreach (FeedEntry entry in feed.Entries)
                {
                    sdTrResult = null;

                    try
                    {
                        // Check whether the source entry had been deleted.
                        // if not we expect a payload!
                        // The variable 'sourceIsDeleteMode' holds the result of this check for later calls.
                        if (entry.IsDeleted)
                        {
                            sourceIsDeleteMode = true;
                        }

                        /*else if (null == entry.Payload)
                         *  throw new Exception("Payload missing.");*/
                        else
                        {
                            sourceIsDeleteMode = false;
                        }

                        // get the source syncstate
                        sourceState = entry.SyncState;
                        string uuidString = entry.UUID.ToString();
                        Guid   uuid       = entry.UUID;

                        // Look into the store to get all correlations of the uuid received from source
                        CorrelatedResSyncInfo[] corelations = correlatedResSyncInfoStore.GetByUuid(resourceKind, new Guid[] { uuid });

                        if (corelations.Length == 0)
                        {
                            if (sourceIsDeleteMode)
                            {
                                // the source entry had been deleted and no correlation exists for this
                                // entry in the target.
                                // So we do nothing here.
                                sdTrResult              = new SdataTransactionResult();
                                sdTrResult.HttpStatus   = HttpStatusCode.OK;
                                sdTrResult.HttpMessage  = "OK";
                                sdTrResult.HttpMethod   = HttpMethod.DELETE;
                                sdTrResult.ResourceKind = resource;
                                sdTrResult.Uuid         = uuidString;
                            }
                            else
                            {
                                // no target entry exists for the updated or added source entry.
                                // So we add the source entry to the application and add a new correlation to the sync store.
                                // If this operation fails we will have to set the result state to conflict.
                                try
                                {
                                    // add the entry to application
                                    sdTrResult = wrapper.Add(entry);

                                    if ((sdTrResult != null) && ((sdTrResult.HttpStatus == HttpStatusCode.OK) || (sdTrResult.HttpStatus == HttpStatusCode.Created)))
                                    {
                                        string etag = EtagServices.ComputeEtag(entry, true);

                                        ResSyncInfo resSyncInfo =
                                            new ResSyncInfo(uuid, entry.SyncState.EndPoint,
                                                            (entry.SyncState.Tick > 0) ? entry.SyncState.Tick : 1, etag, entry.SyncState.Stamp);

                                        CorrelatedResSyncInfo correlatedResSyncInfo = new CorrelatedResSyncInfo(sdTrResult.LocalId, resSyncInfo);

                                        // store the new correlation to the sync store
                                        correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfo);
                                        // update the sync digest entry if the tick of the source entry is newer than the actual tick of the target.
                                        syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfo.ResSyncInfo);
                                    }
                                }
                                catch (Exception e)
                                {
                                    // in case of an unexpected error while adding a new entry to target
                                    // we create a transaction result with the state 'Conflict'
                                    sdTrResult              = new SdataTransactionResult();
                                    sdTrResult.HttpStatus   = HttpStatusCode.Conflict;
                                    sdTrResult.HttpMethod   = HttpMethod.POST;
                                    sdTrResult.HttpMessage  = e.ToString();
                                    sdTrResult.ResourceKind = resource;
                                    sdTrResult.Uuid         = uuidString;
                                }
                            }
                        }
                        else
                        {
                            string key = corelations[0].LocalId;
                            // a correlation was found for the source entry.

                            #region update or delete

                            try
                            {
                                bool doUpdate = false;
                                //bool doDelete = false;
                                bool isConflict = true;

                                // set the Key from correlation to the entry.Payload.Key property
                                // only if source had not been deleted.
                                if (!sourceIsDeleteMode)
                                {
                                    entry.Key = corelations[0].LocalId;
                                }

                                targetState = Helper.GetSyncState(corelations[0]);


                                //If sourceState.EndPoint = targetState.EndPoint,
                                //there is no conflict and the update must be applied
                                //if sourceState.Tick > targetState.tick.
                                if (targetState.EndPoint.Equals(sourceState.EndPoint, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    isConflict = false;
                                    if (sourceState.Tick > targetState.Tick)
                                    {
                                        //if (!sourceIsDeleteMode)
                                        doUpdate = true;
                                        //else
                                        //    doDelete = true;
                                    }
                                }
                                else
                                {
                                    SyncState sourceDigestSyncState = Helper.GetSyncState(sourceDigest, targetState.EndPoint);;
                                    SyncState targetDigestSyncState = Helper.GetSyncState(targetDigest, sourceState.EndPoint);

                                    //If targetState is contained in sourceDigest,
                                    //i.e. if sourceDigest has a digest entry E such that E.EndPoint = targetState.EndPoint
                                    //and E.Tick >= targetState.Tick, there is no conflict and the update must be applied.
                                    if (sourceDigestSyncState != null)
                                    {
                                        if (sourceDigestSyncState.Tick > targetState.Tick)
                                        {
                                            doUpdate   = true;
                                            isConflict = false;
                                        }
                                    }


                                    //If sourceState is contained in targetDigest,
                                    //i.e. if targetDigest has a digest entry E such that E.EndPoint = sourceState.EndPoint
                                    //and E.Tick >= sourceState.Tick, there is no conflict and the update must be ignored
                                    //(target has the most recent version).
                                    if (targetDigestSyncState != null)
                                    {
                                        if (targetDigestSyncState.Tick > sourceState.Tick)
                                        {
                                            doUpdate   = false;
                                            isConflict = false;
                                        }
                                    }



                                    //Otherwise (targetState not contained in sourceDigest, sourceState not contained in targetDigest),
                                    //there is a conflict.
                                    if ((sourceDigestSyncState == null) && (targetDigestSyncState == null))
                                    {
                                        isConflict = true;
                                    }
                                }

                                //****************** Conflict ****************
                                //In case of conflict, the target EndPoint uses the following algorithm to resolve the conflict:
                                //Let sourceEntry be the sourceDigest digest entry such that sourceEntry.EndPoint = sourceState.EndPoint.
                                //Let targetEntry be the targetDigest digest entry such that targetEntry.EndPoint = targetState.EndPoint.
                                //If sourceEntry .conflictPriority <> targetEntry .conflictPriority, the side with lowest priority wins.
                                if (isConflict)
                                {
                                    int sourceConflictPriority = Helper.GetConflictPriority(sourceDigest, sourceState.EndPoint);
                                    int targetConflictPriority = Helper.GetConflictPriority(targetDigest, targetState.EndPoint);

                                    if (sourceConflictPriority > targetConflictPriority)
                                    {
                                        doUpdate = true;
                                    }
                                    else if (sourceConflictPriority < targetConflictPriority)
                                    {
                                        doUpdate = false;
                                    }
                                    else
                                    {
                                        //Otherwise (sourceEntry .conflictPriority = targetEntry .conflictPriority),
                                        //then sourceState.stamp and targetState.stamp are compared
                                        //and the entry with the most recent timestamp wins.
                                        if (sourceState.Stamp > targetState.Stamp)
                                        {
                                            doUpdate = true;
                                        }
                                    }
                                }
                                ResSyncInfo resSyncInfo =
                                    new ResSyncInfo(uuid, entry.SyncState.EndPoint,
                                                    (entry.SyncState.Tick > 0)?entry.SyncState.Tick:1, "", entry.SyncState.Stamp);


                                if (doUpdate && !sourceIsDeleteMode)
                                {
                                    // update the entry in the application and update the sync store
                                    sdTrResult = wrapper.Update(entry);

                                    if ((sdTrResult != null) && (sdTrResult.HttpStatus == HttpStatusCode.OK))
                                    {
                                        string etag = EtagServices.ComputeEtag(entry, true);

                                        resSyncInfo =
                                            new ResSyncInfo(uuid, entry.SyncState.EndPoint,
                                                            (entry.SyncState.Tick > 0) ? entry.SyncState.Tick : 1, etag, entry.SyncState.Stamp);

                                        CorrelatedResSyncInfo correlatedResSyncInfo = new CorrelatedResSyncInfo(sdTrResult.LocalId, resSyncInfo);

                                        correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfo);
                                    }
                                }
                                else if (!doUpdate && !sourceIsDeleteMode)
                                {
                                    sdTrResult              = new SdataTransactionResult();
                                    sdTrResult.HttpStatus   = HttpStatusCode.Conflict;
                                    sdTrResult.HttpMethod   = HttpMethod.PUT;
                                    sdTrResult.HttpMessage  = "";
                                    sdTrResult.ResourceKind = resource;
                                    sdTrResult.Uuid         = uuidString;
                                    sdTrResult.LocalId      = key;
                                }
                                else if (doUpdate && sourceIsDeleteMode)
                                {
                                    // delete the entry in the application and update the sync store
                                    // we do not support nested deletion. So only TradingAccounts and SalesOrders can be deleted.
                                    if (resource == SupportedResourceKinds.tradingAccounts ||
                                        resource == SupportedResourceKinds.salesOrders)
                                    {
                                        sdTrResult = wrapper.Delete(corelations[0].LocalId);

                                        if ((sdTrResult != null) && (sdTrResult.HttpStatus == HttpStatusCode.OK))
                                        {
                                            correlatedResSyncInfoStore.Delete(resource.ToString(), corelations[0].ResSyncInfo.Uuid);
                                        }
                                    }
                                    else
                                    {
                                        // this  does not correspond to real fact, what we did at target side!
                                        sdTrResult              = new SdataTransactionResult();
                                        sdTrResult.HttpStatus   = HttpStatusCode.OK;
                                        sdTrResult.HttpMessage  = "OK";
                                        sdTrResult.HttpMethod   = HttpMethod.DELETE;
                                        sdTrResult.ResourceKind = resource;
                                        sdTrResult.Uuid         = uuidString;
                                        sdTrResult.LocalId      = key;
                                    }
                                }
                                else
                                {
                                    sdTrResult              = new SdataTransactionResult();
                                    sdTrResult.HttpStatus   = HttpStatusCode.Conflict;
                                    sdTrResult.HttpMessage  = "";
                                    sdTrResult.HttpMethod   = HttpMethod.DELETE;
                                    sdTrResult.ResourceKind = resource;
                                    sdTrResult.Uuid         = uuidString;
                                    sdTrResult.LocalId      = key;
                                }

                                syncDigestStore.PersistNewer(resourceKind, resSyncInfo);
                            }
                            catch (Exception e)
                            {
                                sdTrResult              = new SdataTransactionResult();
                                sdTrResult.HttpStatus   = HttpStatusCode.Conflict;
                                sdTrResult.HttpMethod   = HttpMethod.PUT;
                                sdTrResult.HttpMessage  = e.ToString();
                                sdTrResult.ResourceKind = resource;
                                sdTrResult.Uuid         = uuidString;
                                sdTrResult.LocalId      = key;
                            }
                            #endregion
                        }
                    }

                    catch (Exception e)
                    {
                        sdTrResult              = new SdataTransactionResult();
                        sdTrResult.HttpStatus   = HttpStatusCode.Conflict;
                        sdTrResult.HttpMessage  = e.ToString();
                        sdTrResult.ResourceKind = resource;
                        //sdTrResult.Uuid = entry.Payload.PayloadContainer.Uuid;
                    }

                    #region store transaction result

                    if (sdTrResult != null)
                    {
                        lock (_parentPerformer._asyncStateObj)
                        {
                            this._parentPerformer._asyncStateObj.TransactionResults.Add(sdTrResult);
                        }
                    }

                    #endregion
                }
                #endregion


                // Set tracking phase
                lock (_parentPerformer._asyncStateObj.Tracking)
                {
                    _parentPerformer._asyncStateObj.Tracking.Phase = TrackingPhase.FINISH;
                }
            }
            /// <summary>
            ///
            /// </summary>
            /// <param name="config"></param>
            /// <returns></returns>
            /// <remarks>This method is not threadsafe as the performer must be finished when calling this method.</remarks>
            public Feed <FeedEntry> GetFeed(NorthwindConfig config, PageInfo normalizedPageInfo)
            {
                Feed <FeedEntry> syncTargetFeed = new Feed <FeedEntry>();

                syncTargetFeed.Author      = new FeedAuthor();
                syncTargetFeed.Author.Name = "Northwind Adapter";
                syncTargetFeed.Category    = new FeedCategory("http://schemas.sage.com/sdata/categories", "collection", "Resource Collection");

                SdataContext           sdataContext;
                SupportedResourceKinds resource;
                string resourceKind;
                string EndPoint;
                Guid   trackingId;

                List <SdataTransactionResult> transactinResults;

                sdataContext      = _parentPerformer._requestContext.SdataContext;
                resource          = _parentPerformer._requestContext.ResourceKind;
                resourceKind      = resource.ToString();
                transactinResults = _parentPerformer._asyncStateObj.TransactionResults;
                EndPoint          = _parentPerformer._requestContext.DatasetLink + resourceKind;;
                trackingId        = _parentPerformer._requestContext.TrackingId;


                // Create a new Feed instance


                // retrieve the data connection wrapper
                IFeedEntryEntityWrapper wrapper = FeedEntryWrapperFactory.Create(resource, _parentPerformer._requestContext);

                IEnumerator <SdataTransactionResult> transactionResultEnumerator = PagingHelpers.GetPagedEnumerator <SdataTransactionResult>(normalizedPageInfo, transactinResults.ToArray());

                while (transactionResultEnumerator.MoveNext())
                {
                    syncTargetFeed.Entries.Add(this.BuildFeedEntry(transactionResultEnumerator.Current, wrapper));
                }

                // initialize the feed
                string feedUrl             = string.Format("{0}/$syncTarget('{1}')", EndPoint, trackingId);
                string feedUrlWithoutQuery = (new Uri(feedUrl)).GetLeftPart(UriPartial.Path);   // the url without query

                // set id tag
                syncTargetFeed.Id = feedUrl;
                // set title tag
                syncTargetFeed.Title = string.Format("{0} synchronization target feed {1}", resourceKind.ToString(), trackingId);
                // set update
#warning  implement this
                //syncTargetFeed.Updated = DateTime.Now;
                // set syncMode
                syncTargetFeed.SyncMode = SyncMode.catchUp;

                // add links (general)
                syncTargetFeed.Links.AddRange(LinkFactory.CreateFeedLinks(_parentPerformer._requestContext, feedUrl));


                #region PAGING & OPENSEARCH

                // add links (paging)
                syncTargetFeed.Links.AddRange(LinkFactory.CreatePagingLinks(normalizedPageInfo, transactinResults.Count, feedUrlWithoutQuery));

                /* OPENSEARCH */
                syncTargetFeed.ItemsPerPage = normalizedPageInfo.Count;
                syncTargetFeed.StartIndex   = normalizedPageInfo.StartIndex;
                syncTargetFeed.TotalResults = transactinResults.Count;

                #endregion


                return(syncTargetFeed);
            }