public EntityWrapperBase(RequestContext context, SupportedResourceKinds resourceKind)
 {
     _context      = context;
     _resourceKind = resourceKind;
     _emptyToken   = new Token();
     _correlatedResSyncInfoStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_context.SdataContext);
 }
Esempio n. 2
0
 public EntityWrapperBase(RequestContext context, SupportedResourceKinds resourceKind)
 {
     _context = context;
     _resourceKind = resourceKind;
     _emptyToken = new Token();
     _correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_context.SdataContext);
 }
        public TransformationBase(RequestContext context, SupportedResourceKinds resourceKind)
        {
            _context      = context;
            _datasetLink  = _context.DatasetLink;
            _config       = _context.Config;
            _resourceKind = resourceKind;

            _resourceKindString = _resourceKind.ToString();
            _originApplication  = _datasetLink + _resourceKindString;

            _correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_context.SdataContext);
        }
Esempio n. 4
0
        public TransformationBase(RequestContext context, SupportedResourceKinds resourceKind)
        {
            _context = context;
            _datasetLink = _context.DatasetLink;
            _config = _context.Config;
            _resourceKind = resourceKind;

            _resourceKindString = _resourceKind.ToString();
            _originApplication = _datasetLink + _resourceKindString;

            _correlatedResSyncInfoStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_context.SdataContext);
        }
 private void CheckExisting(ICorrelatedResSyncInfoStore correlatedResSyncInfoStore, string localId)
 {
     CorrelatedResSyncInfo[] existingCorrelations = correlatedResSyncInfoStore.GetByLocalId(_requestContext.ResourceKind.ToString(), new string[] { localId });
     if (existingCorrelations.Length > 0)
     {
         StringBuilder b = new StringBuilder(existingCorrelations.Length + " correlations for " + localId + " already exist ( ");
         foreach (CorrelatedResSyncInfo existingCorrelation in existingCorrelations)
         {
             b.Append(existingCorrelation.ResSyncInfo.Uuid);
             b.Append(" ");
         }
         b.Append(")");
         throw new RequestException(b.ToString());
     }
 }
Esempio n. 6
0
        public void DoWork(IRequest request)
        {
            if (String.IsNullOrEmpty(_requestContext.ResourceKey))
            {
                throw new RequestException("Please use a uuid predicate.");
            }
            // TODO: Check resourceKind for value None???

            Guid   uuid         = (Guid)TypeDescriptor.GetConverter(typeof(Guid)).ConvertFrom(_requestContext.ResourceKey);
            string resourceKind = _requestContext.ResourceKind.ToString();

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

            correlatedResSyncInfoStore.Delete(resourceKind, uuid);
        }
        public void GetTrackingState(IRequest request)
        {
            lock (_asyncStateObj)
            {
                if (null == _asyncStateObj.Tracking)
                {
                    throw new InvalidOperationException("Performer has not been started.");
                }


                if (_asyncStateObj.Tracking.Phase == TrackingPhase.FINISH)
                {
                    request.Response.ContentType = MediaType.Atom;
                    int          startindex   = Convert.ToInt32(request.Uri.StartIndex);
                    int          count        = Convert.ToInt32(request.Uri.Count);
                    SdataContext sdataContext = _requestContext.SdataContext;
                    ICorrelatedResSyncInfoStore correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(sdataContext);

                    request.Response.Serializer = new SyncFeedSerializer();
                    SyncFeed syncFeed = _asyncPerformer.GetFeed(_requestContext.Config, startindex, count);
                    syncFeed.FeedType     = FeedType.SyncSource;
                    request.Response.Feed = syncFeed;
                }
                else if (_asyncStateObj.Tracking.Phase == TrackingPhase.ERROR)
                {
                    request.Response.Xml         = XmlSerializationHelpers.SerializeObjectToXml(_asyncStateObj.Tracking);
                    request.Response.ContentType = MediaType.Xml;
                    request.Response.StatusCode  = HttpStatusCode.InternalServerError;
                    request.Response.Serializer  = new XmlSerializer();
                    request.Response.Protocol.SendUnknownResponseHeader("location", String.Format("{0}{1}/$syncSource('{2}')", _requestContext.DatasetLink, _requestContext.ResourceKind.ToString(), _requestContext.TrackingId));
                }
                else
                {
                    request.Response.Xml         = XmlSerializationHelpers.SerializeObjectToXml(_asyncStateObj.Tracking);
                    request.Response.ContentType = MediaType.Xml;
                    request.Response.StatusCode  = HttpStatusCode.Accepted;
                    request.Response.Serializer  = new XmlSerializer();
                    request.Response.Protocol.SendUnknownResponseHeader("location", String.Format("{0}{1}/$syncSource('{2}')", _requestContext.DatasetLink, _requestContext.ResourceKind.ToString(), _requestContext.TrackingId));
                }
            }
        }
