예제 #1
0
        public virtual SyncFeedEntry GetFeedEntry(SdataTransactionResult transactionResult)
        {
            SyncFeedEntry result;

            if (!String.IsNullOrEmpty(transactionResult.LocalId))
            {
                result = GetFeedEntry(transactionResult.LocalId);
            }
            else
            {
                result      = new SyncFeedEntry();
                result.Uuid = transactionResult.Uuid;
            }
            if (result == null)
            {
                return(null);
            }

            //entry.Uuid = transactionResult.Uuid;

            result.HttpStatusCode = transactionResult.HttpStatus;
            result.HttpMessage    = transactionResult.HttpMessage;;
            result.HttpMethod     = transactionResult.HttpMethod;
            result.HttpLocation   = transactionResult.Location;
            result.HttpETag       = transactionResult.Etag;
            return(result);
        }
        private void BuildResponseFeed(ref IRequest request, computePriceResponsetype computePriceResponse)
        {
            ComputePriceResponsePayload computePriceResponsePayload = new ComputePriceResponsePayload();

            computePriceResponsePayload.ComputePriceResponse = computePriceResponse;


            SyncFeedEntry entry = new SyncFeedEntry();

            entry.Payload = computePriceResponsePayload;

            entry.Id      = _requestContext.SdataUri.Uri.ToString();
            entry.Title   = "computePrice";
            entry.Updated = DateTime.Now;

            //entry.Links
            //entry.Categories


            SyncFeed feed = new SyncFeed();

            feed.FeedType = FeedType.ResourceEntry;
            feed.Entries.Add(entry);
            request.Response.Serializer  = new SyncFeedSerializer();
            request.Response.Feed        = feed;
            request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry;
        }
예제 #3
0
        public void DoWork(IRequest request)
        {
            string       resourceKind = _requestContext.ResourceKind.ToString();
            string       endpoint     = _requestContext.DatasetLink + resourceKind;
            SdataContext sdataContext = _requestContext.SdataContext;

            ISyncSyncDigestInfoStore syncDigestStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetSyncDigestStore(sdataContext);

            SyncDigestInfo syncDigestInfo = syncDigestStore.Get(resourceKind);

            SyncDigestPayload syncDigestPayload = new SyncDigestPayload();

            syncDigestPayload.Digest.Origin = endpoint;
            // create a new initial syncDigest and store it.
            if ((null == syncDigestInfo) || (syncDigestInfo.Count == 0))
            {
                SyncFeedDigestEntry entry = new SyncFeedDigestEntry();
                entry.ConflictPriority = 0;
                entry.Endpoint         = endpoint;
                entry.Stamp            = DateTime.Now;
                entry.Tick             = -1;
                syncDigestPayload.Digest.Entries.Add(entry);
            }
            else
            {
                foreach (SyncDigestEntryInfo digestEntry in syncDigestInfo)
                {
                    SyncFeedDigestEntry entry = new SyncFeedDigestEntry();
                    entry.ConflictPriority = digestEntry.ConflictPriority;
                    entry.Endpoint         = digestEntry.Endpoint;
                    //entry.Stamp = digestEntry.;
                    entry.Tick = digestEntry.Tick;
                    syncDigestPayload.Digest.Entries.Add(entry);
                }
            }
            SyncFeed feed = new SyncFeed();
            string   url  = endpoint + "/$syncDigest";
            FeedLink link = new FeedLink(url, LinkType.Self, MediaType.AtomEntry);

            feed.Links = new FeedLinkCollection();
            feed.Links.Add(link);
            feed.Id       = url;
            feed.FeedType = FeedType.ResourceEntry;
            SyncFeedEntry syncFeedEntry = new SyncFeedEntry();

            syncFeedEntry.Payload = syncDigestPayload;
            syncFeedEntry.Title   = "Synchronization digest";
            syncFeedEntry.Id      = url;

            syncFeedEntry.Links.Add(link);
            feed.Entries.Add(syncFeedEntry);

            feed.Id = url;

            request.Response.Serializer  = new SyncFeedSerializer();
            request.Response.Feed        = feed;
            request.Response.ContentType = MediaType.AtomEntry;
        }
예제 #4
0
        public void DoWork(IRequest request)
        {
            if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry)
            {
                throw new RequestException("Atom entry content type expected");
            }

            if (!String.IsNullOrEmpty(_requestContext.ResourceKey))
            {
                throw new RequestException("Please use resource url");
            }

            // read entry from stream
            SyncFeedEntry entry  = new SyncFeedEntry();
            XmlReader     reader = XmlReader.Create(request.Stream);

            reader.MoveToContent();

            entry.ReadXml(reader, ResourceKindHelpers.GetPayloadType(_requestContext.ResourceKind));

            IEntityWrapper wrapper = EntityWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);


            Document document = wrapper.GetTransformedDocument(entry.Payload, entry.SyncLinks);

            if (!String.IsNullOrEmpty(document.Id))
            {
                throw new RequestException("Entity alredy exists");
            }

            // Add Document

            SdataTransactionResult sdTrResult = wrapper.Add(entry.Payload, entry.SyncLinks);

            if (sdTrResult == null)
            {
                throw new RequestException("Entity does not exists"); //?????
            }
            if ((sdTrResult.HttpStatus == System.Net.HttpStatusCode.OK) ||
                (sdTrResult.HttpStatus == System.Net.HttpStatusCode.Created))
            {
                // store correlation
                SyncFeedEntry responseEntry = wrapper.GetFeedEntry(sdTrResult.LocalId);

                SyncFeed feed = new SyncFeed();
                feed.FeedType = FeedType.ResourceEntry;
                feed.Entries.Add(responseEntry);
                request.Response.StatusCode = System.Net.HttpStatusCode.Created;
                request.Response.Serializer = new SyncFeedSerializer();
                request.Response.Feed       = feed;
                request.Response.Protocol.SendUnknownResponseHeader("Location", responseEntry.Id);
                request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry;
            }
            else
            {
                throw new RequestException(sdTrResult.HttpMessage);
            }
        }
