protected override void OnStateChanged(IChangeEvent @event) { switch (@event) { case Events.Appointment.Created _: break; case Events.Appointment.DetailsChanged changed: DoctorId = changed.DoctorId; StartUtc = changed.StartUtc; EndUtc = changed.EndUtc; Logger.LogDebug("Appointment {Id} changed details for {Doctor}", Id, DoctorId); break; case Events.Appointment.AppointmentStarted _: State = AppointmentState.Started; Logger.LogDebug("Appointment {Id} was started", Id); break; case Events.Appointment.AppointmentEnded _: State = AppointmentState.Ended; Logger.LogDebug("Appointment {Id} was ended", Id); break; default: throw new InvalidOperationException($"Unknown event {@event.GetType()}"); } }
protected void OnValueChanged(IChangeEvent evt, object newValue) { if (m_Model is IPortModel portModel) { m_OwnerElement.CommandDispatcher.Dispatch(new UpdatePortConstantCommand(portModel, newValue)); } }
/// <summary> /// Initializes a new instance of the <see cref="CmisSync.Lib.Events.RemoteEvent"/> class. /// </summary> /// <param name="change">Change event.</param> public RemoteEvent(IChangeEvent change) { if (change == null) { throw new ArgumentNullException("change"); } this.change = change; }
public bool Project(IChangeEvent originalEvent) { switch (originalEvent) { case Events.Payment.Created e: this.paymentStorage.Create(e.EntityId.ToIdentifier()); break; case Events.Payment.AppointmentPaymentInvoiced e: this.paymentStorage.Update(e.EntityId, dto => { dto.PaymentId = e.EntityId; dto.AppointmentId = e.AppointmentId; dto.Amount = e.Amount; dto.AmountCurrency = e.Currency; }); break; default: this.logger.LogDebug($"Unknown entity type '{originalEvent.GetType().Name}'"); return(false); } return(true); }
private void RaiseCreateEvent(IChangeEvent @event) { if (this.isInstantiating) { ((IPublishingEntity)this).RaiseEvent(@event); } }
protected override void OnStateChanged(IChangeEvent @event) { switch (@event) { case Events.Person.Created _: break; case Events.Person.NameChanged changed: Name = new PersonName(changed.FirstName, changed.LastName); DisplayName = new PersonDisplayName(changed.FirstName); Logger.LogDebug("Person {Id} changed name to {FirstName}, {LastName}", Id, changed.FirstName, changed.LastName); break; case Events.Person.DisplayNameChanged changed: DisplayName = new PersonDisplayName(changed.DisplayName); Logger.LogDebug("Person {Id} changed display name to {DisplayName}", Id, changed.DisplayName); break; case Events.Person.EmailChanged changed: Email = new Email(changed.EmailAddress); Logger.LogDebug("Person {Id} changed email to {EmailAddress}", Id, changed.EmailAddress); break; case Events.Person.PhoneNumberChanged changed: Phone = new PhoneNumber(changed.PhoneNumber); Logger.LogDebug("Person {Id} changed phone number to {PhoneNumber}", Id, changed.PhoneNumber); break; default: throw new InvalidOperationException($"Unknown event {@event.GetType()}"); } }
public bool Project(IChangeEvent originalEvent) { switch (originalEvent) { case Events.Person.Created e: this.personStorage.Create(e.EntityId.ToIdentifier()); break; case Events.Person.EmailChanged e: this.personStorage.Update(e.EntityId, dto => { dto.Email = e.EmailAddress; }); break; case Events.Person.PhoneNumberChanged e: this.personStorage.Update(e.EntityId, dto => { dto.Phone = e.PhoneNumber; }); break; case Events.Person.NameChanged e: this.personStorage.Update(e.EntityId, dto => { dto.FirstName = e.FirstName; dto.LastName = e.LastName; }); break; case Events.Person.DisplayNameChanged e: this.personStorage.Update(e.EntityId, dto => { dto.DisplayName = e.DisplayName; }); break; default: this.logger.LogDebug($"Unknown entity type '{originalEvent.GetType().Name}'"); return(false); } return(true); }
private void OnTestOnOnCallback(IChangeEvent evt) { foreach (var o in targets) { var casted = (ScriptableValueBase)o; casted.ForceNotifyValueChanged(); } }
/// <summary> /// Initializes a new instance of the <see cref="CmisSync.Lib.Events.RemoteEvent"/> class. /// </summary> /// <param name="change">Change event.</param> public RemoteEvent(IChangeEvent change) { if (change == null) { throw new ArgumentNullException("The given change event must not be null"); } this.change = change; }
private static void ProjectEvent(IReadModelProjection projection, IChangeEvent @event, EventStreamStateChangeEvent changeEvent) { if (!projection.Project(@event)) { throw new InvalidOperationException( Resources.ReadModelProjector_ProjectionError.Fmt(projection.GetType().Name, changeEvent.Id, changeEvent.Metadata.Fqn)); } }
public static string ToData(IChangeEvent @event) { @event.GuardAgainstNull(nameof(@event)); using (var scope = JsConfig.BeginScope()) { scope.ExcludeTypeInfo = true; return(@event.ToJson()); } }
public bool Project(IChangeEvent originalEvent) { switch (originalEvent) { case Events.Car.Created e: this.carStorage.Create(e.EntityId.ToIdentifier()); break; case Events.Car.ManufacturerChanged e: this.carStorage.Update(e.EntityId, dto => { dto.ManufactureYear = e.Year; dto.ManufactureMake = e.Make; dto.ManufactureModel = e.Model; }); break; case Events.Car.OwnershipChanged e: this.carStorage.Update(e.EntityId, dto => { dto.VehicleOwnerId = e.Owner; dto.ManagerIds = new List <string> { e.Owner }; }); break; case Events.Car.RegistrationChanged e: this.carStorage.Update(e.EntityId, dto => { dto.LicenseJurisdiction = e.Jurisdiction; dto.LicenseNumber = e.Number; }); break; case Events.Car.UnavailabilitySlotAdded e: this.unavailabilityStorage.Create(e.EntityId, dto => { dto.CarId = e.CarId; dto.From = e.From; dto.To = e.To; dto.CausedBy = e.CausedBy; dto.CausedByReference = e.CausedByReference; }); break; default: this.recorder.TraceDebug($"Unknown entity type '{originalEvent.GetType().Name}'"); return(false); } return(true); }
protected void OnValueChanged(IChangeEvent evt, object arg3) { if (m_Model is IConstantNodeModel constantNodeModel) { if (evt != null) // Enum editor sends null { var p = evt.GetType().GetProperty("newValue"); var newValue = p?.GetValue(evt); m_OwnerElement.CommandDispatcher.Dispatch(new UpdateConstantValueCommand(constantNodeModel.Value, newValue, constantNodeModel)); } } }
void IPublishingEntity.RaiseEvent(IChangeEvent @event) { OnStateChanged(@event); var isValid = EnsureValidState(); if (!isValid) { throw new RuleViolationException($"The entity with {Id} is in an invalid state."); } LastModifiedAtUtc = DateTime.UtcNow; this.events.Add(@event); }
public void SetEvent(string streamName, string entityType, long version, IChangeEvent @event) { streamName.GuardAgainstNullOrEmpty(nameof(streamName)); entityType.GuardAgainstNullOrEmpty(nameof(entityType)); @event.GuardAgainstNull(nameof(@event)); StreamName = streamName; Version = version; EntityType = entityType; EventType = @event.GetType().Name; Data = ToData(@event); Metadata = new EventMetadata(@event.GetType().AssemblyQualifiedName); }
public bool Notify(IChangeEvent originalEvent) { switch (originalEvent) { case AppointmentsDomain.Events.Appointment.AppointmentEnded e: this.paymentsApplication.CreateInvoice(new AnonymousCaller(), e.EntityId, e.CostAmount, e.CostCurrency); return(true); default: return(false); } }
public bool Notify(IChangeEvent originalEvent) { switch (originalEvent) { case Events.Person.EmailChanged e: this.carsApplication.UpdateManagerEmail(new AnonymousCaller(), e.EntityId, e.EmailAddress); return(true); default: return(false); } }
/// <summary> /// Apply a remote change for Deleted. /// </summary> private bool ApplyRemoteChangeDelete(IChangeEvent change) { try { ICmisObject remoteObject = session.GetObject(change.ObjectId); if (null != remoteObject) { // should be moveObject Logger.Info("Ignore moveObject for id " + change.ObjectId); return(true); } } catch (CmisObjectNotFoundException) { } catch (Exception e) { Logger.Warn("Exception when GetObject for " + change.ObjectId + " : ", e); } string savedDocumentPath = database.GetRemoteFilePath(change.ObjectId); // FIXME use SyncItem to differentiate between local path and remote path if (null != savedDocumentPath) { Logger.Info("Remove local document: " + savedDocumentPath); if (File.Exists(savedDocumentPath)) { File.Delete(savedDocumentPath); } database.RemoveFile(SyncItemFactory.CreateFromRemotePath(savedDocumentPath, repoinfo)); Logger.Info("Removed local document: " + savedDocumentPath); return(true); } string savedFolderPath = database.GetFolderPath(change.ObjectId); if (null != savedFolderPath) { Logger.Info("Remove local folder: " + savedFolderPath); if (Directory.Exists(savedFolderPath)) { Directory.Delete(savedFolderPath, true); database.RemoveFolder(SyncItemFactory.CreateFromRemotePath(savedFolderPath, repoinfo)); } Logger.Info("Removed local folder: " + savedFolderPath); return(true); } return(true); }
void IPublishingEntity.RaiseEvent(IChangeEvent @event, bool validate) { OnEventRaised(@event); if (validate) { var isValid = EnsureValidState(); if (!isValid) { throw new RuleViolationException($"The entity with {Id} is in an invalid state."); } } this.aggregateEntityEventHandler?.Invoke(@event); LastModifiedAtUtc = DateTime.UtcNow; }
protected override void OnEventRaised(IChangeEvent @event) { switch (@event) { case Events.Clinic.DoctorUnavailabilitySlotAdded added: ClinicId = added.ClinicId.ToIdentifier(); Slot = new TimeSlot(added.From, added.To); CausedBy = added.CausedBy; CausedByReference = added.CausedByReference; break; default: throw new InvalidOperationException($"Unknown event {@event.GetType()}"); } }
protected override void OnStateChanged(IChangeEvent @event) { switch (@event) { case Events.Clinic.Created _: break; case Events.Clinic.LocationChanged changed: Location = new Location(changed.Country, changed.City, changed.Street); Logger.LogDebug("Clinic {Id} changed location to {Country}, {City}, {Street}", Id, changed.Country, changed.City, changed.Street); break; case Events.Clinic.OwnershipChanged changed: Owner = new ClinicOwner(changed.Owner); Managers.Add(changed.Owner.ToIdentifier()); Logger.LogDebug("Clinic {Id} changed ownership to {Owner}", Id, Owner); break; case Events.Clinic.RegistrationChanged changed: License = new ClinicLicense(changed.Jurisdiction, changed.Number); Logger.LogDebug("Clinic {Id} registration changed to {Jurisdiction}, {CertificateNumber}", Id, changed.Jurisdiction, changed.Number); break; case Events.Clinic.DoctorUnavailabilitySlotAdded added: var unavailability = new UnavailabilityEntity(Logger, IdFactory); added.EntityId = unavailability.Id; unavailability.SetAggregateEventHandler(RaiseChangeEvent); RaiseToEntity(unavailability, @event); Unavailabilities.Add(unavailability); Logger.LogDebug("Doctor {Id} had been made unavailable from {From} until {To}", Id, added.From, added.To); break; case Events.Clinic.DoctorRegisteredToClinic added: Doctors.Add(added.DoctorId.ToIdentifier()); Logger.LogDebug("Doctor {Id} had been registered to clinic {Clinic}", added.DoctorId, Id); break; default: throw new InvalidOperationException($"Unknown event {@event.GetType()}"); } }
protected override void OnStateChanged(IChangeEvent @event) { switch (@event) { case Events.Payment.Created _: break; case Events.Payment.AppointmentPaymentInvoiced added: AppointmentInvoice = new AppointmentPayment(added.AppointmentId.ToIdentifier(), added.Amount, added.Currency); Logger.LogDebug("Payment {Id} added invoice for appointment {Appointment}", Id, added.AppointmentId); break; default: throw new InvalidOperationException($"Unknown event {@event.GetType()}"); } }
private static void RelayEvent(IDomainEventPublisherSubscriberPair pair, IChangeEvent @event, EventStreamStateChangeEvent changeEvent) { var eventToPublish = pair.Publisher.Publish(@event); if (eventToPublish == null) { throw new InvalidOperationException(Resources.DomainEventNotificationProducer_PublisherError.Format( pair.Publisher.GetType().Name, changeEvent.Id, changeEvent.Metadata.Fqn)); } if (!pair.Subscriber.Notify(eventToPublish)) { throw new InvalidOperationException(Resources.DomainEventNotificationProducer_SubscriberError.Format( pair.Subscriber.GetType().Name, changeEvent.Id, changeEvent.Metadata.Fqn)); } }
protected override void OnStateChanged(IChangeEvent @event) { switch (@event) { case Events.Car.Created _: break; case Events.Car.ManufacturerChanged changed: Manufacturer = new Manufacturer(changed.Year, changed.Make, changed.Model); Recorder.TraceDebug("Car {Id} changed manufacturer to {Year}, {Make}, {Model}", Id, changed.Year, changed.Make, changed.Model); break; case Events.Car.OwnershipChanged changed: Owner = new VehicleOwner(changed.Owner); Managers = new VehicleManagers(); Managers.Add(changed.Owner.ToIdentifier()); Recorder.TraceDebug("Car {Id} changed ownership to {Owner}", Id, Owner); break; case Events.Car.RegistrationChanged changed: Plate = new LicensePlate(changed.Jurisdiction, changed.Number); Recorder.TraceDebug("Car {Id} registration changed to {Jurisdiction}, {Number}", Id, changed.Jurisdiction, changed.Number); break; case Events.Car.UnavailabilitySlotAdded added: var unavailability = new UnavailabilityEntity(Recorder, IdFactory); added.EntityId = unavailability.Id; unavailability.SetAggregateEventHandler(RaiseChangeEvent); RaiseToEntity(unavailability, @event); Unavailabilities.Add(unavailability); Recorder.TraceDebug("Car {Id} had been made unavailable from {From} until {To}", Id, added.From, added.To); break; default: throw new InvalidOperationException($"Unknown event {@event.GetType()}"); } }
/// <summary> /// Apply a remote change for Deleted. /// </summary> private bool ApplyRemoteChangeDelete(IChangeEvent change) { try { ICmisObject remoteObject = session.GetObject(change.ObjectId); if (null != remoteObject) { // should be moveObject Logger.Info("Ignore moveObject for id " + change.ObjectId); return true; } } catch (CmisObjectNotFoundException) { } catch (Exception e) { Logger.Warn("Exception when GetObject for " + change.ObjectId + " : ", e); } string savedDocumentPath = database.GetFilePath(change.ObjectId); if (null != savedDocumentPath) { Logger.Info("Remove local document: " + savedDocumentPath); if(File.Exists(savedDocumentPath)) File.Delete(savedDocumentPath); database.RemoveFile(savedDocumentPath); Logger.Info("Removed local document: " + savedDocumentPath); return true; } string savedFolderPath = database.GetFolderPath(change.ObjectId); if (null != savedFolderPath) { Logger.Info("Remove local folder: " + savedFolderPath); if(Directory.Exists(savedFolderPath)) { Directory.Delete(savedFolderPath, true); database.RemoveFolder(savedFolderPath); } Logger.Info("Removed local folder: " + savedFolderPath); return true; } return true; }
/// <summary> /// Apply a remote change for Created or Updated. /// </summary> private bool ApplyRemoteChangeUpdate(IChangeEvent change) { ICmisObject cmisObject = null; IFolder remoteFolder = null; IDocument remoteDocument = null; string remotePath = null; ICmisObject remoteObject = null; IFolder remoteParent = null; try { cmisObject = session.GetObject(change.ObjectId); } catch (CmisObjectNotFoundException) { Logger.Info("Ignore the missed object for " + change.ObjectId); return(true); } catch (Exception e) { Logger.Warn("Exception when GetObject for " + change.ObjectId + " :", e); return(false); } remoteDocument = cmisObject as IDocument; remoteFolder = cmisObject as IFolder; if (remoteDocument == null && remoteFolder == null) { Logger.Info("Change in no sync object: " + change.ObjectId); return(true); } if (remoteDocument != null) { if (!Utils.IsFileWorthSyncing(remoteDocument.Name, repoinfo)) { Logger.Info("Change in remote unworth syncing file: " + remoteDocument.Paths); return(true); } if (remoteDocument.Paths.Count == 0) { Logger.Info("Ignore the unfiled object: " + remoteDocument.Name); return(true); } // TODO: Support Multiple Paths remotePath = remoteDocument.Paths[0]; remoteParent = remoteDocument.Parents[0]; } if (remoteFolder != null) { remotePath = remoteFolder.Path; remoteParent = remoteFolder.FolderParent; foreach (string name in remotePath.Split('/')) { if (!String.IsNullOrEmpty(name) && Utils.IsInvalidFolderName(name)) { Logger.Info(String.Format("Change in illegal syncing path name {0}: {1}", name, remotePath)); return(true); } } } if (!remotePath.StartsWith(this.remoteFolderPath)) { Logger.Info("Change in unrelated path: " + remotePath); return(true); // The change is not under the folder we care about. } if (this.repoinfo.isPathIgnored(remotePath)) { Logger.Info("Change in ignored path: " + remotePath); return(true); } string relativePath = remotePath.Substring(remoteFolderPath.Length); if (relativePath.Length <= 0) { Logger.Info("Ignore change in root path: " + remotePath); return(true); } if (relativePath[0] == '/') { relativePath = relativePath.Substring(1); } try { remoteObject = session.GetObjectByPath(remotePath); } catch (CmisObjectNotFoundException) { Logger.Info(String.Format("Ignore remote path {0} deleted from id {1}", remotePath, cmisObject.Id)); return(true); } catch (Exception e) { Logger.Warn("Exception when GetObject for " + remotePath + " : ", e); return(false); } if (remoteObject.Id != cmisObject.Id) { Logger.Info(String.Format("Ignore remote path {0} changed from id {1} to id {2}", remotePath, cmisObject.Id, remoteObject.Id)); return(true); } string localPath = Path.Combine(repoinfo.TargetDirectory, relativePath).Replace('/', Path.DirectorySeparatorChar); if (!DownloadFolder(remoteParent, Path.GetDirectoryName(localPath))) { Logger.Warn("Failed to download the parent folder for " + localPath); return(false); } if (null != remoteDocument) { Logger.Info(String.Format("New remote file ({0}) found.", remotePath)); // check moveObject string savedDocumentPath = database.GetRemoteFilePath(change.ObjectId); if ((null != savedDocumentPath) && (savedDocumentPath != localPath)) { if (File.Exists(localPath)) { File.Delete(savedDocumentPath); database.RemoveFile(SyncItemFactory.CreateFromRemotePath(savedDocumentPath, repoinfo)); } else { if (File.Exists(savedDocumentPath)) { if (!Directory.Exists(Path.GetDirectoryName(localPath))) { Logger.Warn("Creating local directory: " + localPath); Directory.CreateDirectory(Path.GetDirectoryName(localPath)); } File.Move(savedDocumentPath, localPath); } database.MoveFile(SyncItemFactory.CreateFromRemotePath(savedDocumentPath, repoinfo), SyncItemFactory.CreateFromLocalPath(savedDocumentPath, repoinfo)); } } return(SyncDownloadFile(remoteDocument, Path.GetDirectoryName(localPath))); } if (null != remoteFolder) { Logger.Info(String.Format("New remote folder ({0}) found.", remotePath)); // check moveObject string savedFolderPath = database.GetFolderPath(change.ObjectId); if ((null != savedFolderPath) && (savedFolderPath != localPath)) { // TODO MoveFolderLocally(savedFolderPath, localPath); CrawlSync(remoteFolder, localPath); } else { SyncDownloadFolder(remoteFolder, Path.GetDirectoryName(localPath)); CrawlSync(remoteFolder, localPath); } } return(true); }
protected override void OnStateChanged(IChangeEvent @event) { //Not used in testing }
void IPublishedEntityEventHandler.HandleEvent(IChangeEvent @event) { OnStateChanged(@event); }
protected static void RaiseToEntity(IPublishedEntityEventHandler entity, IChangeEvent @event) { entity?.HandleEvent(@event); }
protected void RaiseChangeEvent(IChangeEvent @event) { ((IPublishingEntity)this).RaiseEvent(@event); }
protected abstract void OnStateChanged(IChangeEvent @event);
/// <summary> /// Apply a remote change for Created or Updated. /// </summary> private bool ApplyRemoteChangeUpdate(IChangeEvent change) { ICmisObject cmisObject = null; IFolder remoteFolder = null; IDocument remoteDocument = null; string remotePath = null; ICmisObject remoteObject = null; IFolder remoteParent = null; try { cmisObject = session.GetObject(change.ObjectId); } catch(CmisObjectNotFoundException) { Logger.Info("Ignore the missed object for " + change.ObjectId); return true; } catch (Exception e) { Logger.Warn("Exception when GetObject for " + change.ObjectId + " :", e); return false; } remoteDocument = cmisObject as IDocument; remoteFolder = cmisObject as IFolder; if (remoteDocument == null && remoteFolder == null) { Logger.Info("Change in no sync object: " + change.ObjectId); return true; } if (remoteDocument != null) { if (!Utils.IsFileWorthSyncing(remoteDocument.Name, repoinfo)) { Logger.Info("Change in remote unworth syncing file: " + remoteDocument.Paths); return true; } if (remoteDocument.Paths.Count == 0) { Logger.Info("Ignore the unfiled object: " + remoteDocument.Name); return true; } // TODO: Support Multiple Paths remotePath = remoteDocument.Paths[0]; remoteParent = remoteDocument.Parents[0]; } if (remoteFolder != null) { remotePath = remoteFolder.Path; remoteParent = remoteFolder.FolderParent; foreach (string name in remotePath.Split('/')) { if (!String.IsNullOrEmpty(name) && Utils.IsInvalidFolderName(name)) { Logger.Info(String.Format("Change in illegal syncing path name {0}: {1}", name, remotePath)); return true; } } } if (!remotePath.StartsWith(this.remoteFolderPath)) { Logger.Info("Change in unrelated path: " + remotePath); return true; // The change is not under the folder we care about. } if (this.repoinfo.isPathIgnored(remotePath)) { Logger.Info("Change in ignored path: " + remotePath); return true; } string relativePath = remotePath.Substring(remoteFolderPath.Length); if (relativePath.Length <= 0) { Logger.Info("Ignore change in root path: " + remotePath); return true; } if (relativePath[0] == '/') { relativePath = relativePath.Substring(1); } try { remoteObject = session.GetObjectByPath(remotePath); } catch(CmisObjectNotFoundException) { Logger.Info(String.Format("Ignore remote path {0} deleted from id {1}", remotePath, cmisObject.Id)); return true; } catch (Exception e) { Logger.Warn("Exception when GetObject for " + remotePath + " : ", e); return false; } if (remoteObject.Id != cmisObject.Id) { Logger.Info(String.Format("Ignore remote path {0} changed from id {1} to id {2}", remotePath, cmisObject.Id, remoteObject.Id)); return true; } string localPath = Path.Combine(repoinfo.TargetDirectory, relativePath).Replace('/', Path.DirectorySeparatorChar); if (!DownloadFolder(remoteParent, Path.GetDirectoryName(localPath))) { Logger.Warn("Failed to download the parent folder for " + localPath); return false; } if (null != remoteDocument) { Logger.Info(String.Format("New remote file ({0}) found.", remotePath)); // check moveObject string savedDocumentPath = database.GetFilePath(change.ObjectId); if ((null != savedDocumentPath) && (savedDocumentPath != localPath)) { if (File.Exists(localPath)) { File.Delete(savedDocumentPath); database.RemoveFile(savedDocumentPath); } else { if (File.Exists(savedDocumentPath)) { if (!Directory.Exists(Path.GetDirectoryName(localPath))) { Logger.Warn("Creating local directory: "+ localPath); Directory.CreateDirectory(Path.GetDirectoryName(localPath)); } File.Move(savedDocumentPath, localPath); } database.MoveFile(savedDocumentPath, localPath); } } return SyncDownloadFile(remoteDocument, Path.GetDirectoryName(localPath)); } if (null != remoteFolder) { Logger.Info(String.Format("New remote folder ({0}) found.", remotePath)); // check moveObject string savedFolderPath = database.GetFolderPath(change.ObjectId); if ((null != savedFolderPath) && (savedFolderPath != localPath)) { // TODO MoveFolderLocally(savedFolderPath, localPath); CrawlSync(remoteFolder, localPath); } else { SyncDownloadFolder(remoteFolder, Path.GetDirectoryName(localPath)); CrawlSync(remoteFolder,localPath); } } return true; }
/// <summary> /// Check whether a change is relevant for the current synchronized folder. /// </summary> private bool ChangeIsApplicable(IChangeEvent change) { ICmisObject cmisObject = null; IFolder remoteFolder = null; IDocument remoteDocument = null; IList<string> remotePaths = null; var changeIdForDebug = change.Properties.ContainsKey("cmis:name") ? change.Properties["cmis:name"][0] : change.Properties["cmis:objectId"][0]; // TODO is it different from change.ObjectId ? // Get the remote changed object. try { cmisObject = session.GetObject(change.ObjectId); } catch (CmisObjectNotFoundException) { Logger.Info("Changed object has already been deleted on the server. Syncing just in case: " + changeIdForDebug); // Unfortunately, in this case we can not know whether the object was relevant or not. return true; } catch (CmisRuntimeException e) { if (e.Message.Equals("Unauthorized")) { Logger.Info("We can not read the object id, so it is not an object we can sync anyway: " + changeIdForDebug); return false; } else { Logger.Info("A CMIS exception occured when querying the change. Syncing just in case: " + changeIdForDebug + " :", e); return true; } } catch (Exception e) { Logger.Warn("An exception occurred, syncing just in case: " + changeIdForDebug + " :", e); return true; } // Check whether change is about a document or folder. remoteDocument = cmisObject as IDocument; remoteFolder = cmisObject as IFolder; if (remoteDocument == null && remoteFolder == null) { Logger.Info("Ignore change as it is not about a document nor folder: " + changeIdForDebug); return false; } // Check whether it is a document worth syncing. if (remoteDocument != null) { if (!Utils.IsFileWorthSyncing(remoteDocument.Name, repoInfo)) { Logger.Info("Ignore change as it is about a document unworth syncing: " + changeIdForDebug); return false; } if (remoteDocument.Paths.Count == 0) { Logger.Info("Ignore the unfiled object: " + changeIdForDebug); return false; } // We will check the remote document's path(s) at the end of this method. remotePaths = remoteDocument.Paths; } // Check whether it is a folder worth syncing. if (remoteFolder != null) { remotePaths = new List<string>(); remotePaths.Add(remoteFolder.Path); } // Check the object's path(s) foreach (string remotePath in remotePaths) { if (PathIsApplicable(remotePath)) { Logger.Debug("Change is applicable. Sync:" + changeIdForDebug); return true; } } // No path was relevant, so ignore the change. return false; }
/// <summary> /// Apply a remote change for Created or Updated. /// <returns>Whether the change was applied successfully</returns> /// </summary> private bool ChangeIsApplicable(IChangeEvent change) { ICmisObject cmisObject = null; IFolder remoteFolder = null; IDocument remoteDocument = null; string remotePath = null; IFolder remoteParent = null; var changeIdForDebug = change.Properties.ContainsKey("cmis:name") ? change.Properties["cmis:name"][0] : change.Properties["cmis:objectId"][0]; // Get the remote changed object. try { cmisObject = getSession().GetObject(change.ObjectId); } catch (CmisObjectNotFoundException) { Logger.Info("Removed object, syncing might be needed: " + changeIdForDebug); return true; } catch (CmisRuntimeException e) { if (e.Message.Equals("Unauthorized")) { Logger.Info("We can not read the object id, so it is not an object we can sync anyway: " + changeIdForDebug); return false; } else { Logger.Info("A CMIS exception occured: " + changeIdForDebug + " :", e); return true; } } catch (Exception e) { Logger.Warn("An exception occurred: " + change.ObjectId + " :", e); return true; // Better be on the safe side and sync. } // Check whether change is about a document or folder. remoteDocument = cmisObject as IDocument; remoteFolder = cmisObject as IFolder; if (remoteDocument == null && remoteFolder == null) { Logger.Info("Ignore change as it is not about a document nor folder: " + changeIdForDebug); return false; } // Check whether it is a document worth syncing. if (remoteDocument != null) { if ( ! SyncUtils.IsFileWorthSyncing(remoteDocument.Name, SyncFolderInfo)) { Logger.Info("Ignore change as it is about a document unworth syncing: " + changeIdForDebug); return false; } if (remoteDocument.Paths.Count == 0) { Logger.Info("Ignore the unfiled object: " + changeIdForDebug); return false; } // TODO: Support Multiple Paths remotePath = remoteDocument.Paths[0]; remoteParent = remoteDocument.Parents[0]; } // Check whether it is a folder worth syncing. if (remoteFolder != null) { remotePath = remoteFolder.Path; remoteParent = remoteFolder.FolderParent; foreach (string name in remotePath.Split('/')) { if ( ! String.IsNullOrEmpty(name) && SyncUtils.IsInvalidFolderName(name)) { Logger.Info(String.Format("Ignore change as it is in a path unworth syncing: {0}: {1}", name, remotePath)); return false; } } } // Ignore the change if not in a synchronized folder. if ( ! remotePath.StartsWith(this.remoteFolderPath)) { Logger.Info("Ignore change as it is not in the synchronized folder's path: " + remotePath); return false; } if (this.SyncFolderInfo.isPathIgnored(remotePath)) { Logger.Info("Ignore change as it is in a path configured to be ignored: " + remotePath); return false; } string relativePath = remotePath.Substring(remoteFolderPath.Length); if (relativePath.Length <= 0) { Logger.Info("Ignore change as it is above the synchronized folder's path:: " + remotePath); return false; } Logger.Debug("Change is applicable:" + changeIdForDebug); return true; }
private void Sync() { // Get last change log token on server side. this.session.Binding.GetRepositoryService().GetRepositoryInfos(null); // refresh string lastTokenOnServer = this.session.Binding.GetRepositoryService().GetRepositoryInfo(this.session.RepositoryInfo.Id, null).LatestChangeLogToken; // Get last change token that had been saved on client side. string lastTokenOnClient = this.storage.ChangeLogToken; if (lastTokenOnClient == null) { // Token is null, which means no content change sync has ever happened yet, so just sync everything from remote. // Force full sync var fullsyncevent = new StartNextSyncEvent(true); Queue.AddEvent(fullsyncevent); return; } do { // Check which files/folders have changed. IChangeEvents changes = this.session.GetContentChanges(lastTokenOnClient, this.isPropertyChangesSupported, this.maxNumberOfContentChanges); // Replicate each change to the local side. bool first = true; foreach (IChangeEvent change in changes.ChangeEventList) { // ignore first event when lists overlapp if (first) { first = false; if (this.lastChange != null && (this.lastChange.ChangeType == DotCMIS.Enums.ChangeType.Created || this.lastChange.ChangeType == DotCMIS.Enums.ChangeType.Deleted)) { if (change != null && change.ChangeType == this.lastChange.ChangeType && change.ObjectId == this.lastChange.ObjectId) { continue; } } } this.lastChange = change; Queue.AddEvent(new ContentChangeEvent(change.ChangeType, change.ObjectId)); } // Save change log token locally. if (changes.HasMoreItems == true) { lastTokenOnClient = changes.LatestChangeLogToken; } else { lastTokenOnClient = lastTokenOnServer; } this.storage.ChangeLogToken = lastTokenOnClient; // refresh this.session.Binding.GetRepositoryService().GetRepositoryInfos(null); lastTokenOnServer = this.session.Binding.GetRepositoryService().GetRepositoryInfo(this.session.RepositoryInfo.Id, null).LatestChangeLogToken; } while (!lastTokenOnServer.Equals(lastTokenOnClient)); }
/// <summary> /// Apply a remote change. /// </summary> private void ApplyRemoteChange(IChangeEvent change) { Logger.Info("Sync | Change type:" + change.ChangeType.ToString() + " id:" + change.ObjectId + " properties:" + change.Properties); IFolder remoteFolder; IDocument remoteDocument; switch (change.ChangeType) { // Case when an object has been created or updated. case ChangeType.Created: case ChangeType.Updated: ICmisObject cmisObject = session.GetObject(change.ObjectId); if (null != (remoteDocument = cmisObject as IDocument)) { string remoteDocumentPath = remoteDocument.Paths.First(); if (!remoteDocumentPath.StartsWith(remoteFolderPath)) { Logger.Info("Sync | Change in unrelated document: " + remoteDocumentPath); break; // The change is not under the folder we care about. } string relativePath = remoteDocumentPath.Substring(remoteFolderPath.Length + 1); string relativeFolderPath = Path.GetDirectoryName(relativePath); relativeFolderPath = relativeFolderPath.Replace('/', '\\'); // TODO OS-specific separator string localFolderPath = Path.Combine(repoinfo.TargetDirectory, relativeFolderPath); DownloadFile(remoteDocument, localFolderPath); } else if (null != (remoteFolder = cmisObject as IFolder)) { string localFolder = Path.Combine(repoinfo.TargetDirectory, remoteFolder.Path); if(!this.repoinfo.isPathIgnored(remoteFolder.Path)) RecursiveFolderCopy(remoteFolder, localFolder); } break; // Case when an object has been deleted. case ChangeType.Deleted: cmisObject = session.GetObject(change.ObjectId); if (null != (remoteDocument = cmisObject as IDocument)) { string remoteDocumentPath = remoteDocument.Paths.First(); if (!remoteDocumentPath.StartsWith(remoteFolderPath)) { Logger.Info("Sync | Change in unrelated document: " + remoteDocumentPath); break; // The change is not under the folder we care about. } string relativePath = remoteDocumentPath.Substring(remoteFolderPath.Length + 1); string relativeFolderPath = Path.GetDirectoryName(relativePath); relativeFolderPath = relativeFolderPath.Replace('/', '\\'); // TODO OS-specific separator string localFolderPath = Path.Combine(repoinfo.TargetDirectory, relativeFolderPath); // TODO DeleteFile(localFolderPath); // Delete on filesystem and in database } else if (null != (remoteFolder = cmisObject as IFolder)) { string localFolder = Path.Combine(repoinfo.TargetDirectory, remoteFolder.Path); if(!this.repoinfo.isPathIgnored(remoteFolder.Path)) RemoveFolderLocally(localFolder); // Remove from filesystem and database. } break; // Case when access control or security policy has changed. case ChangeType.Security: // TODO break; } }