Esempio n. 8
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);
        }
Esempio n. 9
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;
        }
Esempio n. 10
0
 private void CheckExisting(ICorrelatedResSyncInfoStore correlatedResSyncInfoStore, string localId)
 {
     CorrelatedResSyncInfo[] existingCorrelations = correlatedResSyncInfoStore.GetByLocalId(_requestContext.ResourceKind.ToString(), new string[] { localId });
     if (existingCorrelations.Length > 0)
     {
         StringBuilder b = new StringBuilder(existingCorrelations.Length + " correlations for " + localId + " already exist ( ");
         foreach (CorrelatedResSyncInfo existingCorrelation in existingCorrelations)
         {
             b.Append(existingCorrelation.ResSyncInfo.Uuid);
             b.Append(" ");
         }
         b.Append(")");
         throw new RequestException(b.ToString());
     }
 }
        private CommodityIdentity[] GetCommodityIds(ComputePriceRequestFeedEntry payloadContainer)
        {
            List <CommodityIdentity> identities = new List <CommodityIdentity>();

            // The commodities are situated under the pricing document lines.
            // The commodities are linked resources. That means that the schema provides a sme:relationship="reference"
            // on the commodity schema node.
            // Example: (<xs:element sme:label="Commodity" name="commodity" type="commodity--type" sme:relationship="reference" minOccurs="0" maxOccurs="1" sme:mandatory="true" >)
            //
            // The commodity payload is an empty payload providing all or some sdata attributes as follows:
            // url, key, uuid, lookup, descriptor.
            //
            // To be able to receive commodity data we need the local commodity ids.
            // So we iterate through all line items of the given entry and read the commodity payload attributes.
            // Dependent on the existence of the attributes an id can be requested in 3 ways:
            // 1. Using attribute key (MS: SHOULD or MUST exist??? cannot find compliance info)
            // 2. Parsing attribute url (MS: SHOULD or MUST exist??? cannot find compliance info)
            // 3. Using the uuid attribute and using the correlation repository.

            int noOfLines;                      // The number of line items
            CommodityFeedEntry tmpCommodityPayload;

            noOfLines = payloadContainer.pricingDocumentLines.Entries.Count;

            for (int i = 0; i < noOfLines; i++)
            {
                tmpCommodityPayload = payloadContainer.pricingDocumentLines.Entries[i].commodity;

                if (null == tmpCommodityPayload)
                {
                    throw new RequestException(string.Format("Failed to parse feed. Commodity payload missing in pricing document lines[{0}].", i));
                }

                if (!string.IsNullOrEmpty(tmpCommodityPayload.Key))
                {
                    identities.Add(new CommodityIdentity(tmpCommodityPayload.Key));
                    continue;
                }

                if (!string.IsNullOrEmpty(tmpCommodityPayload.Uri))
                {
                    if (tmpCommodityPayload.Uri.StartsWith(_context.DatasetLink + SupportedResourceKinds.commodities.ToString()))
                    {
                        RequestContext tmpRequestContext = new RequestContext(new SDataUri(tmpCommodityPayload.Uri));
                        if (tmpRequestContext.RequestType == RequestType.Resource)
                        {
                            identities.Add(new CommodityIdentity(tmpRequestContext.ResourceKey));
                            continue;   // continue iteration (parse next line item)
                        }
                    }
                }

                if (tmpCommodityPayload.UUID != null && Guid.Empty != tmpCommodityPayload.UUID)
                {
                    Guid uuid = tmpCommodityPayload.UUID;

                    // get the local id using synch correlation (linking)
                    ICorrelatedResSyncInfoStore correlationStore = NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(_context.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)
                    }
                }

                // Add an empty CommodityIdentity if everything failed.
                identities.Add(CommodityIdentity.Empty);
            }
            return(identities.ToArray());
        }
        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 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;
        }
        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)
        {
            // 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));
        }