예제 #5
0
        public override SyncFeedEntry GetFeedEntry(string idString)
        {
            #region declarations
            int            recordCount;
            DataSets.Order order = new DataSets.Order();
            CalculatedOrdersTableAdapter tableAdapter;
            tableAdapter = new CalculatedOrdersTableAdapter();
            CalculatedOrderDetailsTableAdapter detailTableAdapter;
            detailTableAdapter = new CalculatedOrderDetailsTableAdapter();
            //DeletedOrderDetailsTableAdapter deletedDetailTableAdapter;
            //deletedDetailTableAdapter = new DeletedOrderDetailsTableAdapter();


            int id;
            if (!(Int32.TryParse(idString, out id)))
            {
                id = 0;
            }
            #endregion


            #region fill dataset
            using (OleDbConnection connection = new OleDbConnection(_context.Config.ConnectionString))
            {
                tableAdapter.Connection = connection;
                recordCount             = tableAdapter.FillBy(order.CalculatedOrders, id);
                if (recordCount == 0)
                {
                    return(null);
                }

                detailTableAdapter.Connection = connection;
                detailTableAdapter.FillBy(order.CalculatedOrderDetails, id);

                //deletedDetailTableAdapter.Connection = connection;
                //deletedDetailTableAdapter.Fill(order.DeletedOrderDetails, id.ToString(), lastToken.SequenceNumber, config.CrmUser);
            }
            #endregion


            SyncFeedEntry entry = new SyncFeedEntry();
            entry.Id = String.Format("{0}{1}('{2}')", _context.DatasetLink, _resourceKind.ToString(), idString);

            entry.Title   = String.Format("{0}: {1}", _resourceKind.ToString(), idString);
            entry.Updated = DateTime.Now;

            entry.Payload = GetPayload((DataSets.Order.CalculatedOrdersRow)order.CalculatedOrders[0],
                                       order.CalculatedOrderDetails,
                                       //order.DeletedOrderDetails,
                                       _context.Config);

            entry.SyncLinks.AddRange(GetLinks(entry.Payload.ForeignIds));

            return(entry);
        }
        public void DoWork(IRequest request)
        {
            if (request.ContentType != Sage.Common.Syndication.MediaType.Atom)
            {
                throw new RequestException("Atom content type expected");
            }

            //read feed
            string    resourceKindName = _requestContext.ResourceKind.ToString();
            SyncFeed  feed             = new SyncFeed();
            XmlReader reader           = XmlReader.Create(request.Stream);

            feed.ReadXml(reader, ResourceKindHelpers.GetPayloadType(_requestContext.ResourceKind));

            /* iterate through all entries and store result information */
            ISyncResultInfoStore syncResultInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetSyncResultStore(_requestContext.SdataContext);

            int    noOfEntries = feed.Entries.Count;
            string endpoint    = string.Empty;

            try
            {
                endpoint = new RequestContext(new Sage.Common.Syndication.SDataUri(feed.Id)).OriginEndPoint;
            }
            catch { }

            SyncResultEntryInfo[] syncResultEntries = new SyncResultEntryInfo[noOfEntries];
            for (int i = 0; i < noOfEntries; i++)
            {
                SyncFeedEntry entry      = (SyncFeedEntry)feed.Entries[i];
                string        httpMethod = entry.HttpMethod;
                int           httpStatus = -1;
                if (Enum.IsDefined(typeof(HttpStatusCode), entry.HttpStatusCode.ToString()))
                {
                    httpStatus = (int)Enum.Parse(typeof(HttpStatusCode), entry.HttpStatusCode.ToString(), true);
                }
                string httpLocation = entry.HttpLocation;
                string httpMessage  = entry.HttpMessage;
                string diagnosisXml = XmlSerializationHelpers.SerializeObjectToXml(entry.Diagnoses);
                string payloadXml   = XmlSerializationHelpers.SerializeObjectToXml(entry.Payload);

                syncResultEntries[i] = new SyncResultEntryInfo(httpMethod, httpStatus, httpLocation, httpMessage, diagnosisXml, payloadXml, DateTime.Now, endpoint);
            }

            syncResultInfoStore.Add(resourceKindName, syncResultEntries);
        }
예제 #7
0
        public virtual SyncFeedEntry GetFeedEntry(CorrelatedResSyncInfo resSyncInfo)
        {
            SyncFeedEntry result = GetFeedEntry(resSyncInfo.LocalId);

            if (result == null)
            {
                return(null);
            }


            result.Uuid               = resSyncInfo.ResSyncInfo.Uuid;
            result.HttpETag           = resSyncInfo.ResSyncInfo.Etag;
            result.HttpMethod         = "PUT";
            result.SyncState.Endpoint = resSyncInfo.ResSyncInfo.Endpoint;
            result.SyncState.Tick     = resSyncInfo.ResSyncInfo.Tick;
            result.SyncState.Stamp    = resSyncInfo.ResSyncInfo.ModifiedStamp;

            return(result);
        }
예제 #8
0
        public override SyncFeedEntry GetFeedEntry(string id)
        {
            SyncFeedEntry result = new SyncFeedEntry();

            result.Payload = PayloadFactory.CreatePayload(_resourceKind);

            Identity        identity;
            AccountDocument accountDocument;
            Account         account = new Account();

            identity        = new Identity(account.EntityName, id);
            accountDocument = (AccountDocument)_entity.GetDocument(identity, _emptyToken, _context.Config);
            if (accountDocument.LogState == LogState.Deleted)
            {
                return(null);
            }
            if (accountDocument.addresses.documents.Count == 0)
            {
                return(null);
            }

            Document document = accountDocument.addresses.documents[0];
            List <SyncFeedEntryLink> links;

            result.Payload = GetTransformedPayload(document, out links);

            string taUuid = GetTradingAccountUuid(accountDocument.Id);

            if (!String.IsNullOrEmpty(taUuid))
            {
                SyncFeedEntryLink tradingAccountLink = SyncFeedEntryLink.CreateRelatedLink(
                    String.Format("{0}{1}('{2}')", _context.DatasetLink, SupportedResourceKinds.tradingAccounts.ToString(), accountDocument.Id),
                    SupportedResourceKinds.tradingAccounts.ToString(),
                    _tradingAccountUuidPayloadPath, taUuid);
                links.Add(tradingAccountLink);
            }
            result.SyncLinks = links;
            result.Id        = String.Format("{0}{1}('{2}')", _context.DatasetLink, _resourceKind.ToString(), id);
            result.Title     = String.Format("{0}: {1}", _resourceKind.ToString(), id);
            result.Updated   = DateTime.Now;
            return(result);
        }
