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; }
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; }
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); } }
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); }
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); }
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); }
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; } }
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); }
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; }
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)); }
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); }