예제 #9
0
        public virtual SyncFeedEntry GetFeedEntry(string id)
        {
            SyncFeedEntry result = new SyncFeedEntry();

            result.Payload = PayloadFactory.CreatePayload(_resourceKind);

            Identity identity;
            Document document;

            identity = GetIdentity(id);
            document = _entity.GetDocument(identity, _emptyToken, _context.Config);
            if (document.LogState == LogState.Deleted)
            {
                return(null);
            }
            List <SyncFeedEntryLink> links;

            result.Payload   = GetTransformedPayload(document, out links);
            result.Id        = String.Format("{0}{1}('{2}')", _context.DatasetLink, _resourceKind.ToString(), id);
            result.Title     = String.Format("{0}: {1}", _resourceKind.ToString(), id);
            result.Updated   = DateTime.Now;
            result.SyncLinks = links;
            return(result);
        }
            // Asynchronous called method
            private void Execute(NorthwindConfig config, SyncFeedDigest syncDigestInfo)
            {
                #region Declaration

                SdataContext                sdataContext;
                SupportedResourceKinds      resource;
                IAppBookmarkInfoStore       appBookmarkInfoStore;
                ICorrelatedResSyncInfoStore correlatedResSyncInfoStore;
                ISyncSyncDigestInfoStore    syncDigestStore;
                ISyncTickProvider           tickProvider;
                string         resourceKind;
                string         endpoint;
                int            nextTick = 0;
                Token          lastToken;
                Token          nextToken;
                Identity[]     changedIdentites;
                IEntityWrapper wrapper;

                #endregion

                #region init

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

                wrapper = EntityWrapperFactory.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 feed entry for local identity
                        SyncFeedEntry phoneentry = wrapper.GetFeedEntry(phoneid);
                        SyncFeedEntry faxentry   = wrapper.GetFeedEntry(faxId);
                        if (phoneentry == null && faxentry == null)
                        {
                            continue;
                        }
                        // receive the correlation for the local identity


                        if (phoneentry != null)
                        {
                            CorrelatedResSyncInfo[] correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { phoneid });



                            string etag = EtagServices.ComputeEtag(phoneentry.Payload, true);   // new etag
                            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);
                            }
                        }
                        if (faxentry != null)
                        {
                            CorrelatedResSyncInfo[] correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { faxId });

                            string etag = EtagServices.ComputeEtag(faxentry.Payload, true);   // new etag
                            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
                }
                else
                {
                    for (int index = 0; index < changedIdentites.Length; index++)
                    {
                        string id = changedIdentites[index].Id;
                        // receive the feed entry for local identity
                        SyncFeedEntry entry = wrapper.GetFeedEntry(id);
                        if (entry == null)
                        {
                            continue;
                        }
                        // receive the correlation for the local identity



                        CorrelatedResSyncInfo[] correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { id });



                        string etag = EtagServices.ComputeEtag(entry.Payload, true);   // new etag
                        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;
                }


                // Receive syncDigestInfo
                if (null != syncDigestInfo)
                {
                    ICorrelatedResSyncInfoEnumerator enumerator;
                    List <string> endpoints = new List <string>();

                    foreach (SyncFeedDigestEntry digestEntry in syncDigestInfo.Entries)
                    {
                        endpoints.Add(digestEntry.Endpoint);
                        enumerator = correlatedResSyncInfoStore.GetSinceTick(resourceKind, digestEntry.Endpoint, digestEntry.Tick - 2);
                        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
                lock (_parentPerformer._asyncStateObj.Tracking)
                {
                    _parentPerformer._asyncStateObj.Tracking.Phase = TrackingPhase.FINISH;
                }
            }
예제 #11
0
        public override SyncFeed GetFeed()
        {
            bool includeUuid;

            string whereClause = string.Empty;

            OleDbParameter[] oleDbParameters = null;

            if (this is IEntityQueryWrapper)
            {
                QueryFilterBuilder queryFilterBuilder = new QueryFilterBuilder((IEntityQueryWrapper)this);

                queryFilterBuilder.BuildSqlStatement(_context, out whereClause, out oleDbParameters);
            }

            SyncFeed feed = new SyncFeed();

            feed.Title = _resourceKind.ToString() + ": " + DateTime.Now.ToString();

            Token emptyToken = new Token();


            List <Identity> identities = new List <Identity>();

            if (String.IsNullOrEmpty(_context.ResourceKey))
            {
                identities = _entity.GetAll(_context.Config, whereClause, oleDbParameters);
            }
            else
            {
                identities.Add(new Identity(_entity.EntityName, _context.ResourceKey));
            }


            int totalResult = identities.Count;

            #region PAGING & OPENSEARCH

            /* PAGING */
            feed.Links = FeedMetadataHelpers.CreatePageFeedLinks(_context, totalResult, FeedMetadataHelpers.RequestKeywordType.none);

            /* OPENSEARCH */
            PageController pageController = FeedMetadataHelpers.GetPageLinkBuilder(_context, totalResult, FeedMetadataHelpers.RequestKeywordType.none);

            feed.Opensearch_ItemsPerPageElement = pageController.GetOpensearch_ItemsPerPageElement();
            feed.Opensearch_StartIndexElement   = pageController.GetOpensearch_StartIndexElement();
            feed.Opensearch_TotalResultsElement = pageController.GetOpensearch_TotalResultsElement();

            #endregion


            feed.Id = _context.SdataUri.ToString();

            string tmpValue;
            // ?includeUuid
            includeUuid = false;    // default value, but check for settings now
            if (_context.SdataUri.QueryArgs.TryGetValue("includeUuid", out tmpValue))
            {
                includeUuid = System.Xml.XmlConvert.ToBoolean(tmpValue);
            }

            ICorrelatedResSyncInfoStore correlatedResSyncStore = null;
            if (includeUuid)
            {
                // get store to request the correlations
                correlatedResSyncStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_context.SdataContext);
            }

            for (int pageIndex = pageController.StartIndex; pageIndex <= pageController.LastIndex; pageIndex++)
            //for (int index = startIndex; index < startIndex + count; index++)
            {
                int             zeroBasedIndex  = pageIndex - 1;
                Identity        identity        = identities[zeroBasedIndex];
                AccountDocument accountDocument = (AccountDocument)_entity.GetDocument(identity, emptyToken, _context.Config);
                if (accountDocument.LogState == LogState.Deleted)
                {
                    continue;
                }


                SyncFeedEntry entry = new SyncFeedEntry();
                if (accountDocument.addresses.documents.Count == 0)
                {
                    return(null);
                }


                entry.Id = String.Format("{0}{1}('{2}')", _context.DatasetLink, _resourceKind.ToString(), identity.Id);

                entry.Title   = String.Format("{0}: {1}", _resourceKind.ToString(), identity.Id);
                entry.Updated = DateTime.Now;

                if (_context.SdataUri.Precedence == null)
                {
                    List <SyncFeedEntryLink> links;
                    Document document = accountDocument.addresses.documents[0];
                    entry.Payload = GetTransformedPayload(document, out links);
                    string taUuid = GetTradingAccountUuid(accountDocument.Id);
                    if (!String.IsNullOrEmpty(taUuid))
                    {
                        SyncFeedEntryLink tradingAccountLink = SyncFeedEntryLink.CreateRelatedLink(
                            String.Format("{0}{1}('{2}')", _context.DatasetLink, SupportedResourceKinds.tradingAccounts.ToString(), accountDocument.Id),
                            SupportedResourceKinds.tradingAccounts.ToString(),
                            _tradingAccountUuidPayloadPath, taUuid);
                        links.Add(tradingAccountLink);
                    }

                    entry.SyncLinks = links;
                }

                if (includeUuid)
                {
                    CorrelatedResSyncInfo[] infos = correlatedResSyncStore.GetByLocalId(_context.ResourceKind.ToString(), new string[] { identity.Id });
                    entry.Uuid = (infos.Length > 0) ? infos[0].ResSyncInfo.Uuid : Guid.Empty;
                }

                if (entry != null)
                {
                    feed.Entries.Add(entry);
                }
            }

            return(feed);
        }
예제 #12
0
        public void DoWork(IRequest request)
        {
            EntryRequestType            entryRequestType;
            string                      resourceKindName;
            ICorrelatedResSyncInfoStore correlatedResSyncStore;
            bool includeDataPayloads;   //?includePayloads value

            CorrelatedResSyncInfo[] correlatedResSyncInfos;
            int totalResult;

            #region initialization

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

            resourceKindName = _requestContext.ResourceKind.ToString();

            string tmpValue;
            // ?includePayloads
            includeDataPayloads = false;    // default value, but check for settings now
            if (_requestContext.SdataUri.QueryArgs.TryGetValue("includePayload", out tmpValue))
            {
                includeDataPayloads = System.Xml.XmlConvert.ToBoolean(tmpValue);
            }

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

            #endregion

            // receive correlated resource synchronization entries
            if (entryRequestType == EntryRequestType.Multi)
            {
                int pageNumber = FeedMetadataHelpers.GetPageNumber(_requestContext);

                correlatedResSyncInfos = correlatedResSyncStore.GetPaged(resourceKindName, pageNumber, FeedMetadataHelpers.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;
            }

            // Create the feed
            SyncFeed feed = new SyncFeed();

            // initialize the feed
            feed.Id    = FeedMetadataHelpers.BuildBaseUrl(_requestContext, FeedMetadataHelpers.RequestKeywordType.linked);
            feed.Title = string.Format("{0} Linking Feed", resourceKindName);

            #region PAGING & OPENSEARCH

            /* PAGING */
            feed.Links = FeedMetadataHelpers.CreatePageFeedLinks(_requestContext, totalResult, FeedMetadataHelpers.RequestKeywordType.linked);

            /* OPENSEARCH */
            PageController pageLinkBuilder = FeedMetadataHelpers.GetPageLinkBuilder(_requestContext, totalResult, FeedMetadataHelpers.RequestKeywordType.linked);

            feed.Opensearch_ItemsPerPageElement = pageLinkBuilder.GetOpensearch_ItemsPerPageElement();
            feed.Opensearch_StartIndexElement   = pageLinkBuilder.GetOpensearch_StartIndexElement();
            feed.Opensearch_TotalResultsElement = pageLinkBuilder.GetOpensearch_TotalResultsElement();

            #endregion

            feed.FeedType = (entryRequestType == EntryRequestType.Multi) ? FeedType.Linked : FeedType.LinkedSingle;

            IEntityWrapper wrapper = null;
            if (includeDataPayloads)
            {
                wrapper = EntityWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);
            }

            for (int i = 0; i < correlatedResSyncInfos.Length; i++)
            {
                SyncFeedEntry entry = null;

                if (includeDataPayloads)
                {
                    entry = wrapper.GetFeedEntry(correlatedResSyncInfos[i].LocalId);
                }
                else
                {
                    entry = new SyncFeedEntry();
                }

                entry.Id    = FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, correlatedResSyncInfos[i].ResSyncInfo.Uuid);
                entry.Title = FeedMetadataHelpers.BuildLinkedEntryTitle(_requestContext, correlatedResSyncInfos[i].ResSyncInfo.Uuid);

                #region LINKED ELEMENT

                LinkedElement linkedElement = new LinkedElement();
                linkedElement.Resource = FeedMetadataHelpers.BuildEntryResourceUrl(_requestContext, correlatedResSyncInfos[i].LocalId);
                linkedElement.Uuid     = correlatedResSyncInfos[i].ResSyncInfo.Uuid;
                entry.Linked           = linkedElement;

                #endregion

                feed.Entries.Add(entry);
            }

            request.Response.Serializer  = new SyncFeedSerializer();
            request.Response.Feed        = (IFeed)feed;
            request.Response.ContentType = (entryRequestType == EntryRequestType.Multi) ? MediaType.Atom : MediaType.AtomEntry;
        }
예제 #13
0
        public void DoWork(IRequest request)
        {
            if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry)
            {
                throw new RequestException("Atom entry content type expected");
            }

            if (String.IsNullOrEmpty(_requestContext.ResourceKey))
            {
                throw new RequestException("Please use single resource url");
            }
            //SupportedResourceKinds resKind = _requestContext.ResourceKind;
            //switch (resKind)
            //{
            //    case SupportedResourceKinds.tradingAccounts:
            //    case SupportedResourceKinds.contacts:
            //    case SupportedResourceKinds.phoneNumbers:
            //    case SupportedResourceKinds.postalAddresses:
            //        break;
            //    default:
            //        throw new RequestException("Put is not Supported for requested resource");
            //}

            // read entry from stream
            SyncFeedEntry entry  = new SyncFeedEntry();
            XmlReader     reader = XmlReader.Create(request.Stream);

            reader.MoveToContent();

            entry.ReadXml(reader, ResourceKindHelpers.GetPayloadType(_requestContext.ResourceKind));

            IEntityWrapper wrapper = EntityWrapperFactory.Create(_requestContext.ResourceKind, _requestContext);

            Token    emptyToken = new Token();
            Identity identity   = wrapper.GetIdentity(_requestContext.ResourceKey);

            Document originalDocument = wrapper.Entity.GetDocument(identity, emptyToken, _requestContext.Config);

            if (originalDocument.LogState == LogState.Deleted)
            {
                throw new RequestException("Entity does not exists");
            }

            entry.Payload.LocalID = _requestContext.ResourceKey;
            SdataTransactionResult sdTrResult = wrapper.Update(entry.Payload, entry.SyncLinks);

            if (sdTrResult == null)
            {
                SyncFeedEntry responseEntry = wrapper.GetFeedEntry(_requestContext.ResourceKey);

                SyncFeed feed = new SyncFeed();
                feed.FeedType = FeedType.ResourceEntry;
                feed.Entries.Add(responseEntry);
                request.Response.Serializer  = new SyncFeedSerializer();
                request.Response.Feed        = feed;
                request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry;
            }
            else if (sdTrResult.HttpStatus == System.Net.HttpStatusCode.OK)
            {
                SyncFeedEntry responseEntry = wrapper.GetFeedEntry(_requestContext.ResourceKey);

                SyncFeed feed = new SyncFeed();
                feed.FeedType = FeedType.ResourceEntry;
                feed.Entries.Add(responseEntry);
                request.Response.Serializer  = new SyncFeedSerializer();
                request.Response.Feed        = feed;
                request.Response.ContentType = Sage.Common.Syndication.MediaType.AtomEntry;
            }
            else
            {
                throw new RequestException(sdTrResult.HttpMessage);
            }
        }
        public void DoWork(IRequest request)
        {
            // only atom entry supported!!!
            if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry)
            {
                throw new RequestException("Atom entry content type expected");
            }

            // deserialize the request stream to a SyncFeedEntry
            SyncFeedEntry entry  = new SyncFeedEntry();
            XmlReader     reader = XmlReader.Create(request.Stream);

            reader.MoveToContent();
            entry.ReadXml(reader, typeof(SyncDigestPayload));

            if (null == entry.Linked)
            {
                throw new RequestException("Invalid content: element 'linked' missing");
            }

            // Parse the resource url 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.

            string         requestEndpointUrl            = _requestContext.OriginEndPoint;
            RequestContext entryResourceAsRequestContext = new RequestContext(new Sage.Common.Syndication.SDataUri(entry.Linked.Resource));    // 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();
            string localId          = entryResourceAsRequestContext.SdataUri.CollectionPredicate;
            Guid   uuid             = entry.Linked.Uuid;

            // store a new correlation entry to the sync store
            ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);

            ResSyncInfo           newResSyncInfo = new ResSyncInfo(uuid, requestEndpointUrl, 0, string.Empty, DateTime.Now);
            CorrelatedResSyncInfo newInfo        = new CorrelatedResSyncInfo(localId, newResSyncInfo);

            correlatedResSyncInfoStore.Add(resourceKindName, newInfo);

            // Set the response values
            SyncFeed feed = new SyncFeed();

            feed.FeedType = FeedType.LinkedSingle;

            SyncFeedEntry feedEntry = new SyncFeedEntry();

            feedEntry.Title     = FeedMetadataHelpers.BuildLinkedEntryTitle(_requestContext, uuid);
            feedEntry.Id        = FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, uuid);
            feedEntry.Updated   = newInfo.ResSyncInfo.ModifiedStamp;
            feedEntry.Published = newInfo.ResSyncInfo.ModifiedStamp;
            feedEntry.Linked    = entry.Linked;

            feed.Entries.Add(feedEntry);


            request.Response.Serializer  = new SyncFeedSerializer();
            request.Response.Feed        = (IFeed)feed;
            request.Response.ContentType = MediaType.AtomEntry;

            request.Response.StatusCode = System.Net.HttpStatusCode.Created;
            request.Response.Protocol.SendUnknownResponseHeader("location", FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, uuid));
        }
예제 #15
0
        public void DoWork(IRequest request)
        {
            // only atom entry supported!!!
            if (request.ContentType != Sage.Common.Syndication.MediaType.AtomEntry)
            {
                throw new RequestException("Atom entry content type expected");
            }

            // deserialize the request stream to a SyncFeedEntry
            SyncFeedEntry entry  = new SyncFeedEntry();
            XmlReader     reader = XmlReader.Create(request.Stream);

            reader.MoveToContent();
            entry.ReadXml(reader, typeof(SyncDigestPayload));

            if (null == entry.Linked)
            {
                throw new RequestException("Invalid content: element 'linked' missing");
            }

            // We check for equality of the urls of the request url and
            // in the linked element up to the resourceKind.

            string         requestEndpointUrl            = _requestContext.OriginEndPoint;
            RequestContext entryResourceAsRequestContext = new RequestContext(new Sage.Common.Syndication.SDataUri(entry.Linked.Resource));    // 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();

            Guid   currentUuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(_requestContext.ResourceKey);
            Guid   newUuid     = entry.Linked.Uuid;
            string newLocalId  = entryResourceAsRequestContext.SdataUri.CollectionPredicate;

            // update the correlation entry in the sync store.
            // if the uuid should be updated we have to remove the current correlation and then add a new one.
            // otherwise we update the current correlation.
            ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);
            // create the target correlation
            ResSyncInfo           targetResSyncInfo = new ResSyncInfo(newUuid, requestEndpointUrl, 0, string.Empty, DateTime.Now);
            CorrelatedResSyncInfo targetInfo        = new CorrelatedResSyncInfo(newLocalId, targetResSyncInfo);

            if (currentUuid == newUuid)
            {
                correlatedResSyncInfoStore.Update(resourceKindName, targetInfo);
            }
            else
            {
                correlatedResSyncInfoStore.Delete(resourceKindName, currentUuid);
                correlatedResSyncInfoStore.Add(resourceKindName, targetInfo);
            }

            // create response
            SyncFeed feed = new SyncFeed();

            feed.FeedType = FeedType.LinkedSingle;

            // create entry
            SyncFeedEntry responseEntry = new SyncFeedEntry();

            responseEntry.Id    = FeedMetadataHelpers.BuildLinkedEntryUrl(_requestContext, targetInfo.ResSyncInfo.Uuid);
            responseEntry.Title = FeedMetadataHelpers.BuildLinkedEntryTitle(_requestContext, targetInfo.ResSyncInfo.Uuid);

            LinkedElement linkedElement = new LinkedElement();

            linkedElement.Resource = FeedMetadataHelpers.BuildEntryResourceUrl(_requestContext, targetInfo.LocalId);
            linkedElement.Uuid     = targetInfo.ResSyncInfo.Uuid;
            responseEntry.Linked   = linkedElement;

            feed.Entries.Add(responseEntry);

            request.Response.Serializer  = new SyncFeedSerializer();
            request.Response.Feed        = (IFeed)feed;
            request.Response.ContentType = MediaType.AtomEntry;
        }
        private CommodityIdentity[] GetCommodityIds(SyncFeedEntry requestEntry)
        {
            List <CommodityIdentity> identities = new List <CommodityIdentity>();

            // To be able to receive commodity data we need the local commodity ids.
            // These ids can be requested in 2 ways:
            // 1a) Using reference link: If attribute 'href' is a valid url of this adapter and has a resource key we can use the given resourceKey.
            // 1b) Using reference link: Otherwise we use the attribute 'uuid' and use the correlation repository.
            // 2)  Using the value contained in line property 'uuid' and using the correlation repository.
            // If 1) and 2) do not succeed we add an empty object.

            ComputePriceRequestPayload payload = (ComputePriceRequestPayload)requestEntry.Payload;

            int noOflines = payload.ComputePriceRequest.pricingDocumentLines.Length;

            for (int i = 0; i < noOflines; i++)
            {
                string payloadPath = string.Format("computePrice/pricingDocumentLines[{0}]/commodity", i);

                SyncFeedEntryLink feedLink = Helper.FindLinkByPayloadPath(requestEntry.SyncLinks.ToArray(), payloadPath);

                //if (null == feedLink)
                //    throw new RequestException(string.Format("Link for payloadPath '{0}' missing", payloadPath));

                if (null != feedLink)
                {
                    // validate
                    string strRel = SyncFeedEntryLink.GetRelString(Sage.Integration.Northwind.Feeds.RelEnum.related);
                    if (feedLink.LinkRel != strRel)
                    {
                        throw new RequestException(string.Format("Parsing link with payloadPath '{0}' failed: Attribute 'rel' must contain value '{1}'.", payloadPath, strRel));
                    }

                    // TODO: excluded because condition linktype could have valid space character and we cannot check this in a simple way.
                    //string strType = SyncFeedEntryLink.GetTypeString(Sage.Integration.Northwind.Feeds.LinkTypeEnum.entry);
                    //if (feedLink.LinkType != strType)
                    //    throw new RequestException(string.Format("Parsing link with payloadPath '{0}' failed: Invalid media type defined in attribute 'type'. Value '{1}' expected.", payloadPath, strType));

                    string url = feedLink.Href;

                    // 1a) Try to parse href
                    if (url.StartsWith(_requestContext.DatasetLink + SupportedResourceKinds.commodities.ToString()))
                    {
                        RequestContext tmpRequestContext = new RequestContext(new SDataUri(url));
                        if (tmpRequestContext.RequestType == RequestType.Resource)
                        {
                            identities.Add(new CommodityIdentity(tmpRequestContext.ResourceKey));
                            continue;   // continue iteration (parse next line item)
                        }
                    }

                    // 1b) Try to get uuid from link and to get the local id using synch correlation (linking)
                    if (!string.IsNullOrEmpty(feedLink.Uuid))
                    {
                        Guid uuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(feedLink.Uuid);
                        ICorrelatedResSyncInfoStore correlationStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);
                        CorrelatedResSyncInfo[]     correlations     = correlationStore.GetByUuid(SupportedResourceKinds.commodities.ToString(), new Guid[] { uuid });

                        if (correlations.Length == 1)
                        {
                            identities.Add(new CommodityIdentity(correlations[0].LocalId));
                            continue;   // continue iteration (parse next line item)
                        }
                    }
                }
                else
                {
                    // 2) Try to get uuid from property named 'uuid'
                    string strLineUuid = payload.ComputePriceRequest.pricingDocumentLines[i].uuid;
                    if (!string.IsNullOrEmpty(strLineUuid))
                    {
                        Guid uuid = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(strLineUuid);

                        // get the local id using synch correlation (linking)
                        ICorrelatedResSyncInfoStore correlationStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_requestContext.SdataContext);
                        CorrelatedResSyncInfo[]     correlations     = correlationStore.GetByUuid(SupportedResourceKinds.commodities.ToString(), new Guid[] { uuid });

                        if (correlations.Length == 1)
                        {
                            identities.Add(new CommodityIdentity(correlations[0].LocalId));
                            continue;   // continue iteration (parse next line item)
                        }
                    }
                }

                // If 1) and 2) failed add an empty CommodityIdentity
                identities.Add(CommodityIdentity.Empty);
            }

            return(identities.ToArray());
        }
        public void DoWork(IRequest request)
        {
            //// check for resource kind existence and supported types
            //if (_requestContext.ResourceKind == SupportedResourceKinds.None)
            //    throw new RequestException("Invalid request: The service {0} is a resource based service.");

            // if request was done in the context of a resource kind -> check for supported resourceKinds
            if (_requestContext.ResourceKind != SupportedResourceKinds.None)
            {
                if (!(_requestContext.ResourceKind == SupportedResourceKinds.salesOrders ||
                      _requestContext.ResourceKind == SupportedResourceKinds.salesOrderLines))
                {
                    throw new RequestException("Invalid request: The service {0} is only supported by salesOrders and salesOrderLines.");
                }
            }

            // read entry from stream
            SyncFeedEntry entry  = new SyncFeedEntry();
            XmlReader     reader = XmlReader.Create(request.Stream);

            reader.MoveToContent();
            entry.ReadXml(reader, typeof(ComputePriceRequestPayload));

            // underlying resources for price computing
            computePriceRequesttype computePriceRequest;

            CommodityIdentity[] productIds;     // will contain local ids of the commodity referenced by line items.
                                                // Could contain empty items if commodity id could not be found.

            // compute price
            computePriceResponsetype computePriceResponse;

            if (null == entry.Payload)
            {
                throw new RequestException("Invalid Xml input stream. Could not parse the payload.");
            }

            computePriceRequest = ((ComputePriceRequestPayload)entry.Payload).ComputePriceRequest;

            #region Trading Account (discounted)

            // get the undelying trading account
            // is null if request is not in the context of an account.
            // if no account found means that the account exists in CRM only
            // and has not yet been linked with ERP. ERP could treat the account as a
            // prospect account and generate a price for the account, or if this is not
            // possible it could return an error.

            #endregion

            #region PricingDocument (only salesOrder suppported)

            // document associated with this pricing request (e.g. the Sales Order, Quotation, Purchase Order number).
            // could be of any type of enumeration "pricingDocumenttype"
            // if no document exists the request is not in the context of a document like order, quote, etc.

            // TODO: Get the associated document to find out the context of the request.

            // Validate document type
            // here: only salesOrder supported
            // removed to avoid possible errors (OK as this is only an example project)
            //if (computePriceRequest.pricingDocumentType != pricingDocumenttype.salesOrder)
            //    throw new RequestException("Invalid document type in element 'pricingDocumentType' defined. Only salesOrder supported.");

            #endregion

            #region Commodities (for each document lines)

            // Get Commodity local ids used on the associated document lines.
            // (the array returned is always of the same size as the number of document lines in the request payload.
            // If a commodity local id could not be found in feed entry the array item will be null.
            productIds = this.GetCommodityIds(entry);   // (never returns null, but could return an empty array)

            #endregion

            // compute price
            PricingServices pricingServices = new PricingServices(_requestContext.Config);

            if (_requestContext.ResourceKind == SupportedResourceKinds.salesOrders ||
                _requestContext.ResourceKind == SupportedResourceKinds.None)
            {
                computePriceResponse = pricingServices.ComputePrice(computePriceRequest, productIds, false);
            }
            else
            {
                computePriceResponse = pricingServices.ComputePrice(computePriceRequest, productIds, true);
            }


            // create response feed
            this.BuildResponseFeed(ref request, computePriceResponse);
            //this.BuildResponseFeed(ref request, cpr);
        }
        //private NorthwindConfig _config;

        #endregion

        #region IRequestProcess Members

        public void DoWork(IRequest request)
        {
            // If an asyncState object already exists, an exception is thrown as the performer only accepts
            // one call after each other. The Request receiver has to manage a queued execution.

            // Before calling the performers execution implementation method a new AsyncState object is created
            // and set to an initial tracking state.

            lock (_asyncStateObj)
            {
                if (null != _asyncStateObj.Tracking)
                {
                    throw new InvalidOperationException("The performer cannot be executed because it is already running.");
                }

                SyncTracking tracking = new SyncTracking();
                tracking.ElapsedSeconds   = 1;
                tracking.Phase            = TrackingPhase.INIT;
                tracking.PhaseDetail      = "Tracking Id was: " + _requestContext.TrackingId.ToString();
                tracking.PollingMillis    = 100;
                tracking.RemainingSeconds = 100;

                _asyncStateObj.Tracking = tracking;
            }


            // *** Initialization for the async execution ***
            // - Read SyncDigest from request stream.
            // - Read trackingId from request URL

            //// Load input stream (throws RequestException if it fails.)
            //XmlDocument xmlInputDoc;
            //InputStreamHelpers.Get(request, out xmlInputDoc);

            //// load syncDigest info from input stream of the request
            //SyncDigestInfo syncDigestInfo = SyncDigestInfoHelpers.Load(xmlInputDoc);

            SyncFeedEntry entry  = new SyncFeedEntry();
            XmlReader     reader = XmlReader.Create(request.Stream);

            reader.MoveToContent();
            entry.ReadXml(reader, typeof(SyncDigestPayload));
            if (entry.Payload == null)
            {
                throw new RequestException("Invalid Content");
            }
            SyncFeedDigest syncDigestInfo = ((SyncDigestPayload)entry.Payload).Digest;

            // convert tracking ID from request to type Guid
            string strTrackingId = request.Uri.TrackingID;

            if (String.IsNullOrEmpty(strTrackingId))
            {
                throw new RequestException("TrackingId is missing");
            }

            GuidConverter converter = new GuidConverter();

            this.TrackingId = (Guid)converter.ConvertFrom(strTrackingId);



            // *** Do work asynchronously ***
            _asyncPerformer = new InternalAsyncPerformer(this);
            _asyncPerformer.DoWork(_requestContext.Config, syncDigestInfo);


            // *** set the tracking to the request response ***
            this.GetTrackingState(request);
        }
            /// <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 SyncFeed GetFeed(NorthwindConfig config, int startIndex, int count)
            {
                SyncFeed               feed;
                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;

                if (count == 0)
                {
                    count = 10;
                }

                feed = new SyncFeed();
                Token emptyToken = new Token();



                IEntityWrapper wrapper = EntityWrapperFactory.Create(resource, _parentPerformer._requestContext);



                for (int index = startIndex;
                     index < ((startIndex + count > transactinResults.Count) ? transactinResults.Count : startIndex + count);
                     index++)
                {
                    SdataTransactionResult transactionResult = (SdataTransactionResult)transactinResults[index];

                    SyncFeedEntry entry = wrapper.GetFeedEntry(transactionResult);

                    if (entry != null)
                    {
                        feed.Entries.Add(entry);
                    }
                    else
                    {
                        entry                = new SyncFeedEntry();
                        entry.Uuid           = transactionResult.Uuid;
                        entry.HttpStatusCode = transactionResult.HttpStatus;
                        entry.HttpMessage    = transactionResult.HttpMessage;;
                        entry.HttpMethod     = transactionResult.HttpMethod;
                        entry.HttpLocation   = transactionResult.Location;
                        entry.HttpETag       = transactionResult.Etag;
                        feed.Entries.Add(entry);
                    }
                }

                // initialize the feed
                string url = string.Format("{0}/$syncTarget('{1}')", endpoint, trackingId);

                feed.Title = resourceKind;
                feed.Id    = url;

                #region PAGING & OPENSEARCH

                int totalResults = transactinResults.Count;

                PageController pageController = new PageController(startIndex + 1, FeedMetadataHelpers.DEFAULT_ITEMS_PER_PAGE, totalResults, count, url);

                /* PAGING */
                FeedLinkCollection feedLinks = new FeedLinkCollection();
                feedLinks.Add(new FeedLink(pageController.GetLinkSelf(), LinkType.Self, MediaType.Atom, "Current Page"));
                feedLinks.Add(new FeedLink(pageController.GetLinkFirst(), LinkType.First, MediaType.Atom, "First Page"));
                feedLinks.Add(new FeedLink(pageController.GetLinkLast(), LinkType.Last, MediaType.Atom, "Last Page"));

                string linkUrl;
                if (pageController.GetLinkNext(out linkUrl))
                {
                    feedLinks.Add(new FeedLink(linkUrl, LinkType.Next, MediaType.Atom, "Next Page"));
                }
                if (pageController.GetLinkPrevious(out linkUrl))
                {
                    feedLinks.Add(new FeedLink(linkUrl, LinkType.Previous, MediaType.Atom, "Previous Page"));
                }

                feed.Links = feedLinks;


                /* OPENSEARCH */
                feed.Opensearch_ItemsPerPageElement = pageController.GetOpensearch_ItemsPerPageElement();
                feed.Opensearch_StartIndexElement   = pageController.GetOpensearch_StartIndexElement();
                feed.Opensearch_TotalResultsElement = pageController.GetOpensearch_TotalResultsElement();

                #endregion

                //if (startIndex + count < transactinResults.Count)
                //{
                //    FeedLink linkNext = new FeedLink(string.Format("{0}?startIndex={1}&count=10", url, startIndex + count), LinkType.Next);
                //    feed.Links.Add(linkNext);
                //}

                //FeedLink linkFirst = new FeedLink(String.Format("{0}?startIndex=0&count=10", url), LinkType.First);
                //feed.Links.Add(linkFirst);

                //FeedLink linkSelf = new FeedLink(String.Format("{0}?startIndex={1}&count=10", url, startIndex), LinkType.Self);
                //feed.Links.Add(linkSelf);

                return(feed);
            }
            /// <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 SyncFeed GetFeed(NorthwindConfig config, int startIndex, int count)
            {
                SyncFeed               feed;
                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);
                SyncDigestInfo           syncDigestInfo  = syncDigestStore.Get(resourceKind);


                if (count == 0)
                {
                    count = 10;
                }

                feed = new SyncFeed();
                Token emptyToken = new Token();

                feed.Digest         = new SyncFeedDigest();
                feed.Digest.Origin  = _parentPerformer._requestContext.OriginEndPoint;
                feed.Digest.Entries = new List <SyncFeedDigestEntry>();

                if (syncDigestInfo != null)
                {
                    foreach (SyncDigestEntryInfo entryinfo in syncDigestInfo)
                    {
                        SyncFeedDigestEntry entry = new SyncFeedDigestEntry();
                        entry.ConflictPriority = entryinfo.ConflictPriority;
                        entry.Endpoint         = entryinfo.Endpoint;
                        entry.Tick             = entryinfo.Tick;
                        entry.Stamp            = DateTime.Now;
                        feed.Digest.Entries.Add(entry);
                    }
                }



                IEntityWrapper wrapper = EntityWrapperFactory.Create(resource, _parentPerformer._requestContext);


                for (int index = startIndex;
                     index < ((startIndex + count > correlatedResSyncInfos.Count) ? correlatedResSyncInfos.Count : startIndex + count);
                     index++)
                {
                    CorrelatedResSyncInfo resSyncInfo = (CorrelatedResSyncInfo)correlatedResSyncInfos[index];
                    SyncFeedEntry         entry       = wrapper.GetFeedEntry(resSyncInfo);
                    if (entry != null)
                    {
                        feed.Entries.Add(entry);
                    }
                    else
                    {
                        entry            = new SyncFeedEntry();
                        entry.HttpMethod = "DELETE";
                        entry.Uuid       = resSyncInfo.ResSyncInfo.Uuid;
                        feed.Entries.Add(entry);
                    }
                }


                // initialize the feed
                string url = string.Format("{0}/$syncSource('{1}')", endpoint, trackingId);

                feed.Id    = url;
                feed.Title = resourceKind;

                #region PAGING & OPENSEARCH

                int totalResults = correlatedResSyncInfos.Count;

                PageController pageController = new PageController(startIndex + 1, FeedMetadataHelpers.DEFAULT_ITEMS_PER_PAGE, totalResults, count, url);

                /* PAGING */
                FeedLinkCollection feedLinks = new FeedLinkCollection();
                feedLinks.Add(new FeedLink(pageController.GetLinkSelf(), LinkType.Self, MediaType.Atom, "Current Page"));
                feedLinks.Add(new FeedLink(pageController.GetLinkFirst(), LinkType.First, MediaType.Atom, "First Page"));
                feedLinks.Add(new FeedLink(pageController.GetLinkLast(), LinkType.Last, MediaType.Atom, "Last Page"));

                string linkUrl;
                if (pageController.GetLinkNext(out linkUrl))
                {
                    feedLinks.Add(new FeedLink(linkUrl, LinkType.Next, MediaType.Atom, "Next Page"));
                }
                if (pageController.GetLinkPrevious(out linkUrl))
                {
                    feedLinks.Add(new FeedLink(linkUrl, LinkType.Previous, MediaType.Atom, "Previous Page"));
                }

                feed.Links = feedLinks;


                /* OPENSEARCH */
                feed.Opensearch_ItemsPerPageElement = pageController.GetOpensearch_ItemsPerPageElement();
                feed.Opensearch_StartIndexElement   = pageController.GetOpensearch_StartIndexElement();
                feed.Opensearch_TotalResultsElement = pageController.GetOpensearch_TotalResultsElement();

                #endregion



                //feed.Id = url;
                //if (startIndex + count < correlatedResSyncInfos.Count)
                //{
                //    FeedLink linkNext = new FeedLink(string.Format("{0}?startIndex={1}&count=10", url, startIndex + count), LinkType.Next);
                //    feed.Links.Add(linkNext);
                //}

                //FeedLink linkFirst = new FeedLink(String.Format("{0}?startIndex=0&count=10", url), LinkType.First);
                //feed.Links.Add(linkFirst);

                //FeedLink linkSelf = new FeedLink(String.Format("{0}?startIndex={1}&count=10", url, startIndex), LinkType.Self);
                //feed.Links.Add(linkSelf);

                return(feed);
            }
        public override SyncFeedEntry GetFeedEntry(string id)
        {
            SyncFeedEntry result = new SyncFeedEntry();

            result.Payload = PayloadFactory.CreatePayload(_resourceKind);

            Identity        identity;
            AccountDocument accountDocument;
            Account         account = new Account();
            string          accountId;

            if (id.EndsWith(Sage.Integration.Northwind.Application.API.Constants.PhoneIdPostfix))
            {
                accountId = id.Replace(Sage.Integration.Northwind.Application.API.Constants.PhoneIdPostfix, "");
            }
            else if (id.EndsWith(Sage.Integration.Northwind.Application.API.Constants.FaxIdPostfix))
            {
                accountId = id.Replace(Sage.Integration.Northwind.Application.API.Constants.FaxIdPostfix, "");
            }
            else
            {
                return(null);
            }

            identity = new Identity(account.EntityName, accountId);


            accountDocument = (AccountDocument)_entity.GetDocument(identity, _emptyToken, _context.Config);

            if (accountDocument.LogState == LogState.Deleted)
            {
                return(null);
            }
            if (accountDocument.addresses.documents.Count == 0)
            {
                return(null);
            }
            Document document = null;

            foreach (Document phoneDoc in accountDocument.phones.documents)
            {
                if (phoneDoc.Id.Equals(id, StringComparison.InvariantCultureIgnoreCase))
                {
                    document = phoneDoc;
                    break;
                }
            }
            if (document == null)
            {
                return(null);
            }


            List <SyncFeedEntryLink> links;

            result.Payload = GetTransformedPayload(document, out links);

            string taUuid = GetTradingAccountUuid(accountDocument.Id);

            if (!String.IsNullOrEmpty(taUuid))
            {
                SyncFeedEntryLink tradingAccountLink = SyncFeedEntryLink.CreateRelatedLink(
                    String.Format("{0}{1}('{2}')", _context.DatasetLink, SupportedResourceKinds.tradingAccounts.ToString(), accountDocument.Id),
                    SupportedResourceKinds.tradingAccounts.ToString(),
                    _tradingAccountUuidPayloadPath, taUuid);
                links.Add(tradingAccountLink);
            }
            result.SyncLinks = links;
            result.Id        = String.Format("{0}{1}('{2}')", _context.DatasetLink, _resourceKind.ToString(), id);
            result.Title     = String.Format("{0}: {1}", _resourceKind.ToString(), id);
            result.Updated   = DateTime.Now;
            return(result);
        }